aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/adl/adl.cpp49
-rw-r--r--engines/adl/adl.h4
-rw-r--r--engines/adl/adl_v2.cpp9
-rw-r--r--engines/adl/adl_v2.h3
-rw-r--r--engines/adl/adl_v4.cpp84
-rw-r--r--engines/adl/adl_v4.h17
-rw-r--r--engines/adl/adl_v5.cpp220
-rw-r--r--engines/adl/adl_v5.h39
-rw-r--r--engines/adl/console.cpp3
-rw-r--r--engines/adl/detection.cpp23
-rw-r--r--engines/adl/display.cpp5
-rw-r--r--engines/adl/graphics.cpp60
-rw-r--r--engines/adl/graphics.h14
-rw-r--r--engines/adl/hires1.cpp2
-rw-r--r--engines/adl/hires6.cpp382
-rw-r--r--engines/adl/sound.cpp21
-rw-r--r--engines/agi/agi.cpp2
-rw-r--r--engines/agi/agi.h2
-rw-r--r--engines/agi/appleIIgs_timedelay_overwrite.h54
-rw-r--r--engines/agi/cycle.cpp17
-rw-r--r--engines/agi/keyboard.cpp35
-rw-r--r--engines/agi/picture.h2
-rw-r--r--engines/cryo/configure.engine3
-rw-r--r--engines/cryo/cryo.cpp85
-rw-r--r--engines/cryo/cryo.h100
-rw-r--r--engines/cryo/cryolib.cpp433
-rw-r--r--engines/cryo/cryolib.h175
-rw-r--r--engines/cryo/debugger.cpp64
-rw-r--r--engines/cryo/debugger.h (renamed from engines/titanic/sound/music_wave.cpp)42
-rw-r--r--engines/cryo/defs.h816
-rw-r--r--engines/cryo/detection.cpp166
-rw-r--r--engines/cryo/eden.cpp7802
-rw-r--r--engines/cryo/eden.h774
-rw-r--r--engines/cryo/graphics.cpp1208
-rw-r--r--engines/cryo/module.mk20
-rw-r--r--engines/cryo/platdefs.h43
-rw-r--r--engines/cryo/resource.cpp555
-rw-r--r--engines/cryo/sound.cpp113
-rw-r--r--engines/cryo/sound.h70
-rw-r--r--engines/cryo/video.cpp617
-rw-r--r--engines/cryo/video.h106
-rw-r--r--engines/director/archive.cpp7
-rw-r--r--engines/director/cast.cpp19
-rw-r--r--engines/director/detection.cpp1
-rw-r--r--engines/director/detection_tables.h31
-rw-r--r--engines/director/director.cpp93
-rw-r--r--engines/director/director.h14
-rw-r--r--engines/director/frame.cpp158
-rw-r--r--engines/director/frame.h2
-rw-r--r--engines/director/graphics.cpp148
-rw-r--r--engines/director/images.cpp8
-rw-r--r--engines/director/lingo/lingo-builtins.cpp771
-rw-r--r--engines/director/lingo/lingo-code.cpp100
-rw-r--r--engines/director/lingo/lingo-codegen.cpp39
-rw-r--r--engines/director/lingo/lingo-funcs.cpp88
-rw-r--r--engines/director/lingo/lingo-gr.cpp2202
-rw-r--r--engines/director/lingo/lingo-gr.h300
-rw-r--r--engines/director/lingo/lingo-gr.y136
-rw-r--r--engines/director/lingo/lingo-lex.cpp850
-rw-r--r--engines/director/lingo/lingo-lex.l121
-rw-r--r--engines/director/lingo/lingo-the.cpp161
-rw-r--r--engines/director/lingo/lingo-the.h64
-rw-r--r--engines/director/lingo/lingo.cpp44
-rw-r--r--engines/director/lingo/lingo.h49
-rw-r--r--engines/director/lingo/tests/builtin.lingo6
-rw-r--r--engines/director/score.cpp221
-rw-r--r--engines/director/score.h8
-rw-r--r--engines/dm/champion.cpp68
-rw-r--r--engines/dm/champion.h10
-rw-r--r--engines/dm/console.cpp4
-rw-r--r--engines/dm/dm.cpp31
-rw-r--r--engines/dm/dm.h31
-rw-r--r--engines/dm/dungeonman.cpp90
-rw-r--r--engines/dm/eventman.cpp18
-rw-r--r--engines/dm/gfx.cpp16
-rw-r--r--engines/dm/group.cpp72
-rw-r--r--engines/dm/inventory.cpp28
-rw-r--r--engines/dm/loadsave.cpp2
-rw-r--r--engines/dm/menus.cpp44
-rw-r--r--engines/dm/movesens.cpp74
-rw-r--r--engines/dm/objectman.cpp2
-rw-r--r--engines/dm/projexpl.cpp70
-rw-r--r--engines/dm/timeline.cpp48
-rw-r--r--engines/drascula/detection.cpp30
-rw-r--r--engines/drascula/drascula.h4
-rw-r--r--engines/drascula/graphics.cpp5
-rw-r--r--engines/drascula/sound.cpp88
-rw-r--r--engines/dreamweb/detection_tables.h18
-rw-r--r--engines/sci/console.cpp2
-rw-r--r--engines/sci/engine/file.cpp2
-rw-r--r--engines/sci/engine/kfile.cpp4
-rw-r--r--engines/sci/engine/kgraphics.cpp15
-rw-r--r--engines/sci/engine/kstring.cpp2
-rw-r--r--engines/sci/engine/message.cpp40
-rw-r--r--engines/sci/engine/message.h5
-rw-r--r--engines/sci/engine/savegame.cpp3
-rw-r--r--engines/sci/engine/scriptdebug.cpp8
-rw-r--r--engines/sci/engine/seg_manager.cpp21
-rw-r--r--engines/sci/engine/segment.h6
-rw-r--r--engines/sci/graphics/controls16.cpp11
-rw-r--r--engines/sci/graphics/controls16.h4
-rw-r--r--engines/sci/graphics/text16.cpp27
-rw-r--r--engines/sci/graphics/text16.h10
-rw-r--r--engines/sci/parser/vocabulary.cpp33
-rw-r--r--engines/sci/resource.cpp2
-rw-r--r--engines/scumm/actor.cpp7
-rw-r--r--engines/scumm/script_v2.cpp54
-rw-r--r--engines/sword25/util/lua_unpersist.cpp16
-rw-r--r--engines/titanic/carry/arm.cpp108
-rw-r--r--engines/titanic/carry/arm.h12
-rw-r--r--engines/titanic/carry/brain.cpp64
-rw-r--r--engines/titanic/carry/brain.h4
-rw-r--r--engines/titanic/carry/carry.cpp63
-rw-r--r--engines/titanic/carry/carry.h20
-rw-r--r--engines/titanic/carry/carry_parrot.cpp6
-rw-r--r--engines/titanic/carry/ear.cpp6
-rw-r--r--engines/titanic/carry/head_piece.cpp2
-rw-r--r--engines/titanic/carry/magazine.cpp28
-rw-r--r--engines/titanic/carry/mouth.cpp2
-rw-r--r--engines/titanic/carry/phonograph_cylinder.cpp13
-rw-r--r--engines/titanic/carry/phonograph_cylinder.h16
-rw-r--r--engines/titanic/carry/phonograph_ear.cpp9
-rw-r--r--engines/titanic/carry/phonograph_ear.h4
-rw-r--r--engines/titanic/core/background.cpp2
-rw-r--r--engines/titanic/core/game_object.cpp87
-rw-r--r--engines/titanic/core/game_object.h54
-rw-r--r--engines/titanic/core/saveable_object.cpp2
-rw-r--r--engines/titanic/core/tree_item.cpp2
-rw-r--r--engines/titanic/core/turn_on_turn_off.cpp4
-rw-r--r--engines/titanic/core/view_item.cpp2
-rw-r--r--engines/titanic/game/arboretum_gate.cpp26
-rw-r--r--engines/titanic/game/bomb.cpp153
-rw-r--r--engines/titanic/game/bomb.h12
-rw-r--r--engines/titanic/game/brain_slot.cpp32
-rw-r--r--engines/titanic/game/brain_slot.h6
-rw-r--r--engines/titanic/game/bridge_view.cpp24
-rw-r--r--engines/titanic/game/bridge_view.h8
-rw-r--r--engines/titanic/game/captains_wheel.cpp72
-rw-r--r--engines/titanic/game/captains_wheel.h8
-rw-r--r--engines/titanic/game/cdrom.cpp10
-rw-r--r--engines/titanic/game/cdrom.h2
-rw-r--r--engines/titanic/game/chicken_dispensor.cpp6
-rw-r--r--engines/titanic/game/code_wheel.cpp70
-rw-r--r--engines/titanic/game/code_wheel.h12
-rw-r--r--engines/titanic/game/computer_screen.cpp6
-rw-r--r--engines/titanic/game/end_explode_ship.cpp16
-rw-r--r--engines/titanic/game/end_explode_ship.h5
-rw-r--r--engines/titanic/game/end_game_credits.cpp3
-rw-r--r--engines/titanic/game/end_sequence_control.cpp2
-rw-r--r--engines/titanic/game/fan_control.cpp2
-rw-r--r--engines/titanic/game/games_console.cpp2
-rw-r--r--engines/titanic/game/glass_smasher.cpp2
-rw-r--r--engines/titanic/game/gondolier/gondolier_base.cpp30
-rw-r--r--engines/titanic/game/gondolier/gondolier_base.h10
-rw-r--r--engines/titanic/game/gondolier/gondolier_chest.cpp8
-rw-r--r--engines/titanic/game/gondolier/gondolier_mixer.cpp6
-rw-r--r--engines/titanic/game/gondolier/gondolier_slider.cpp165
-rw-r--r--engines/titanic/game/gondolier/gondolier_slider.h21
-rw-r--r--engines/titanic/game/hammer_dispensor.cpp4
-rw-r--r--engines/titanic/game/head_slot.cpp129
-rw-r--r--engines/titanic/game/head_slot.h20
-rw-r--r--engines/titanic/game/head_smash_event.cpp2
-rw-r--r--engines/titanic/game/long_stick_dispenser.cpp4
-rw-r--r--engines/titanic/game/music_console_button.cpp40
-rw-r--r--engines/titanic/game/music_room_stop_phonograph_button.cpp2
-rw-r--r--engines/titanic/game/nut_replacer.cpp2
-rw-r--r--engines/titanic/game/parrot/parrot_nut_eater.cpp2
-rw-r--r--engines/titanic/game/phonograph.cpp84
-rw-r--r--engines/titanic/game/phonograph.h14
-rw-r--r--engines/titanic/game/phonograph_lid.cpp2
-rw-r--r--engines/titanic/game/play_music_button.cpp4
-rw-r--r--engines/titanic/game/play_on_act.cpp2
-rw-r--r--engines/titanic/game/port_hole.cpp2
-rw-r--r--engines/titanic/game/record_phonograph_button.cpp2
-rw-r--r--engines/titanic/game/replacement_ear.cpp2
-rw-r--r--engines/titanic/game/restaurant_cylinder_holder.cpp28
-rw-r--r--engines/titanic/game/restaurant_cylinder_holder.h2
-rw-r--r--engines/titanic/game/restaurant_phonograph.cpp60
-rw-r--r--engines/titanic/game/restaurant_phonograph.h4
-rw-r--r--engines/titanic/game/season_background.cpp14
-rw-r--r--engines/titanic/game/sgt/armchair.cpp4
-rw-r--r--engines/titanic/game/sgt/basin.cpp4
-rw-r--r--engines/titanic/game/sgt/bedfoot.cpp10
-rw-r--r--engines/titanic/game/sgt/bedhead.cpp4
-rw-r--r--engines/titanic/game/sgt/chest_of_drawers.cpp4
-rw-r--r--engines/titanic/game/sgt/desk.cpp4
-rw-r--r--engines/titanic/game/sgt/deskchair.cpp4
-rw-r--r--engines/titanic/game/sgt/drawer.cpp4
-rw-r--r--engines/titanic/game/sgt/sgt_doors.cpp8
-rw-r--r--engines/titanic/game/sgt/sgt_navigation.cpp4
-rw-r--r--engines/titanic/game/sgt/sgt_tv.cpp4
-rw-r--r--engines/titanic/game/sgt/toilet.cpp4
-rw-r--r--engines/titanic/game/sgt/vase.cpp4
-rw-r--r--engines/titanic/game/sgt/washstand.cpp4
-rw-r--r--engines/titanic/game/starling_puret.cpp2
-rw-r--r--engines/titanic/game/sub_glass.cpp2
-rw-r--r--engines/titanic/game/sweet_bowl.cpp2
-rw-r--r--engines/titanic/game/throw_tv_down_well.cpp2
-rw-r--r--engines/titanic/game/transport/lift.cpp32
-rw-r--r--engines/titanic/game/transport/pellerator.cpp34
-rw-r--r--engines/titanic/game/wheel_button.cpp18
-rw-r--r--engines/titanic/game/wheel_button.h4
-rw-r--r--engines/titanic/game/wheel_hotspot.cpp22
-rw-r--r--engines/titanic/game/wheel_hotspot.h10
-rw-r--r--engines/titanic/game/wheel_spin_horn.cpp27
-rw-r--r--engines/titanic/game/wheel_spin_horn.h6
-rw-r--r--engines/titanic/game_manager.cpp2
-rw-r--r--engines/titanic/game_state.cpp12
-rw-r--r--engines/titanic/game_state.h18
-rw-r--r--engines/titanic/gfx/music_control.cpp8
-rw-r--r--engines/titanic/gfx/music_control.h4
-rw-r--r--engines/titanic/gfx/music_slider_pitch.cpp2
-rw-r--r--engines/titanic/gfx/music_slider_speed.cpp2
-rw-r--r--engines/titanic/gfx/music_switch_inversion.cpp2
-rw-r--r--engines/titanic/gfx/music_switch_reverse.cpp3
-rw-r--r--engines/titanic/gfx/toggle_switch.cpp4
-rw-r--r--engines/titanic/messages/messages.h9
-rw-r--r--engines/titanic/module.mk6
-rw-r--r--engines/titanic/moves/enter_bridge.cpp2
-rw-r--r--engines/titanic/moves/enter_sec_class_state.cpp4
-rw-r--r--engines/titanic/npcs/barbot.cpp156
-rw-r--r--engines/titanic/npcs/barbot.h28
-rw-r--r--engines/titanic/npcs/bellbot.cpp10
-rw-r--r--engines/titanic/npcs/bilge_succubus.cpp26
-rw-r--r--engines/titanic/npcs/deskbot.cpp2
-rw-r--r--engines/titanic/npcs/doorbot.cpp10
-rw-r--r--engines/titanic/npcs/maitre_d.cpp91
-rw-r--r--engines/titanic/npcs/maitre_d.h19
-rw-r--r--engines/titanic/npcs/parrot.cpp14
-rw-r--r--engines/titanic/npcs/parrot.h1
-rw-r--r--engines/titanic/npcs/succubus.cpp4
-rw-r--r--engines/titanic/npcs/titania.cpp17
-rw-r--r--engines/titanic/npcs/titania.h2
-rw-r--r--engines/titanic/sound/audio_buffer.cpp78
-rw-r--r--engines/titanic/sound/audio_buffer.h100
-rw-r--r--engines/titanic/sound/music_player.cpp79
-rw-r--r--engines/titanic/sound/music_player.h6
-rw-r--r--engines/titanic/sound/music_room.cpp48
-rw-r--r--engines/titanic/sound/music_room.h55
-rw-r--r--engines/titanic/sound/music_room_handler.cpp319
-rw-r--r--engines/titanic/sound/music_room_handler.h166
-rw-r--r--engines/titanic/sound/music_room_instrument.cpp353
-rw-r--r--engines/titanic/sound/music_room_instrument.h142
-rw-r--r--engines/titanic/sound/music_song.cpp192
-rw-r--r--engines/titanic/sound/music_song.h (renamed from engines/titanic/sound/music_wave.h)69
-rw-r--r--engines/titanic/sound/qmixer.cpp6
-rw-r--r--engines/titanic/sound/sound_manager.cpp12
-rw-r--r--engines/titanic/sound/sound_manager.h27
-rw-r--r--engines/titanic/sound/titania_speech.cpp38
-rw-r--r--engines/titanic/sound/titania_speech.h5
-rw-r--r--engines/titanic/sound/wave_file.cpp160
-rw-r--r--engines/titanic/sound/wave_file.h58
-rw-r--r--engines/titanic/star_control/star_control.cpp4
-rw-r--r--engines/titanic/star_control/star_control.h6
-rw-r--r--engines/titanic/star_control/star_field.cpp14
-rw-r--r--engines/titanic/star_control/star_field.h14
-rw-r--r--engines/titanic/support/avi_surface.cpp11
-rw-r--r--engines/titanic/support/avi_surface.h7
-rw-r--r--engines/titanic/support/files_manager.cpp2
-rw-r--r--engines/titanic/titanic.cpp2
-rw-r--r--engines/titanic/true_talk/barbot_script.cpp43
-rw-r--r--engines/titanic/true_talk/tt_npc_script.cpp8
-rw-r--r--engines/titanic/true_talk/tt_npc_script.h2
-rw-r--r--engines/titanic/true_talk/tt_parser.cpp8
-rw-r--r--engines/titanic/true_talk/tt_parser.h2
-rw-r--r--engines/titanic/true_talk/tt_title_script.cpp3
-rw-r--r--engines/titanic/true_talk/tt_title_script.h5
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp19
268 files changed, 20603 insertions, 4704 deletions
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 33124a2ea4..58d5fa9e67 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -55,10 +55,11 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
_dumpFile(nullptr),
_display(nullptr),
_graphics(nullptr),
+ _textMode(false),
_isRestarting(false),
_isRestoring(false),
_isQuitting(false),
- _skipOneCommand(false),
+ _abortScript(false),
_gameDescription(gd),
_console(nullptr),
_messageIds(),
@@ -446,16 +447,13 @@ void AdlEngine::loadDroppedItemOffsets(Common::ReadStream &stream, byte count) {
}
}
-void AdlEngine::clearScreen() const {
- _display->setMode(DISPLAY_MODE_MIXED);
- _display->clear(0x00);
-}
-
void AdlEngine::drawPic(byte pic, Common::Point pos) const {
if (_roomData.pictures.contains(pic))
_graphics->drawPic(*_roomData.pictures[pic]->createReadStream(), pos);
- else
+ else if (_pictures.contains(pic))
_graphics->drawPic(*_pictures[pic]->createReadStream(), pos);
+ else
+ error("Picture %d not found", pic);
}
void AdlEngine::bell(uint count) const {
@@ -914,10 +912,6 @@ byte AdlEngine::convertKey(uint16 ascii) const {
}
Common::String AdlEngine::getLine() {
- // Original engine uses a global here, which isn't reset between
- // calls and may not match actual mode
- bool textMode = false;
-
while (1) {
Common::String line = inputString(APPLECHAR('?'));
@@ -925,8 +919,8 @@ Common::String AdlEngine::getLine() {
return "";
if ((byte)line[0] == ('\r' | 0x80)) {
- textMode = !textMode;
- _display->setMode(textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
+ _textMode = !_textMode;
+ _display->setMode(_textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
continue;
}
@@ -1077,7 +1071,7 @@ int AdlEngine::o1_isItemPicEQ(ScriptEnv &e) {
int AdlEngine::o1_varAdd(ScriptEnv &e) {
OP_DEBUG_2("\tVARS[%d] += %d", e.arg(2), e.arg(1));
- setVar(e.arg(2), getVar(e.arg(2) + e.arg(1)));
+ setVar(e.arg(2), getVar(e.arg(2)) + e.arg(1));
return 2;
}
@@ -1240,8 +1234,7 @@ int AdlEngine::o1_goDirection(ScriptEnv &e) {
return -1;
}
- getCurRoom().curPicture = getCurRoom().picture;
- _state.room = room;
+ switchRoom(room);
return -1;
}
@@ -1324,20 +1317,18 @@ bool AdlEngine::doOneCommand(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
-
- if (_skipOneCommand) {
- _skipOneCommand = false;
- continue;
- }
-
ScriptEnv env(*cmd, _state.room, verb, noun);
if (matchCommand(env)) {
doActions(env);
return true;
}
+
+ if (_abortScript) {
+ _abortScript = false;
+ return false;
+ }
}
- _skipOneCommand = false;
return false;
}
@@ -1345,11 +1336,6 @@ void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
Commands::const_iterator cmd;
for (cmd = commands.begin(); cmd != commands.end(); ++cmd) {
- if (_skipOneCommand) {
- _skipOneCommand = false;
- continue;
- }
-
ScriptEnv env(*cmd, _state.room, verb, noun);
if (matchCommand(env)) {
doActions(env);
@@ -1357,9 +1343,12 @@ void AdlEngine::doAllCommands(const Commands &commands, byte verb, byte noun) {
if (_isRestarting)
return;
}
- }
- _skipOneCommand = false;
+ if (_abortScript) {
+ _abortScript = false;
+ return;
+ }
+ }
}
Common::String AdlEngine::toAscii(const Common::String &str) {
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 3f26636234..d71d40816e 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -309,7 +309,6 @@ protected:
int o1_setRoomPic(ScriptEnv &e);
// Graphics
- void clearScreen() const;
void drawPic(byte pic, Common::Point pos = Common::Point()) const;
// Sound
@@ -349,6 +348,7 @@ protected:
Display *_display;
GraphicsMan *_graphics;
+ bool _textMode;
// Opcodes
typedef Common::Functor1<ScriptEnv &, int> Opcode;
@@ -392,7 +392,7 @@ protected:
bool _isRestarting, _isRestoring, _isQuitting;
bool _canSaveNow, _canRestoreNow;
- bool _skipOneCommand;
+ bool _abortScript;
const AdlGameDescription *_gameDescription;
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index e78366ff63..272e7801e7 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -37,6 +37,7 @@ AdlEngine_v2::~AdlEngine_v2() {
AdlEngine_v2::AdlEngine_v2(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd),
_linesPrinted(0),
+ _maxLines(4),
_disk(nullptr),
_itemRemoved(false),
_roomOnScreen(0),
@@ -151,9 +152,11 @@ void AdlEngine_v2::checkTextOverflow(char c) {
++_linesPrinted;
- if (_linesPrinted < 4)
- return;
+ if (_linesPrinted >= _maxLines)
+ handleTextOverflow();
+}
+void AdlEngine_v2::handleTextOverflow() {
_linesPrinted = 0;
_display->updateTextScreen();
bell();
@@ -255,7 +258,7 @@ void AdlEngine_v2::showRoom() {
if (_state.room != _roomOnScreen) {
loadRoom(_state.room);
- clearScreen();
+ _graphics->clearScreen();
if (!_state.isDark)
redrawPic = true;
diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h
index f0af9eba22..5447974a2e 100644
--- a/engines/adl/adl_v2.h
+++ b/engines/adl/adl_v2.h
@@ -62,6 +62,7 @@ protected:
int askForSlot(const Common::String &question);
void checkTextOverflow(char c);
+ void handleTextOverflow();
int o2_isFirstTime(ScriptEnv &e);
int o2_isRandomGT(ScriptEnv &e);
@@ -85,7 +86,7 @@ protected:
Common::String restoreInsert, restoreReplace;
} _strings_v2;
- uint _linesPrinted;
+ uint _linesPrinted, _maxLines;
DiskImage *_disk;
Common::Array<DataBlockPtr> _itemPics;
bool _itemRemoved;
diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp
index dcf0f997c9..e8ee798199 100644
--- a/engines/adl/adl_v4.cpp
+++ b/engines/adl/adl_v4.cpp
@@ -127,7 +127,7 @@ void AdlEngine_v4::loadState(Common::ReadStream &stream) {
if (size != expectedSize)
error("Variable count mismatch (expected %i; found %i)", expectedSize, size);
- for (uint i = getRegion(1).vars.size(); i < size; ++i)
+ for (uint i = getRegion(1).vars.size(); i < _state.vars.size(); ++i)
_state.vars[i] = stream.readByte();
if (stream.err() || stream.eos())
@@ -139,6 +139,7 @@ void AdlEngine_v4::loadState(Common::ReadStream &stream) {
}
void AdlEngine_v4::saveState(Common::WriteStream &stream) {
+ getCurRoom().isFirstTime = false;
backupVars();
backupRoomState(_state.room);
@@ -189,24 +190,23 @@ Common::String AdlEngine_v4::getItemDescription(const Item &item) const {
return _itemDesc[item.id - 1];
}
-DiskImage *AdlEngine_v4::loadDisk(byte volume) const {
+Common::String AdlEngine_v4::getDiskImageName(byte volume) const {
const ADGameFileDescription *ag;
- for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++) {
- if (ag->fileType == volume) {
- DiskImage *disk = new DiskImage();
- if (!disk->open(ag->fileName))
- error("Failed to open %s", ag->fileName);
- return disk;
- }
- }
+ for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++)
+ if (ag->fileType == volume)
+ return ag->fileName;
error("Disk volume %d not found", volume);
}
void AdlEngine_v4::insertDisk(byte volume) {
delete _disk;
- _disk = loadDisk(volume);
+ _disk = new DiskImage();
+
+ if (!_disk->open(getDiskImageName(volume)))
+ error("Failed to open disk volume %d", volume);
+
_currentVolume = volume;
}
@@ -238,6 +238,11 @@ void AdlEngine_v4::loadRegionInitDataOffsets(Common::ReadStream &stream, uint re
}
}
+void AdlEngine_v4::initRoomState(RoomState &roomState) const {
+ roomState.picture = 1;
+ roomState.isFirstTime = 1;
+}
+
void AdlEngine_v4::initRegions(const byte *roomsPerRegion, uint regions) {
_state.regions.resize(regions);
@@ -247,12 +252,8 @@ void AdlEngine_v4::initRegions(const byte *roomsPerRegion, uint regions) {
regn.vars.resize(24);
regn.rooms.resize(roomsPerRegion[r]);
- for (uint rm = 0; rm < roomsPerRegion[r]; ++rm) {
- // TODO: hires6 uses 0xff and has slightly different
- // code working on these values
- regn.rooms[rm].picture = 1;
- regn.rooms[rm].isFirstTime = 1;
- }
+ for (uint rm = 0; rm < roomsPerRegion[r]; ++rm)
+ initRoomState(regn.rooms[rm]);
}
}
@@ -273,6 +274,27 @@ void AdlEngine_v4::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, b
fixupDiskOffset(track, sector);
}
+AdlEngine_v4::RegionChunkType AdlEngine_v4::getRegionChunkType(const uint16 addr) const {
+ switch (addr) {
+ case 0x9000:
+ return kRegionChunkMessages;
+ case 0x4a80:
+ return kRegionChunkGlobalPics;
+ case 0x4000:
+ return kRegionChunkVerbs;
+ case 0x1800:
+ return kRegionChunkNouns;
+ case 0x0e00:
+ return kRegionChunkRooms;
+ case 0x7b00:
+ return kRegionChunkRoomCmds;
+ case 0x9500:
+ return kRegionChunkGlobalCmds;
+ default:
+ return kRegionChunkUnknown;
+ }
+}
+
void AdlEngine_v4::loadRegion(byte region) {
if (_currentVolume != _regionInitDataOffsets[region - 1].volume) {
insertDisk(_regionInitDataOffsets[region - 1].volume);
@@ -302,29 +324,29 @@ void AdlEngine_v4::loadRegion(byte region) {
stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1));
stream->skip(4);
- switch (addr) {
- case 0x9000: {
+ switch (getRegionChunkType(addr)) {
+ case kRegionChunkMessages: {
// Messages
_messages.clear();
uint count = size / 4;
loadMessages(*stream, count);
break;
}
- case 0x4a80: {
+ case kRegionChunkGlobalPics: {
// Global pics
_pictures.clear();
loadPictures(*stream);
break;
}
- case 0x4000:
+ case kRegionChunkVerbs:
// Verbs
loadWords(*stream, _verbs, _priVerbs);
break;
- case 0x1800:
+ case kRegionChunkNouns:
// Nouns
loadWords(*stream, _nouns, _priNouns);
break;
- case 0x0e00: {
+ case kRegionChunkRooms: {
// Rooms
uint count = size / 14 - 1;
stream->skip(14); // Skip invalid room 0
@@ -333,12 +355,11 @@ void AdlEngine_v4::loadRegion(byte region) {
loadRooms(*stream, count);
break;
}
- case 0x7b00:
- // TODO: hires6 has global and room lists swapped
+ case kRegionChunkRoomCmds:
// Room commands
readCommands(*stream, _roomCommands);
break;
- case 0x9500:
+ case kRegionChunkGlobalCmds:
// Global commands
readCommands(*stream, _globalCommands);
break;
@@ -375,11 +396,16 @@ void AdlEngine_v4::backupRoomState(byte room) {
backup.picture = getRoom(room).picture;
}
-void AdlEngine_v4::restoreRoomState(byte room) {
+byte AdlEngine_v4::restoreRoomState(byte room) {
const RoomState &backup = getCurRegion().rooms[room - 1];
- getRoom(room).isFirstTime = backup.isFirstTime;
- getRoom(room).picture = backup.picture;
+ if (backup.isFirstTime != 1) {
+ getRoom(room).curPicture = getRoom(room).picture = backup.picture;
+ getRoom(room).isFirstTime = false;
+ return 0;
+ }
+
+ return 1;
}
void AdlEngine_v4::backupVars() {
diff --git a/engines/adl/adl_v4.h b/engines/adl/adl_v4.h
index 4e87530673..ca9aeff492 100644
--- a/engines/adl/adl_v4.h
+++ b/engines/adl/adl_v4.h
@@ -60,16 +60,29 @@ protected:
// AdlEngine_v2
virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
- DiskImage *loadDisk(byte volume) const;
+ enum RegionChunkType {
+ kRegionChunkUnknown,
+ kRegionChunkMessages,
+ kRegionChunkGlobalPics,
+ kRegionChunkVerbs,
+ kRegionChunkNouns,
+ kRegionChunkRooms,
+ kRegionChunkRoomCmds,
+ kRegionChunkGlobalCmds
+ };
+
+ Common::String getDiskImageName(byte volume) const;
void insertDisk(byte volume);
void loadRegionLocations(Common::ReadStream &stream, uint regions);
void loadRegionInitDataOffsets(Common::ReadStream &stream, uint regions);
void initRegions(const byte *roomsPerRegion, uint regions);
void fixupDiskOffset(byte &track, byte &sector) const;
+ virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
void loadRegion(byte region);
void loadItemPicIndex(Common::ReadStream &stream, uint items);
void backupRoomState(byte room);
- void restoreRoomState(byte room);
+ virtual void initRoomState(RoomState &roomState) const;
+ virtual byte restoreRoomState(byte room);
void backupVars();
void restoreVars();
diff --git a/engines/adl/adl_v5.cpp b/engines/adl/adl_v5.cpp
index 7e7c6e40ac..929ffff7f4 100644
--- a/engines/adl/adl_v5.cpp
+++ b/engines/adl/adl_v5.cpp
@@ -30,139 +30,39 @@
namespace Adl {
AdlEngine_v5::AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd) :
- AdlEngine_v3(syst, gd),
- _curDisk(0) {
+ AdlEngine_v4(syst, gd) {
}
-Common::String AdlEngine_v5::loadMessage(uint idx) const {
- Common::String str = AdlEngine_v2::loadMessage(idx);
-
- for (uint i = 0; i < str.size(); ++i) {
- const char *xorStr = "AVISDURGAN";
- str.setChar(str[i] ^ xorStr[i % strlen(xorStr)], i);
- }
-
- return str;
-}
-
-Common::String AdlEngine_v5::getItemDescription(const Item &item) const {
- return _itemDesc[item.id - 1];
-}
-
-void AdlEngine_v5::applyDiskOffset(byte &track, byte &sector) const {
- sector += _diskOffsets[_curDisk].sector;
- if (sector >= 16) {
- sector -= 16;
- ++track;
- }
-
- track += _diskOffsets[_curDisk].track;
-}
-
-void AdlEngine_v5::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const {
- applyDiskOffset(track, sector);
+void AdlEngine_v5::initRoomState(RoomState &roomState) const {
+ roomState.picture = 0xff;
+ roomState.isFirstTime = 0xff;
}
-typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v5> OpcodeV4;
-#define SetOpcodeTable(x) table = &x;
-#define Opcode(x) table->push_back(new OpcodeV4(this, &AdlEngine_v5::x))
-#define OpcodeUnImpl() table->push_back(new OpcodeV4(this, 0))
-
-void AdlEngine_v5::setupOpcodeTables() {
- Common::Array<const Opcode *> *table = 0;
-
- SetOpcodeTable(_condOpcodes);
- // 0x00
- OpcodeUnImpl();
- Opcode(o2_isFirstTime);
- Opcode(o2_isRandomGT);
- Opcode(o5_isItemInRoom);
- // 0x04
- Opcode(o5_isNounNotInRoom);
- Opcode(o1_isMovesGT);
- Opcode(o1_isVarEQ);
- Opcode(o2_isCarryingSomething);
- // 0x08
- Opcode(o5_isVarGT);
- Opcode(o1_isCurPicEQ);
- Opcode(o5_skipOneCommand);
-
- SetOpcodeTable(_actOpcodes);
- // 0x00
- OpcodeUnImpl();
- Opcode(o1_varAdd);
- Opcode(o1_varSub);
- Opcode(o1_varSet);
- // 0x04
- Opcode(o1_listInv);
- Opcode(o5_moveItem);
- Opcode(o1_setRoom);
- Opcode(o2_setCurPic);
- // 0x08
- Opcode(o2_setPic);
- Opcode(o1_printMsg);
- Opcode(o5_dummy);
- Opcode(o5_setTextMode);
- // 0x0c
- Opcode(o2_moveAllItems);
- Opcode(o1_quit);
- Opcode(o5_dummy);
- Opcode(o2_save);
- // 0x10
- Opcode(o2_restore);
- Opcode(o1_restart);
- Opcode(o5_setDisk);
- Opcode(o5_dummy);
- // 0x14
- Opcode(o1_resetPic);
- Opcode(o1_goDirection<IDI_DIR_NORTH>);
- Opcode(o1_goDirection<IDI_DIR_SOUTH>);
- Opcode(o1_goDirection<IDI_DIR_EAST>);
- // 0x18
- Opcode(o1_goDirection<IDI_DIR_WEST>);
- Opcode(o1_goDirection<IDI_DIR_UP>);
- Opcode(o1_goDirection<IDI_DIR_DOWN>);
- Opcode(o1_takeItem);
- // 0x1c
- Opcode(o1_dropItem);
- Opcode(o1_setRoomPic);
- Opcode(o5_sound);
- OpcodeUnImpl();
- // 0x20
- Opcode(o2_initDisk);
-}
-
-int AdlEngine_v5::o5_isVarGT(ScriptEnv &e) {
- OP_DEBUG_2("\t&& VARS[%d] > %d", e.arg(1), e.arg(2));
-
- if (getVar(e.arg(1)) > e.arg(2))
- return 2;
-
- return -1;
-}
+byte AdlEngine_v5::restoreRoomState(byte room) {
+ const RoomState &backup = getCurRegion().rooms[room - 1];
-int AdlEngine_v5::o5_skipOneCommand(ScriptEnv &e) {
- OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()");
+ if (backup.isFirstTime != 0xff) {
+ getRoom(room).curPicture = getRoom(room).picture = backup.picture;
- _skipOneCommand = true;
- setVar(2, 0);
+ // CHECKME: Why doesn't this just copy the flag unconditionally?
+ if (backup.isFirstTime != 1) {
+ getRoom(room).isFirstTime = false;
+ return 0;
+ }
+ }
- return -1;
+ return backup.isFirstTime;
}
-// FIXME: Rename "isLineArt" and look at code duplication
-int AdlEngine_v5::o5_isItemInRoom(ScriptEnv &e) {
- OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str());
-
- const Item &item = getItem(e.arg(1));
-
- if (e.arg(2) != IDI_ANY && item.isLineArt != _curDisk)
- return -1;
-
- if (item.room == roomArg(e.arg(2)))
- return 2;
-
- return -1;
+AdlEngine_v5::RegionChunkType AdlEngine_v5::getRegionChunkType(const uint16 addr) const {
+ switch (addr) {
+ case 0x7b00:
+ return kRegionChunkGlobalCmds;
+ case 0x9500:
+ return kRegionChunkRoomCmds;
+ default:
+ return AdlEngine_v4::getRegionChunkType(addr);
+ }
}
int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) {
@@ -183,23 +83,13 @@ int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) {
return 1;
}
-int AdlEngine_v5::o5_moveItem(ScriptEnv &e) {
- OP_DEBUG_2("\tSET_ITEM_ROOM(%s, %s)", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str());
+int AdlEngine_v5::o5_abortScript(ScriptEnv &e) {
+ OP_DEBUG_0("\t&& ABORT_SCRIPT()");
- byte room = roomArg(e.arg(2));
-
- Item &item = getItem(e.arg(1));
-
- if (item.room == _roomOnScreen)
- _picOnScreen = 0;
-
- // Set items that move from inventory to a room to state "dropped"
- if (item.room == IDI_ANY && room != IDI_VOID_ROOM)
- item.state = IDI_ITEM_DROPPED;
+ _abortScript = true;
+ setVar(2, 0);
- item.room = room;
- item.isLineArt = _curDisk;
- return 2;
+ return -1;
}
int AdlEngine_v5::o5_dummy(ScriptEnv &e) {
@@ -211,36 +101,54 @@ int AdlEngine_v5::o5_dummy(ScriptEnv &e) {
int AdlEngine_v5::o5_setTextMode(ScriptEnv &e) {
OP_DEBUG_1("\tSET_TEXT_MODE(%d)", e.arg(1));
- // TODO
- // 1: 4-line mode
- // 2: 24-line mode
-
switch (e.arg(1)) {
+ case 1:
+ if (_linesPrinted != 0) {
+ _display->printChar(APPLECHAR(' '));
+ handleTextOverflow();
+ _display->moveCursorTo(Common::Point(0, 23));
+ _maxLines = 4;
+ }
+ return 1;
+ case 2:
+ _textMode = true;
+ _display->setMode(DISPLAY_MODE_TEXT);
+ _display->home();
+ _maxLines = 24;
+ _linesPrinted = 0;
+ return 1;
case 3:
// We re-use the restarting flag here, to simulate a long jump
_isRestarting = true;
return -1;
+ default:
+ error("Invalid text mode %d", e.arg(1));
}
-
- return 1;
}
-int AdlEngine_v5::o5_setDisk(ScriptEnv &e) {
- OP_DEBUG_2("\tSET_DISK(%d, %d)", e.arg(1), e.arg(2));
+int AdlEngine_v5::o5_setRegionRoom(ScriptEnv &e) {
+ OP_DEBUG_2("\tSET_REGION_ROOM(%d, %d)", e.arg(1), e.arg(2));
- // TODO
- // Arg 1: disk
- // Arg 2: room
-
- return 2;
+ getCurRoom().curPicture = getCurRoom().picture;
+ getCurRoom().isFirstTime = false;
+ switchRegion(e.arg(1));
+ _state.room = e.arg(2);
+ restoreRoomState(_state.room);
+ return -1;
}
-int AdlEngine_v5::o5_sound(ScriptEnv &e) {
- OP_DEBUG_0("\tSOUND()");
+int AdlEngine_v5::o5_setRoomPic(ScriptEnv &e) {
+ const byte isFirstTime = restoreRoomState(e.arg(1));
- // TODO
+ // CHECKME: More peculiar isFirstTime handling (see also restoreRoomState).
+ // Is this here to prevent changing the backed up flag from 1 to 0? Since
+ // that could only happen if the room isFirstTime is 0 while the backed up flag
+ // is 1, is this scenario even possible?
+ if (isFirstTime != 0xff)
+ getRoom(e.arg(1)).isFirstTime = isFirstTime;
- return 0;
+ o4_setRoomPic(e);
+ return 2;
}
} // End of namespace Adl
diff --git a/engines/adl/adl_v5.h b/engines/adl/adl_v5.h
index 377fe45e20..473b244993 100644
--- a/engines/adl/adl_v5.h
+++ b/engines/adl/adl_v5.h
@@ -23,49 +23,28 @@
#ifndef ADL_ADL_V5_H
#define ADL_ADL_V5_H
-#include "adl/adl_v3.h"
-
-namespace Common {
-class RandomSource;
-}
-
-struct DiskOffset {
- byte track;
- byte sector;
-};
+#include "adl/adl_v4.h"
namespace Adl {
-// FIXME: Subclass _v4 when it is done
-class AdlEngine_v5 : public AdlEngine_v3 {
+class AdlEngine_v5 : public AdlEngine_v4 {
public:
virtual ~AdlEngine_v5() { }
protected:
AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd);
- // AdlEngine
- virtual void setupOpcodeTables();
- virtual Common::String loadMessage(uint idx) const;
- Common::String getItemDescription(const Item &item) const;
+ // AdlEngine_v4
+ virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
+ virtual void initRoomState(RoomState &roomState) const;
+ virtual byte restoreRoomState(byte room);
- // AdlEngine_v2
- virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
-
- void applyDiskOffset(byte &track, byte &sector) const;
-
- int o5_isVarGT(ScriptEnv &e);
- int o5_isItemInRoom(ScriptEnv &e);
int o5_isNounNotInRoom(ScriptEnv &e);
- int o5_skipOneCommand(ScriptEnv &e);
- int o5_moveItem(ScriptEnv &e);
+ int o5_abortScript(ScriptEnv &e);
int o5_dummy(ScriptEnv &e);
int o5_setTextMode(ScriptEnv &e);
- int o5_setDisk(ScriptEnv &e);
- int o5_sound(ScriptEnv &e);
-
- byte _curDisk;
- Common::Array<DiskOffset> _diskOffsets;
+ int o5_setRegionRoom(ScriptEnv &e);
+ int o5_setRoomPic(ScriptEnv &e);
};
} // End of namespace Adl
diff --git a/engines/adl/console.cpp b/engines/adl/console.cpp
index 7305ec8125..ad3277ffaa 100644
--- a/engines/adl/console.cpp
+++ b/engines/adl/console.cpp
@@ -24,6 +24,7 @@
#include "adl/console.h"
#include "adl/display.h"
+#include "adl/graphics.h"
#include "adl/adl.h"
namespace Adl {
@@ -173,7 +174,7 @@ bool Console::Cmd_DumpScripts(int argc, const char **argv) {
}
void Console::prepareGame() {
- _engine->clearScreen();
+ _engine->_graphics->clearScreen();
_engine->loadRoom(_engine->_state.room);
_engine->showRoom();
_engine->_display->updateTextScreen();
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index cba66faca9..02fadd255b 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -141,6 +141,21 @@ static const AdlGameDescription gameDescriptions[] = {
},
GAME_TYPE_HIRES0
},
+ { // Hi-Res Adventure #4: Ulysses and the Golden Fleece - Apple II - Load 'N' Go
+ {
+ "hires4", 0,
+ {
+ { "ULYSSESA.DSK", 0, "df21f28ae94440f958dbbcfdfaf0c36e", 143360 },
+ { "ULYSSESB.DSK", 1, "c204e8fe265e9534049f3c0f816cc9fc", 143360 },
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformApple2,
+ ADGF_UNSTABLE,
+ GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES)
+ },
+ GAME_TYPE_HIRES4
+ },
{ // Hi-Res Adventure #4: Ulysses and the Golden Fleece - Atari 8-bit - Re-release
{
"hires4", 0,
@@ -178,7 +193,7 @@ static const AdlGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformApple2,
- ADGF_UNSTABLE,
+ ADGF_TESTING,
GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES)
},
GAME_TYPE_HIRES5
@@ -188,9 +203,9 @@ static const AdlGameDescription gameDescriptions[] = {
"hires6", 0,
{
{ "DARK1A.DSK", 0, "00c2646d6943d1405717332a6f42d493", 143360 },
- { "DARK2A.NIB", 0, "271eb92db107e8d5829437f8ba77991e", 232960 },
- { "DARK1B.NIB", 0, "dbedd736617343ade0e6bead8bf2b10c", 232960 },
- { "DARK2B.NIB", 0, "cb72044a9b391c4285f4752f746bea2e", 232960 },
+ { "DARK1B.NIB", 3, "dbedd736617343ade0e6bead8bf2b10c", 232960 },
+ { "DARK2A.NIB", 4, "271eb92db107e8d5829437f8ba77991e", 232960 },
+ { "DARK2B.NIB", 5, "cb72044a9b391c4285f4752f746bea2e", 232960 },
AD_LISTEND
},
Common::EN_ANY,
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index c630d034c9..7283777fe3 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -250,6 +250,8 @@ void Display::setPixelPalette(const Common::Point &p, byte color) {
}
bool Display::getPixelBit(const Common::Point &p) const {
+ assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
+
byte *b = _frameBuf + p.y * DISPLAY_PITCH + p.x / 7;
return *b & (1 << (p.x % 7));
}
@@ -334,8 +336,7 @@ void Display::showCursor(bool enable) {
}
void Display::writeFrameBuffer(const Common::Point &p, byte color, byte mask) {
- if (p.x >= DISPLAY_WIDTH || p.y >= DISPLAY_HEIGHT)
- return;
+ assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
byte *b = _frameBuf + p.y * DISPLAY_PITCH + p.x / 7;
color ^= *b;
diff --git a/engines/adl/graphics.cpp b/engines/adl/graphics.cpp
index 47ef5744fa..cf906657b5 100644
--- a/engines/adl/graphics.cpp
+++ b/engines/adl/graphics.cpp
@@ -29,6 +29,11 @@
namespace Adl {
+void GraphicsMan::clearScreen() const {
+ _display.setMode(DISPLAY_MODE_MIXED);
+ _display.clear(getClearColor());
+}
+
// Draws a four-connected line
void GraphicsMan::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const {
int16 deltaX = p2.x - p1.x;
@@ -52,7 +57,7 @@ void GraphicsMan::drawLine(const Common::Point &p1, const Common::Point &p2, byt
int16 err = deltaX + deltaY;
while (true) {
- _display.putPixel(p, color);
+ putPixel(p, color);
if (--steps == 0)
return;
@@ -67,6 +72,11 @@ void GraphicsMan::drawLine(const Common::Point &p1, const Common::Point &p2, byt
}
}
+void GraphicsMan::putPixel(const Common::Point &p, byte color) const {
+ if (_bounds.contains(p))
+ _display.putPixel(p, color);
+}
+
void Graphics_v1::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
byte x, y;
bool bNewLine = false;
@@ -93,7 +103,7 @@ void Graphics_v1::drawPic(Common::SeekableReadStream &pic, const Common::Point &
y = 160;
if (bNewLine) {
- _display.putPixel(Common::Point(x, y), 0x7f);
+ putPixel(Common::Point(x, y), 0x7f);
bNewLine = false;
} else {
drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
@@ -106,7 +116,7 @@ void Graphics_v1::drawPic(Common::SeekableReadStream &pic, const Common::Point &
void Graphics_v1::drawCornerPixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
if (bits & 4)
- _display.putPixel(p, color);
+ putPixel(p, color);
bits += quadrant;
@@ -209,11 +219,6 @@ static const byte fillPatterns[NUM_PATTERNS][PATTERN_LEN] = {
p.y += _offset.y; \
} while (0)
-void Graphics_v2::clear() {
- _display.clear(0xff);
- _color = 0;
-}
-
void Graphics_v2::drawCorners(Common::SeekableReadStream &pic, bool yFirst) {
Common::Point p;
@@ -228,7 +233,7 @@ void Graphics_v2::drawCorners(Common::SeekableReadStream &pic, bool yFirst) {
READ_BYTE(n);
n += _offset.x;
- _display.putPixel(p, _color);
+ putPixel(p, _color);
n <<= 1;
drawLine(p, Common::Point(n, p.y), _color);
@@ -238,10 +243,10 @@ doYStep:
READ_BYTE(n);
n += _offset.y;
- _display.putPixel(p, _color);
+ putPixel(p, _color);
drawLine(p, Common::Point(p.x, n), _color);
- _display.putPixel(Common::Point(p.x + 1, p.y), _color);
+ putPixel(Common::Point(p.x + 1, p.y), _color);
drawLine(Common::Point(p.x + 1, p.y), Common::Point(p.x + 1, n), _color);
p.y = n;
@@ -252,7 +257,7 @@ void Graphics_v2::drawRelativeLines(Common::SeekableReadStream &pic) {
Common::Point p1;
READ_POINT(p1);
- _display.putPixel(p1, _color);
+ putPixel(p1, _color);
while (true) {
Common::Point p2(p1);
@@ -282,7 +287,7 @@ void Graphics_v2::drawAbsoluteLines(Common::SeekableReadStream &pic) {
Common::Point p1;
READ_POINT(p1);
- _display.putPixel(p1, _color);
+ putPixel(p1, _color);
while (true) {
Common::Point p2;
@@ -310,7 +315,7 @@ bool Graphics_v2::canFillAt(const Common::Point &p, const bool stopBit) {
void Graphics_v2::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
byte color = getPatternColor(p, pattern);
- while (--p.x >= 0) {
+ while (--p.x >= _bounds.left) {
if ((p.x % 7) == 6) {
color = getPatternColor(p, pattern);
_display.setPixelPalette(p, color);
@@ -331,7 +336,7 @@ void Graphics_v2::fillRow(Common::Point p, const byte pattern, const bool stopBi
fillRowLeft(p, pattern, stopBit);
// Fill right of p
- while (++p.x < DISPLAY_WIDTH) {
+ while (++p.x < _bounds.right) {
if ((p.x % 7) == 0) {
color = getPatternColor(p, pattern);
// Palette is set before the first bit is tested
@@ -347,10 +352,10 @@ void Graphics_v2::fillAt(Common::Point p, const byte pattern) {
const bool stopBit = !_display.getPixelBit(p);
// Move up into the open space above p
- while (--p.y >= 0 && canFillAt(p, stopBit));
+ while (--p.y >= _bounds.top && canFillAt(p, stopBit));
// Then fill by moving down
- while (++p.y < DISPLAY_HEIGHT && canFillAt(p, stopBit))
+ while (++p.y < _bounds.bottom && canFillAt(p, stopBit))
fillRow(p, pattern, stopBit);
}
@@ -362,11 +367,16 @@ void Graphics_v2::fill(Common::SeekableReadStream &pic) {
Common::Point p;
READ_POINT(p);
- fillAt(p, pattern);
+ if (_bounds.contains(p))
+ fillAt(p, pattern);
}
}
void Graphics_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
+ // NOTE: The original engine only resets the color for overlays. As a result, room
+ // pictures that draw without setting a color or clearing the screen, will use the
+ // last color set by the previous picture. We assume this is unintentional and do
+ // not copy this behavior.
_color = 0;
_offset = pos;
@@ -393,7 +403,8 @@ void Graphics_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &
fill(pic);
break;
case 0xe5:
- clear();
+ clearScreen();
+ _color = 0x00;
break;
case 0xf0:
_color = 0x00;
@@ -422,7 +433,10 @@ void Graphics_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &
case 0xff:
return;
default:
- error("Invalid pic opcode %02x", opcode);
+ if (opcode >= 0xe0)
+ error("Invalid pic opcode %02x", opcode);
+ else
+ warning("Expected pic opcode, but found data byte %02x", opcode);
}
}
}
@@ -430,7 +444,7 @@ void Graphics_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &
void Graphics_v3::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
byte color = getPatternColor(p, pattern);
- while (--p.x >= 0) {
+ while (--p.x >= _bounds.left) {
// In this version, when moving left, it no longer sets the palette first
if (!_display.getPixelBit(p))
return;
@@ -452,11 +466,11 @@ void Graphics_v3::fillAt(Common::Point p, const byte pattern) {
Common::Point q(p);
// Fill up from p
- while (--q.y >= 0 && canFillAt(q))
+ while (--q.y >= _bounds.top && canFillAt(q))
fillRow(q, pattern);
// Fill down from p
- while (++p.y < DISPLAY_HEIGHT && canFillAt(p))
+ while (++p.y < _bounds.bottom && canFillAt(p))
fillRow(p, pattern);
}
diff --git a/engines/adl/graphics.h b/engines/adl/graphics.h
index af34e80113..c0d1780a33 100644
--- a/engines/adl/graphics.h
+++ b/engines/adl/graphics.h
@@ -23,9 +23,10 @@
#ifndef ADL_PICTURE_H
#define ADL_PICTURE_H
+#include "common/rect.h"
+
namespace Common {
class SeekableReadStream;
-struct Point;
}
namespace Adl {
@@ -36,12 +37,18 @@ class GraphicsMan {
public:
virtual ~GraphicsMan() { }
virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) = 0;
+ void clearScreen() const;
+ void putPixel(const Common::Point &p, byte color) const;
protected:
- GraphicsMan(Display &display) : _display(display) { }
+ GraphicsMan(Display &display) : _bounds(280, 160), _display(display) { }
void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const;
Display &_display;
+ Common::Rect _bounds;
+
+private:
+ virtual byte getClearColor() const = 0;
};
// Used in hires1
@@ -53,6 +60,7 @@ public:
private:
void drawCornerPixel(Common::Point &p, byte color, byte bits, byte quadrant) const;
+ byte getClearColor() const { return 0x00; }
};
// Used in hires0 and hires2-hires4
@@ -66,13 +74,13 @@ protected:
void fillRow(Common::Point p, const byte pattern, const bool stopBit = false);
private:
- void clear();
void drawCorners(Common::SeekableReadStream &pic, bool yFirst);
void drawRelativeLines(Common::SeekableReadStream &pic);
void drawAbsoluteLines(Common::SeekableReadStream &pic);
virtual void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit);
virtual void fillAt(Common::Point p, const byte pattern);
void fill(Common::SeekableReadStream &pic);
+ byte getClearColor() const { return 0xff; }
byte _color;
Common::Point _offset;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index e811b747c3..239792d4f7 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -429,7 +429,7 @@ void HiRes1Engine::loadRoom(byte roomNr) {
void HiRes1Engine::showRoom() {
_state.curPicture = getCurRoom().curPicture;
- clearScreen();
+ _graphics->clearScreen();
loadRoom(_state.room);
if (!_state.isDark) {
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index c07493f5bd..b3b66f6873 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -34,59 +34,171 @@
namespace Adl {
-#define IDI_HR6_NUM_ROOMS 35
-#define IDI_HR6_NUM_MESSAGES 256
-#define IDI_HR6_NUM_VARS 40
-#define IDI_HR6_NUM_ITEM_DESCS 15
-#define IDI_HR6_NUM_ITEM_PICS 15
-#define IDI_HR6_NUM_ITEM_OFFSETS 16
-
-// Messages used outside of scripts
-#define IDI_HR6_MSG_CANT_GO_THERE 249
-#define IDI_HR6_MSG_DONT_UNDERSTAND 247
-#define IDI_HR6_MSG_ITEM_DOESNT_MOVE 253
-#define IDI_HR6_MSG_ITEM_NOT_HERE 254
-#define IDI_HR6_MSG_THANKS_FOR_PLAYING 252
-
-struct DiskDataDesc {
- byte track;
- byte sector;
- byte offset;
- byte volume;
-};
-
class HiRes6Engine : public AdlEngine_v5 {
public:
HiRes6Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine_v5(syst, gd),
- _boot(nullptr),
_currVerb(0),
_currNoun(0) {
}
- ~HiRes6Engine() { delete _boot; }
-
private:
// AdlEngine
+ void gameLoop();
+ void setupOpcodeTables();
void runIntro();
void init();
void initGameState();
- void printRoomDescription();
void showRoom();
Common::String formatVerbError(const Common::String &verb) const;
Common::String formatNounError(const Common::String &verb, const Common::String &noun) const;
+ void loadState(Common::ReadStream &stream);
+ void saveState(Common::WriteStream &stream);
// AdlEngine_v2
void printString(const Common::String &str);
- void loadDisk(byte disk);
+ template <Direction D>
+ int o_goDirection(ScriptEnv &e);
+ int o_fluteSound(ScriptEnv &e);
+
+ static const uint kRegions = 3;
+ static const uint kItems = 15;
- DiskImage *_boot;
byte _currVerb, _currNoun;
- Common::Array<DiskDataDesc> _diskDataDesc;
};
-static const char *disks[] = { "DARK1A.DSK", "DARK1B.NIB", "DARK2A.NIB", "DARK2B.NIB" };
+void HiRes6Engine::gameLoop() {
+ AdlEngine_v5::gameLoop();
+
+ // Variable 25 starts at 5 and counts down every 160 moves.
+ // When it reaches 0, the game ends. This variable determines
+ // what you see when you "LOOK SUNS".
+ // Variable 39 is used to advance the suns based on game events,
+ // so even a fast player will see the suns getting closer together
+ // as he progresses.
+ if (getVar(39) != 0) {
+ if (getVar(39) < getVar(25))
+ setVar(25, getVar(39));
+ setVar(39, 0);
+ }
+
+ if (getVar(25) != 0) {
+ if (getVar(25) > 5)
+ error("Variable 25 has unexpected value %d", getVar(25));
+ if ((6 - getVar(25)) * 160 == _state.moves)
+ setVar(25, getVar(25) - 1);
+ }
+}
+
+typedef Common::Functor1Mem<ScriptEnv &, int, HiRes6Engine> OpcodeH6;
+#define SetOpcodeTable(x) table = &x;
+#define Opcode(x) table->push_back(new OpcodeH6(this, &HiRes6Engine::x))
+#define OpcodeUnImpl() table->push_back(new OpcodeH6(this, 0))
+
+void HiRes6Engine::setupOpcodeTables() {
+ Common::Array<const Opcode *> *table = 0;
+
+ SetOpcodeTable(_condOpcodes);
+ // 0x00
+ OpcodeUnImpl();
+ Opcode(o2_isFirstTime);
+ Opcode(o2_isRandomGT);
+ Opcode(o4_isItemInRoom);
+ // 0x04
+ Opcode(o5_isNounNotInRoom);
+ Opcode(o1_isMovesGT);
+ Opcode(o1_isVarEQ);
+ Opcode(o2_isCarryingSomething);
+ // 0x08
+ Opcode(o4_isVarGT);
+ Opcode(o1_isCurPicEQ);
+ Opcode(o5_abortScript);
+
+ SetOpcodeTable(_actOpcodes);
+ // 0x00
+ OpcodeUnImpl();
+ Opcode(o1_varAdd);
+ Opcode(o1_varSub);
+ Opcode(o1_varSet);
+ // 0x04
+ Opcode(o1_listInv);
+ Opcode(o4_moveItem);
+ Opcode(o1_setRoom);
+ Opcode(o2_setCurPic);
+ // 0x08
+ Opcode(o2_setPic);
+ Opcode(o1_printMsg);
+ Opcode(o5_dummy);
+ Opcode(o5_setTextMode);
+ // 0x0c
+ Opcode(o4_moveAllItems);
+ Opcode(o1_quit);
+ Opcode(o5_dummy);
+ Opcode(o4_save);
+ // 0x10
+ Opcode(o4_restore);
+ Opcode(o1_restart);
+ Opcode(o5_setRegionRoom);
+ Opcode(o5_dummy);
+ // 0x14
+ Opcode(o1_resetPic);
+ Opcode(o_goDirection<IDI_DIR_NORTH>);
+ Opcode(o_goDirection<IDI_DIR_SOUTH>);
+ Opcode(o_goDirection<IDI_DIR_EAST>);
+ // 0x18
+ Opcode(o_goDirection<IDI_DIR_WEST>);
+ Opcode(o_goDirection<IDI_DIR_UP>);
+ Opcode(o_goDirection<IDI_DIR_DOWN>);
+ Opcode(o1_takeItem);
+ // 0x1c
+ Opcode(o1_dropItem);
+ Opcode(o5_setRoomPic);
+ Opcode(o_fluteSound);
+ OpcodeUnImpl();
+ // 0x20
+ Opcode(o2_initDisk);
+}
+
+template <Direction D>
+int HiRes6Engine::o_goDirection(ScriptEnv &e) {
+ OP_DEBUG_0((Common::String("\tGO_") + dirStr(D) + "()").c_str());
+
+ byte room = getCurRoom().connections[D];
+
+ if (room == 0) {
+ if (getVar(33) == 2)
+ setVar(34, getVar(34) + 1);
+
+ printMessage(_messageIds.cantGoThere);
+ return -1;
+ }
+
+ switchRoom(room);
+
+ if (getVar(33) == 2) {
+ printMessage(102);
+ setVar(33, 0);
+ }
+
+ return -1;
+}
+
+int HiRes6Engine::o_fluteSound(ScriptEnv &e) {
+ OP_DEBUG_0("\tFLUTE_SOUND()");
+
+ Tones tones;
+
+ tones.push_back(Tone(1072.0, 587.6));
+ tones.push_back(Tone(1461.0, 495.8));
+ tones.push_back(Tone(0.0, 1298.7));
+
+ playTones(tones, false);
+
+ _linesPrinted = 0;
+
+ return 0;
+}
#define SECTORS_PER_TRACK 16
#define BYTES_PER_SECTOR 256
@@ -121,12 +233,9 @@ static Common::MemoryReadStream *loadSectors(DiskImage *disk, byte track, byte s
}
void HiRes6Engine::runIntro() {
- DiskImage *boot(new DiskImage());
-
- if (!boot->open(disks[0]))
- error("Failed to open disk image '%s'", disks[0]);
+ insertDisk(0);
- StreamPtr stream(loadSectors(boot, 11, 1, 96));
+ StreamPtr stream(loadSectors(_disk, 11, 1, 96));
_display->setMode(DISPLAY_MODE_HIRES);
_display->loadFrameBuffer(*stream);
@@ -139,13 +248,11 @@ void HiRes6Engine::runIntro() {
_display->loadFrameBuffer(*stream);
- delete boot;
-
// Load copyright string from boot file
Files_DOS33 *files(new Files_DOS33());
- if (!files->open(disks[0]))
- error("Failed to open disk image '%s'", disks[0]);
+ if (!files->open(getDiskImageName(0)))
+ error("Failed to open disk volume 0");
stream.reset(files->createReadStream("\010\010\010\010\010\010"));
Common::String copyright(readStringAt(*stream, 0x103, APPLECHAR('\r')));
@@ -161,161 +268,61 @@ void HiRes6Engine::runIntro() {
}
void HiRes6Engine::init() {
- _boot = new DiskImage();
- _graphics = new Graphics_v2(*_display);
+ _graphics = new Graphics_v3(*_display);
+
+ insertDisk(0);
- if (!_boot->open(disks[0]))
- error("Failed to open disk image '%s'", disks[0]);
+ StreamPtr stream(_disk->createReadStream(0x3, 0xf, 0x05));
+ loadRegionLocations(*stream, kRegions);
- StreamPtr stream(loadSectors(_boot, 0x7));
+ stream.reset(_disk->createReadStream(0x5, 0xa, 0x07));
+ loadRegionInitDataOffsets(*stream, kRegions);
+
+ stream.reset(loadSectors(_disk, 0x7));
- // Read parser messages
_strings.verbError = readStringAt(*stream, 0x666);
_strings.nounError = readStringAt(*stream, 0x6bd);
_strings.enterCommand = readStringAt(*stream, 0x6e9);
- // Read line feeds
_strings.lineFeeds = readStringAt(*stream, 0x408);
- // Read opcode strings (TODO)
_strings_v2.saveInsert = readStringAt(*stream, 0xad8);
- readStringAt(*stream, 0xb95); // Confirm save
- // _strings_v2.saveReplace
+ _strings_v2.saveReplace = readStringAt(*stream, 0xb95);
_strings_v2.restoreInsert = readStringAt(*stream, 0xc07);
- // _strings_v2.restoreReplace
_strings.playAgain = readStringAt(*stream, 0xcdf, 0xff);
- _messageIds.cantGoThere = IDI_HR6_MSG_CANT_GO_THERE;
- _messageIds.dontUnderstand = IDI_HR6_MSG_DONT_UNDERSTAND;
- _messageIds.itemDoesntMove = IDI_HR6_MSG_ITEM_DOESNT_MOVE;
- _messageIds.itemNotHere = IDI_HR6_MSG_ITEM_NOT_HERE;
- _messageIds.thanksForPlaying = IDI_HR6_MSG_THANKS_FOR_PLAYING;
+ _messageIds.cantGoThere = 249;
+ _messageIds.dontUnderstand = 247;
+ _messageIds.itemDoesntMove = 253;
+ _messageIds.itemNotHere = 254;
+ _messageIds.thanksForPlaying = 252;
- // Item descriptions
- stream.reset(loadSectors(_boot, 0x6, 0xb, 2));
+ stream.reset(loadSectors(_disk, 0x6, 0xb, 2));
stream->seek(0x16);
- loadItemDescriptions(*stream, IDI_HR6_NUM_ITEM_DESCS);
-
- // Load dropped item offsets
- stream.reset(_boot->createReadStream(0x8, 0x9, 0x16));
- loadDroppedItemOffsets(*stream, IDI_HR6_NUM_ITEM_OFFSETS);
-
- // Location of game data for each disc
- stream.reset(_boot->createReadStream(0x5, 0xa, 0x03));
- for (uint i = 0; i < sizeof(disks); ++i) {
- DiskDataDesc desc;
- desc.track = stream->readByte();
- desc.sector = stream->readByte();
- desc.offset = stream->readByte();
- desc.volume = stream->readByte();
- _diskDataDesc.push_back(desc);
- }
+ loadItemDescriptions(*stream, kItems);
- // DataBlockPtr offsets for each disk
- stream.reset(_boot->createReadStream(0x3, 0xf, 0x03));
- for (uint i = 0; i < sizeof(disks); ++i) {
- DiskOffset offset;
- offset.track = stream->readByte();
- offset.sector = stream->readByte();
- _diskOffsets.push_back(offset);
- }
-}
-
-void HiRes6Engine::loadDisk(byte disk) {
- delete _disk;
- _disk = new DiskImage();
-
- if (!_disk->open(disks[disk]))
- error("Failed to open disk image '%s'", disks[disk]);
-
- _curDisk = 0;
-
- // Load item picture data (indexed on boot disk)
- StreamPtr stream(_boot->createReadStream(0xb, 0xd, 0x08));
- _itemPics.clear();
- loadItemPictures(*stream, IDI_HR6_NUM_ITEM_PICS);
-
- _curDisk = disk;
-
- byte track = _diskDataDesc[disk].track;
- byte sector = _diskDataDesc[disk].sector;
- uint offset = _diskDataDesc[disk].offset;
-
- applyDiskOffset(track, sector);
-
- for (uint block = 0; block < 7; ++block) {
- stream.reset(_disk->createReadStream(track, sector, offset, 1));
-
- uint16 addr = stream->readUint16LE();
- uint16 size = stream->readUint16LE();
-
- stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1));
- stream->skip(4);
-
- switch (addr) {
- case 0x9000: {
- // Messages
- _messages.clear();
- uint count = size / 4;
- loadMessages(*stream, count);
- break;
- }
- case 0x4a80: {
- // Global pics
- _pictures.clear();
- loadPictures(*stream);
- break;
- }
- case 0x4000:
- // Verbs
- loadWords(*stream, _verbs, _priVerbs);
- break;
- case 0x1800:
- // Nouns
- loadWords(*stream, _nouns, _priNouns);
- break;
- case 0x0e00: {
- // Rooms
- uint count = size / 14 - 1;
- stream->skip(14); // Skip invalid room 0
-
- _state.rooms.clear();
- loadRooms(*stream, count);
- break;
- }
- case 0x7b00:
- // Global commands
- readCommands(*stream, _globalCommands);
- break;
- case 0x9500:
- // Room commands
- readCommands(*stream, _roomCommands);
- break;
- default:
- error("Unknown data block found (addr %04x; size %04x)", addr, size);
- }
+ stream.reset(_disk->createReadStream(0x8, 0x9, 0x16));
+ loadDroppedItemOffsets(*stream, 16);
- offset += 4 + size;
- while (offset >= 256) {
- offset -= 256;
- ++sector;
- if (sector >= 16) {
- sector = 0;
- ++track;
- }
- }
- }
+ stream.reset(_disk->createReadStream(0xb, 0xd, 0x08));
+ loadItemPicIndex(*stream, kItems);
}
void HiRes6Engine::initGameState() {
- _state.vars.resize(IDI_HR6_NUM_VARS);
+ _state.vars.resize(40);
- loadDisk(1);
-
- StreamPtr stream(_boot->createReadStream(0x3, 0xe, 0x03));
+ insertDisk(0);
+ StreamPtr stream(_disk->createReadStream(0x3, 0xe, 0x03));
loadItems(*stream);
+ // A combined total of 91 rooms
+ static const byte rooms[kRegions] = { 35, 29, 27 };
+
+ initRegions(rooms, kRegions);
+
+ loadRegion(1);
+
_currVerb = _currNoun = 0;
}
@@ -335,7 +342,7 @@ void HiRes6Engine::showRoom() {
if (getVar(26) < 0x80 && getCurRoom().isFirstTime)
setVar(26, 0);
- clearScreen();
+ _graphics->clearScreen();
if (!_state.isDark)
redrawPic = true;
@@ -405,10 +412,26 @@ Common::String HiRes6Engine::formatNounError(const Common::String &verb, const C
return err;
}
+void HiRes6Engine::loadState(Common::ReadStream &stream) {
+ AdlEngine_v5::loadState(stream);
+ _state.moves = (getVar(39) << 8) | getVar(24);
+ setVar(39, 0);
+}
+
+void HiRes6Engine::saveState(Common::WriteStream &stream) {
+ // Move counter is stuffed into variables, in order to save it
+ setVar(24, _state.moves & 0xff);
+ setVar(39, _state.moves >> 8);
+ AdlEngine_v5::saveState(stream);
+ setVar(39, 0);
+}
+
void HiRes6Engine::printString(const Common::String &str) {
Common::String s;
uint found = 0;
+ // Variable 27 is 1 when Kira is present, 0 otherwise. It's used for choosing
+ // between singular and plural variants of a string.
// This does not emulate the corner cases of the original, hence this check
if (getVar(27) > 1)
error("Invalid value %i encountered for variable 27", getVar(27));
@@ -424,21 +447,24 @@ void HiRes6Engine::printString(const Common::String &str) {
}
}
- if (getVar(2) != 0xff) {
- AdlEngine_v2::printString(s);
- } else {
+ // Variables 2 and 26 are used for controlling the printing of room descriptions
+ if (getVar(2) == 0xff) {
if (getVar(26) == 0) {
+ // This checks for special room description string " "
if (str.size() != 1 || APPLECHAR(str[0]) != APPLECHAR(' '))
- return AdlEngine_v2::printString(s);
- setVar(2, APPLECHAR(' '));
- } else if (getVar(26) != 0xff) {
- setVar(2, 'P');
- } else {
+ return AdlEngine_v5::printString(s);
+ setVar(2, 160);
+ } else if (getVar(26) == 0xff) {
+ // Storing the room number in a variable allows for range comparisons
setVar(26, _state.room);
setVar(2, 1);
+ } else {
+ setVar(2, 80);
}
doAllCommands(_globalCommands, _currVerb, _currNoun);
+ } else {
+ AdlEngine_v5::printString(s);
}
}
diff --git a/engines/adl/sound.cpp b/engines/adl/sound.cpp
index 63eea45953..3d46ea0409 100644
--- a/engines/adl/sound.cpp
+++ b/engines/adl/sound.cpp
@@ -47,10 +47,9 @@ private:
Speaker::Speaker(int sampleRate) :
_rate(sampleRate),
- _curSample(32767) {
-
- stopTone();
-}
+ _halfWaveLen(0),
+ _halfWaveRem(0),
+ _curSample(32767) { }
void Speaker::startTone(double freq) {
_halfWaveLen = _halfWaveRem = doubleToFrac(_rate / freq / 2);
@@ -63,10 +62,15 @@ void Speaker::startTone(double freq) {
void Speaker::stopTone() {
_halfWaveLen = 0;
- _halfWaveRem = intToFrac(32767);
}
void Speaker::generateSamples(int16 *buffer, int numSamples) {
+ if (_halfWaveLen == 0) {
+ // Silence
+ memset(buffer, 0, numSamples * sizeof(int16));
+ return;
+ }
+
int offset = 0;
while (offset < numSamples) {
@@ -79,15 +83,14 @@ void Speaker::generateSamples(int16 *buffer, int numSamples) {
// Compute next transition point
_halfWaveRem += _halfWaveLen - FRAC_ONE;
} else {
- // Low/high level (incl. silence)
+ // Low/high level
// Generate as many samples as we can
const int samples = MIN(numSamples - offset, (int)fracToInt(_halfWaveRem));
Common::fill(buffer + offset, buffer + offset + samples, _curSample);
offset += samples;
- // Count down to level transition point, unless we're playing silence
- if (_halfWaveLen > 0)
- _halfWaveRem -= intToFrac(samples);
+ // Count down to level transition point
+ _halfWaveRem -= intToFrac(samples);
}
}
}
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 60c8d1f3ef..b293a8e9e5 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -173,6 +173,7 @@ int AgiEngine::agiInit() {
#endif
_keyHoldMode = false;
+ _keyHoldModeLastKey = Common::KEYCODE_INVALID;
_game.mouseFence.setWidth(0); // Reset
@@ -423,6 +424,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_inventory = nullptr;
_keyHoldMode = false;
+ _keyHoldModeLastKey = Common::KEYCODE_INVALID;
_artificialDelayCurrentRoom = 0;
_artificialDelayCurrentPicture = 0;
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index b8c30e9d5c..2b62f9757a 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -27,6 +27,7 @@
#include "common/error.h"
#include "common/util.h"
#include "common/file.h"
+#include "common/keyboard.h"
#include "common/rect.h"
#include "common/rendermode.h"
#include "common/stack.h"
@@ -936,6 +937,7 @@ public:
int getDirection(int16 objX, int16 objY, int16 destX, int16 destY, int16 stepSize);
bool _keyHoldMode;
+ Common::KeyCode _keyHoldModeLastKey;
// Keyboard
int doPollKeyboard();
diff --git a/engines/agi/appleIIgs_timedelay_overwrite.h b/engines/agi/appleIIgs_timedelay_overwrite.h
index c24d7cb5bd..06b94bf3fc 100644
--- a/engines/agi/appleIIgs_timedelay_overwrite.h
+++ b/engines/agi/appleIIgs_timedelay_overwrite.h
@@ -28,46 +28,50 @@ namespace Agi {
struct AgiAppleIIgsDelayOverwriteRoomEntry {
int16 fromRoom;
int16 toRoom;
- int16 timeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles
- bool onlyWhenPlayerNotInControl;
+ int16 activePictureNr; // resource number of current active background picture
+ int16 timeDelayOverwrite; // time delay here is like on PC
+ // so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles, -1 means do not touch speed set by scripts
+ bool onlyWhenPlayerNotInControl; // only sets spee, when play is not in control
};
struct AgiAppleIIgsDelayOverwriteGameEntry {
uint32 gameId;
- int16 defaultTimeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles
- const AgiAppleIIgsDelayOverwriteRoomEntry *roomTable;
+ int16 defaultTimeDelayOverwrite; // time delay here is like on PC
+ // so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles, -1 means do not touch speed set by scripts
+ const AgiAppleIIgsDelayOverwriteRoomEntry *roomTable; // pointer to room table (optional)
};
static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteKQ4[] = {
- { 120, 121, -1, true }, // Part of the intro: Graham gets his hat, throws it and breaks down, don't touch speed (3 is set)
- { 128, 128, -1, true }, // Part of the intro: first actual room for gameplay, but during intro, don't touch speed (3 is set)
- { 92, 92, -1, true }, // Part of caught by gargoyle w/ Lolotte cutscene (3 is set)
+ { 120, 121, -1, -1, true }, // Part of the intro: Graham gets his hat, throws it and breaks down, don't touch speed (3 is set)
+ { 128, 128, -1, -1, true }, // Part of the intro: first actual room for gameplay, but during intro, don't touch speed (3 is set)
+ { 92, 92, -1, -1, true }, // Part of caught by gargoyle w/ Lolotte cutscene (3 is set)
// room 54 sets the speed for a short time to 3 right after entering "clean" command. It doesn't seem to hurt that we switch it down to 2
// room 92 is dual use, part of cutscenes, part of gameplay, that's why we only stop touching it, when player is not in control
- { 135, 135, -1, true }, // Part of ending cutscene. Don't touch speed (3 is set)
- { -1, -1, -1, false }
+ { 135, 135, -1, -1, true }, // Part of ending cutscene. Don't touch speed (3 is set)
+ { -1, -1, -1, -1, false }
};
static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteMH1[] = {
- //{ 153, 153, 2, false }, // Intro w/ credits
- //{ 104, 104, 2, false }, // Intro cutscene
- //{ 117, 117, 2, false }, // Intro cutscene (ego waking up)
- { 114, 114, -1, false }, // interactive MAD map
- { 124, 125, -1, false }, // MAD during intro (tracking), seem to work properly at given speed
- { 132, 133, -1, false }, // MAD day 2 intro (tracking)
- { 137, 137, -1, false }, // Night Club 4th arcade game - game sets speed to 7
- { 115, 116, -1, false }, // MAD day 3 intro (tracking)
- { 148, 148, -1, false }, // day 3: arcade sequence under pawn shop (game sets speed to 6)
- { 103, 103, -1, false }, // MAD day 4 intro (tracking)
- { 105, 105, -1, false }, // day 4 tracking mini game right at the start (game sets speed to 3)
- { 107, 107, -1, false }, // MAD day 4 intro (tracking)
- { 112, 112, -1, false }, // MAD day 4 intro (tracking)
- { -1, -1, -1, false }
+ //{ 153, 153, -1, 2, false }, // Intro w/ credits
+ //{ 104, 104, -1, 2, false }, // Intro cutscene
+ //{ 117, 117, -1, 2, false }, // Intro cutscene (ego waking up)
+ { 114, 114, -1, -1, false }, // interactive MAD map
+ { 124, 125, -1, -1, false }, // MAD during intro (tracking), seem to work properly at given speed
+ { 132, 133, -1, -1, false }, // MAD day 2 intro (tracking)
+ { 137, 137, 17, -1, false }, // Night Club 4th arcade game - game sets speed to 7, needs to run that slow to be playable
+ { 137, 137, -1, 4, false }, // Night Club first few arcade games - game sets speed to 0, we need to fix it
+ { 115, 116, -1, -1, false }, // MAD day 3 intro (tracking)
+ { 148, 148, -1, -1, false }, // day 3: arcade sequence under pawn shop (game sets speed to 6)
+ { 103, 103, -1, -1, false }, // MAD day 4 intro (tracking)
+ { 105, 105, -1, -1, false }, // day 4 tracking mini game right at the start (game sets speed to 3)
+ { 107, 107, -1, -1, false }, // MAD day 4 intro (tracking)
+ { 112, 112, -1, -1, false }, // MAD day 4 intro (tracking)
+ { -1, -1, -1, -1, false }
};
static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteSQ2[] = {
- { 1, 1, -1, false }, // Intro: space ship entering space port, don't touch speed
- { -1, -1, -1, false }
+ { 1, 1, -1, -1, false }, // Intro: space ship entering space port, don't touch speed
+ { -1, -1, -1, -1, false }
};
static const AgiAppleIIgsDelayOverwriteGameEntry appleIIgsDelayOverwriteGameTable[] = {
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 4148306de2..d09a9501d6 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -377,19 +377,22 @@ int AgiEngine::playGame() {
// Now check, if we got a time delay overwrite entry for current room
if (appleIIgsDelayOverwrite->roomTable) {
byte curRoom = getVar(VM_VAR_CURRENT_ROOM);
+ int16 curPictureNr = _picture->getResourceNr();
appleIIgsDelayRoomOverwrite = appleIIgsDelayOverwrite->roomTable;
while (appleIIgsDelayRoomOverwrite->fromRoom >= 0) {
if ((appleIIgsDelayRoomOverwrite->fromRoom <= curRoom) && (appleIIgsDelayRoomOverwrite->toRoom >= curRoom)) {
- if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) {
- if (_game.playerControl) {
- // Player is actually currently in control? -> then skip this entry
- appleIIgsDelayRoomOverwrite++;
- continue;
+ if ((appleIIgsDelayRoomOverwrite->activePictureNr == curPictureNr) || (appleIIgsDelayRoomOverwrite->activePictureNr == -1)) {
+ if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) {
+ if (_game.playerControl) {
+ // Player is actually currently in control? -> then skip this entry
+ appleIIgsDelayRoomOverwrite++;
+ continue;
+ }
}
+ timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite;
+ break;
}
- timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite;
- break;
}
appleIIgsDelayRoomOverwrite++;
}
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 7ed67949b5..8fb49fdf02 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -247,6 +247,29 @@ void AgiEngine::processScummVMEvents() {
default:
break;
}
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_HOME:
+ case Common::KEYCODE_END:
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_KP9:
+ case Common::KEYCODE_KP3:
+ case Common::KEYCODE_KP7:
+ case Common::KEYCODE_KP1:
+ _keyHoldModeLastKey = event.kbd.keycode;
+ break;
+ default:
+ break;
+ }
}
if (key)
keyEnqueue(key);
@@ -255,8 +278,12 @@ void AgiEngine::processScummVMEvents() {
case Common::EVENT_KEYUP:
if (_keyHoldMode) {
// Original AGI actually created direction events in here
- // We don't do that, that's why we create a stationary event instead, which will
- // result in a direction change to 0 in handleController().
+ // but only in case the last pressed cursor key was released, in other cases it did nothing.
+ // So when you pressed and held down left and then pressed up, and then released left,
+ // direction wouldn't be changed at all.
+ //
+ // We don't create direction events in here, that's why we create a stationary event instead,
+ // which will result in a direction change to 0 in handleController().
switch (event.kbd.keycode) {
case Common::KEYCODE_LEFT:
case Common::KEYCODE_RIGHT:
@@ -274,7 +301,9 @@ void AgiEngine::processScummVMEvents() {
case Common::KEYCODE_KP3:
case Common::KEYCODE_KP7:
case Common::KEYCODE_KP1:
- keyEnqueue(AGI_KEY_STATIONARY);
+ if (_keyHoldModeLastKey == event.kbd.keycode) {
+ keyEnqueue(AGI_KEY_STATIONARY);
+ }
break;
default:
break;
diff --git a/engines/agi/picture.h b/engines/agi/picture.h
index dfc505d8d0..2cb5bfabc8 100644
--- a/engines/agi/picture.h
+++ b/engines/agi/picture.h
@@ -64,6 +64,8 @@ class PictureMgr {
public:
PictureMgr(AgiBase *agi, GfxMgr *gfx);
+ int16 getResourceNr() { return _resourceNr; };
+
private:
void draw_xCorner(bool skipOtherCoords = false);
void yCorner(bool skipOtherCoords = false);
diff --git a/engines/cryo/configure.engine b/engines/cryo/configure.engine
new file mode 100644
index 0000000000..a0f5a044e9
--- /dev/null
+++ b/engines/cryo/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine cryo "Lost Eden" no "" "" ""
diff --git a/engines/cryo/cryo.cpp b/engines/cryo/cryo.cpp
new file mode 100644
index 0000000000..3574105053
--- /dev/null
+++ b/engines/cryo/cryo.cpp
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "graphics/surface.h"
+#include "graphics/screen.h"
+#include "graphics/palette.h"
+#include "common/system.h"
+
+#include "engines/util.h"
+
+#include "cryo/cryo.h"
+#include "cryo/eden.h"
+
+namespace Cryo {
+
+CryoEngine *g_ed = nullptr;
+
+CryoEngine::CryoEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+ _rnd = new Common::RandomSource("cryo");
+ _debugger = nullptr;
+
+ _game = nullptr;
+ _video = nullptr;
+ _screenView = nullptr;
+
+ _showHotspots = false;
+ _timerTicks = 0;
+
+ g_ed = this;
+}
+
+CryoEngine::~CryoEngine() {
+ delete _rnd;
+ delete _game;
+ delete _video;
+ delete _screenView;
+ delete _debugger;
+
+ DebugMan.clearAllDebugChannels();
+}
+
+Common::Error CryoEngine::run() {
+ _game = new EdenGame(this);
+ _video = new HnmPlayer(this);
+ _screenView = new View(320, 200);
+ _debugger = new Debugger(this);
+
+ ///// CLTimer
+ _timerTicks = 0; // incremented in realtime
+
+ // Initialize graphics using following:
+ initGraphics(320, 200, false);
+ _screen.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+
+ _game->run();
+
+ return Common::kNoError;
+}
+
+} // End of namespace Cryo
diff --git a/engines/cryo/cryo.h b/engines/cryo/cryo.h
new file mode 100644
index 0000000000..515849ffea
--- /dev/null
+++ b/engines/cryo/cryo.h
@@ -0,0 +1,100 @@
+/* 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.
+ *
+ */
+
+#ifndef CRYO_CRYO_H
+#define CRYO_CRYO_H
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "engines/advancedDetector.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/random.h"
+#include "engines/engine.h"
+#include "gui/debugger.h"
+#include "graphics/surface.h"
+#include "graphics/screen.h"
+
+#include "cryo/eden.h"
+#include "cryo/video.h"
+#include "cryo/debugger.h"
+
+namespace Cryo {
+
+class Console;
+
+// our engine debug channels
+enum {
+ kCryoDebugExample = 1 << 0,
+ kCryoDebugExample2 = 1 << 1
+ // next new channel must be 1 << 2 (4)
+ // the current limitation is 32 debug channels (1 << 31 is the last one)
+};
+
+class CryoEngine : public Engine {
+public:
+ CryoEngine(OSystem *syst, const ADGameDescription *gameDesc);
+ ~CryoEngine();
+
+ virtual Common::Error run();
+
+ // Detection related functions
+ const ADGameDescription *_gameDescription;
+ const char *getGameId() const;
+ Common::Platform getPlatform() const;
+ bool isDemo() const;
+
+ // We need random numbers
+ Common::RandomSource *_rnd;
+
+ Graphics::Surface _screen;
+ EdenGame *_game;
+ HnmPlayer *_video;
+ Debugger *_debugger;
+
+ View *_screenView;
+ volatile int32 _timerTicks;
+
+ bool _showHotspots;
+
+ void pollEvents();
+
+ void hideMouse();
+ void showMouse();
+ void getMousePosition(int16 *x, int16 *y);
+ void setMousePosition(int16 x, int16 y);
+ bool isMouseButtonDown();
+};
+
+extern CryoEngine *g_ed;
+
+// Example console class
+class Console : public GUI::Debugger {
+public:
+ Console(CryoEngine *vm) {}
+ virtual ~Console(void) {}
+};
+
+} // End of namespace Cryo
+
+#endif
diff --git a/engines/cryo/cryolib.cpp b/engines/cryo/cryolib.cpp
new file mode 100644
index 0000000000..8b8efad588
--- /dev/null
+++ b/engines/cryo/cryolib.cpp
@@ -0,0 +1,433 @@
+/* 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.
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+#include "common/timer.h"
+
+#include "graphics/palette.h"
+
+#include "cryo/cryo.h"
+#include "cryo/cryolib.h"
+
+namespace Cryo {
+
+///// Mac APIs
+
+void SysBeep(int x) {
+}
+
+void FlushEvents(int16 arg1, int16 arg2) {
+}
+
+///// CLView
+
+View::View(int w, int h) {
+ void *buffer = (byte *)malloc(w * h);
+ if (buffer)
+ initDatas(w, h, buffer);
+ else
+ error("Unable to allocate view buffer");
+}
+
+View::~View() {
+ if (_bufferPtr)
+ free(_bufferPtr);
+}
+
+// Original name: CLView_SetSrcZoomValues
+void View::setSrcZoomValues(int x, int y) {
+ _zoom._srcLeft = x;
+ _zoom._srcTop = y;
+}
+
+// Original name: CLView_SetDisplayZoomValues
+void View::setDisplayZoomValues(int w, int h) {
+ _zoom._width = w;
+ _zoom._height = h;
+}
+
+// Original name: CLView_InitDatas
+void View::initDatas(int w, int h, void *buffer) {
+ _bufferPtr = (byte *)buffer;
+ _width = w;
+ _height = h;
+ _pitch = w;
+ _normal._srcLeft = 0;
+ _normal._srcTop = 0;
+ _normal._dstLeft = 0;
+ _normal._dstTop = 0;
+ _normal._width = w;
+ _normal._height = h;
+ _zoom._srcLeft = 0;
+ _zoom._srcTop = 0;
+ _zoom._dstLeft = 0;
+ _zoom._dstTop = 0;
+ _zoom._width = w;
+ _zoom._height = h;
+}
+
+// Original name: CLView_CenterIn
+void View::centerIn(View *parent) {
+ _normal._dstLeft = (parent->_width - _normal._width) / 2;
+ _normal._dstTop = (parent->_height - _normal._height) / 2;
+ _zoom._dstLeft = (parent->_width - _zoom._width) / 2;
+ _zoom._dstTop = (parent->_height - _zoom._height) / 2;
+}
+
+///// CLPalette
+uint16 gIntervalLast, gIntervalFirst, gIntervalSet;
+int16 gMacintize = 0;
+color_t black_palette[256];
+color_t last_palette[256];
+
+void CLPalette_Init() {
+ for (int16 i = 0; i < 256; i++)
+ black_palette[i].r = black_palette[i].g = black_palette[i].b = 0;
+}
+
+void CLPalette_SetLastPalette(color_t *palette, int16 first, int16 count) {
+ for (int16 i = first; i < first + count; i++)
+ last_palette[i] = palette[i];
+}
+
+void CLPalette_GetLastPalette(color_t *palette) {
+ for (int16 i = 0; i < 256; i++)
+ palette[i] = last_palette[i];
+}
+
+void CLPalette_SetRGBColor(color_t *palette, uint16 index, color3_t *rgb) {
+ palette[index].r = rgb->r;
+ palette[index].g = rgb->g;
+ palette[index].b = rgb->b;
+ palette[index].a = 0;
+}
+
+void CLPalette_Macintize(int16 macintize) {
+ gMacintize = macintize;
+}
+
+void CLPalette_SetInterval(uint16 first, uint16 last) {
+ gIntervalFirst = first;
+ gIntervalSet = 1;
+ gIntervalLast = last;
+}
+
+void CLPalette_DeactivateInterval() {
+ gIntervalSet = 0;
+}
+
+void CLPalette_Send2Screen(struct color_t *palette, uint16 first, uint16 count) {
+ if (gMacintize) {
+ palette[0].r = palette[0].g = palette[0].b = 0xFFFF;
+ palette[255].r = palette[255].g = palette[255].b = 0;
+ }
+ if (gIntervalSet) {
+ if (first < gIntervalFirst)
+ first = gIntervalFirst;
+ if (first + count > gIntervalLast)
+ count = gIntervalLast - first;
+ }
+
+ byte buffer[256 * 3];
+ for (int i = 0; i < 256; i++) {
+ buffer[i * 3] = palette[i].r >> 8;
+ buffer[i * 3 + 1] = palette[i].g >> 8;
+ buffer[i * 3 + 2] = palette[i].b >> 8;
+ }
+
+ g_system->getPaletteManager()->setPalette(buffer, first, count);
+ g_system->updateScreen();
+
+ CLPalette_SetLastPalette(palette, first, count);
+}
+
+void CLPalette_BeSystem() {
+}
+
+///// CLBlitter
+static uint16 newPaletteCount, newPaletteFirst;
+static color_t *pNewPalette;
+static bool useNewPalette;
+
+void CLBlitter_CopyViewRect(View *view1, View *view2, Common::Rect *rect1, Common::Rect *rect2) {
+ int dy = rect2->top;
+ int w = rect1->right - rect1->left + 1;
+ // debug("- Copy rect %3d:%3d-%3d:%3d -> %3d:%3d-%3d:%3d - %s",
+ // rect1->sx, rect1->sy, rect1->ex, rect1->ey,
+ // rect2->sx, rect2->sy, rect2->ex, rect2->ey,
+ // (rect1->ex - rect1->sx == rect2->ex - rect2->sx && rect1->ey - rect1->sy == rect2->ey - rect2->sy) ? "ok" : "BAD");
+ assert(rect1->right - rect1->left == rect2->right - rect2->left && rect1->bottom - rect1->top == rect2->bottom - rect2->top);
+ for (int sy = rect1->top; sy <= rect1->bottom; sy++, dy++) {
+ byte *s = view1->_bufferPtr + sy * view1->_pitch + rect1->left;
+ byte *d = view2->_bufferPtr + dy * view2->_pitch + rect2->left;
+ for (int x = 0; x < w; x++)
+ *d++ = *s++;
+ }
+}
+
+void CLBlitter_Send2ScreenNextCopy(color_t *palette, uint16 first, uint16 count) {
+ pNewPalette = palette;
+ useNewPalette = true;
+ newPaletteFirst = first;
+ newPaletteCount = count;
+}
+
+void CLBlitter_OneBlackFlash() {
+}
+
+void CLBlitter_CopyView2ViewSimpleSize(byte *src, int16 srcw, int16 srcp, int16 srch,
+ byte *dst, int16 dstw, int16 dstp, int16 dsth) {
+ for (int16 y = 0; y < srch; y++) {
+ for (int16 x = 0; x < srcw; x++)
+ *dst++ = *src++;
+ src += srcp - srcw;
+ dst += dstp - dstw;
+ }
+}
+
+void CLBlitter_CopyView2ScreenCUSTOM(View *view) {
+ View *dest = g_ed->_screenView;
+ int16 srcpitch = view->_pitch;
+ int16 dstpitch = dest->_pitch;
+
+ CLBlitter_CopyView2ViewSimpleSize(view->_bufferPtr + view->_normal._srcTop * srcpitch + view->_normal._srcLeft,
+ view->_normal._width, srcpitch, view->_normal._height,
+ dest->_bufferPtr + (dest->_normal._dstTop + view->_normal._dstTop) * dstpitch + dest->_normal._dstLeft + view->_normal._dstLeft,
+ dest->_normal._width, dstpitch, dest->_normal._height);
+}
+
+void CLBlitter_CopyView2Screen(View *view) {
+ if (useNewPalette) {
+ color_t palette[256];
+ CLPalette_GetLastPalette(palette);
+ CLPalette_Send2Screen(pNewPalette, newPaletteFirst, newPaletteCount);
+ useNewPalette = false;
+ }
+
+ //HACK: Quick hack to force screen update
+ if (view)
+ CLBlitter_CopyView2ScreenCUSTOM(view);
+
+ g_system->copyRectToScreen(g_ed->_screenView->_bufferPtr, g_ed->_screenView->_pitch, 0, 0, g_ed->_screenView->_width, g_ed->_screenView->_height);
+ g_system->updateScreen();
+}
+
+void CLBlitter_UpdateScreen() {
+ CLBlitter_CopyView2Screen(nullptr);
+}
+
+void CLBlitter_FillView(View *view, unsigned int fill) {
+ byte *d = view->_bufferPtr;
+ assert((fill & 0xFF) * 0x01010101 == fill);
+
+ for (int16 y = 0; y < view->_height; y++) {
+ for (int16 x = 0; x < view->_width; x++)
+ *d++ = fill;
+ d += view->_pitch - view->_width;
+ }
+}
+
+void CLBlitter_FillScreenView(unsigned int fill) {
+ CLBlitter_FillView(g_ed->_screenView, fill);
+}
+
+///// events wrapper
+int _mouseButton;
+byte _keyState[256];
+
+void CryoEngine::pollEvents() {
+ g_system->delayMillis(10);
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ // Handle keypress
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ return;
+
+ case Common::EVENT_KEYDOWN:
+ // Check for debugger
+ if ((event.kbd.keycode == Common::KEYCODE_d) && (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _debugger->attach();
+ _debugger->onFrame();
+ }
+ return;
+ case Common::EVENT_KEYUP:
+ // _keyState[(byte)toupper(event.kbd.ascii)] = false;
+ return;
+ case Common::EVENT_LBUTTONDOWN:
+ _mouseButton = 1;
+ return;
+ case Common::EVENT_RBUTTONDOWN:
+ _mouseButton = 2;
+ return;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ _mouseButton = 0;
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+void CryoEngine::hideMouse() {
+}
+
+void CryoEngine::showMouse() {
+}
+
+void CryoEngine::getMousePosition(int16 *x, int16 *y) {
+ *x = g_system->getEventManager()->getMousePos().x;
+ *y = g_system->getEventManager()->getMousePos().y;
+}
+
+void CryoEngine::setMousePosition(int16 x, int16 y) {
+ g_system->warpMouse(x, y);
+}
+
+bool CryoEngine::isMouseButtonDown() {
+ pollEvents();
+ return _mouseButton != 0;
+}
+
+///// CLSound
+// base sound
+
+Sound::Sound(int16 length, float rate, int16 sampleSize, int16 mode) {
+ _sndHandle = nullptr;
+ _headerLen = 0;
+ _headerOffset = 0;
+
+ _length = 0;
+ _mode = 0;
+ _volume = 0;
+
+ _maxLength = length;
+ _rate = rate;
+ _sampleSize = sampleSize;
+ _buffer = nullptr;
+ // sndHandle = CLMemory_AllocHandle(arg1 + 100);
+ // if(!sndHandle)
+ // error("CLSoundRaw_New - Not enough memory");
+ // else
+ prepareSample(mode);
+}
+
+Sound::~Sound() {
+}
+
+void CLSoundRaw_AssignBuffer(Sound *sound, void *buffer, int bufferOffs, int length) {
+ sound->_length = length;
+ char *buf = bufferOffs + (char *)buffer;
+ // if(CLSound_GetWantsDesigned())
+ // CLSound_Signed2NonSigned(buf, length);
+ sound->_buffer = buf;
+ // if(sound->reversed && sound->sampleSize == 16)
+ // ReverseBlock16(buf, length);
+}
+
+void Sound::prepareSample(int16 mode) {
+ _mode = mode;
+ _volume = 255;
+}
+
+void Sound::setWantsDesigned(int16 designed) {
+}
+
+///// CLSoundChannel
+/// sound output device that plays queue of sounds
+SoundChannel::SoundChannel(int arg1) {
+ _volumeLeft = _volumeRight = 255;
+ _numSounds = 0;
+
+ for (int16 i = 0; i < kCryoMaxChSounds; i++)
+ _sounds[i] = nullptr;
+}
+
+SoundChannel::~SoundChannel() {
+}
+
+void SoundChannel::stop() {
+ // _vm->_mixer->stopHandle(this);
+}
+
+void SoundChannel::play(Sound *sound) {
+}
+
+int16 SoundChannel::getVolume() {
+ return (_volumeLeft + _volumeRight) / 2;
+}
+
+void SoundChannel::setVolume(int16 volume) {
+ if (volume < 0 || volume > 255)
+ return;
+
+ _volumeLeft = volume;
+ _volumeRight = volume;
+}
+
+void SoundChannel::setVolumeRight(int16 volume) {
+ if (volume < 0 || volume > 255)
+ return;
+
+ _volumeRight = volume;
+}
+
+void SoundChannel::setVolumeLeft(int16 volume) {
+ if (volume < 0 || volume > 255)
+ return;
+
+ _volumeLeft = volume;
+}
+
+///// CLTimer
+void CLTimer_Action(void *arg) {
+ // long& counter = *((long*)arg);
+ // counter++;
+ g_ed->_timerTicks++;
+}
+
+///// CRYOLib
+void CRYOLib_ManagersInit() {
+ g_system->getTimerManager()->installTimerProc(CLTimer_Action, 10000, nullptr, "100hz timer");
+ g_ed->_screenView->initDatas(g_ed->_screen.w, g_ed->_screen.h, g_ed->_screen.getPixels());
+}
+
+void CRYOLib_ManagersDone() {
+ g_system->getTimerManager()->removeTimerProc(CLTimer_Action);
+}
+
+PakHeaderNode::PakHeaderNode(int count) {
+ _count = count;
+ _files = new PakHeaderItem[count];
+}
+
+PakHeaderNode::~PakHeaderNode() {
+ _count = 0;
+ delete[] _files;
+}
+
+} // End of namespace Cryo
diff --git a/engines/cryo/cryolib.h b/engines/cryo/cryolib.h
new file mode 100644
index 0000000000..83fdfee236
--- /dev/null
+++ b/engines/cryo/cryolib.h
@@ -0,0 +1,175 @@
+/* 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.
+ *
+ */
+
+#ifndef CRYO_CRYOLIB_H
+#define CRYO_CRYOLIB_H
+
+#include "audio/mixer.h"
+#include "common/system.h"
+
+#include "cryo/platdefs.h"
+
+namespace Cryo {
+
+class CryoEngine;
+
+#define SW16(n) ( (((n) & 0xFF) << 8) | (((n) >> 8) & 0xFF) )
+#define SW32(n) ( (((n) & 0xFF) << 24) | (((n) >> 24) & 0xFF) | (((n) & 0xFF00) << 8) | (((n) >> 8) & 0xFF00))
+#ifdef SCUMM_BIG_ENDIAN
+//big-endian host
+#define LE16(n) SW16(n)
+#define LE32(n) SW32(n)
+#define BE16(n) (n)
+#define BE32(n) (n)
+#else
+//little-endian host
+#define LE16(n) (n)
+#define LE32(n) (n)
+#define BE16(n) SW16(n)
+#define BE32(n) SW32(n)
+#endif
+
+enum {
+ fsFromStart = 1
+};
+
+struct BlitView{
+ int _srcLeft;
+ int _srcTop;
+ int _dstLeft;
+ int _dstTop;
+ int _width;
+ int _height;
+};
+
+class View {
+public:
+ View(int w, int h);
+ ~View();
+
+ void setSrcZoomValues(int x, int y);
+ void setDisplayZoomValues(int w, int h);
+ void initDatas(int w, int h, void *buffer);
+ void centerIn(View *parent);
+
+ int _width;
+ int _height;
+ byte *_bufferPtr;
+ int16 _pitch;
+ BlitView _normal;
+ BlitView _zoom;
+};
+
+struct color3_t {
+ uint16 r, g, b;
+};
+
+struct color_t {
+ uint16 a, r, g, b;
+};
+
+struct HNMHeader {
+ int32 _signature;
+ uint16 _width;
+ uint16 _height;
+ int32 _numbFrame;
+ int32 _bufferSize;
+};
+
+class Sound {
+private:
+ int32 _headerOffset;
+ int16 _mode;
+ int16 _volume;
+
+public:
+ Sound(int16 length, float rate, int16 sampleSize, int16 mode);
+ ~Sound();
+
+ void assignBuffer(void *buffer, int bufferOffs, int length);
+ void prepareSample(int16 mode);
+ void setWantsDesigned(int16 designed);
+
+ char *_sndHandle;
+ char *_buffer;
+
+ float _rate;
+
+ int16 _maxLength;
+ int16 _headerLen;
+ int16 _sampleSize;
+
+ int _length;
+};
+
+#define kCryoMaxChSounds 10
+
+class SoundChannel {
+private:
+ int16 _volumeLeft;
+ int16 _volumeRight;
+ int16 _numSounds;
+
+ Sound *_sounds[kCryoMaxChSounds];
+
+public:
+ SoundChannel(int arg1);
+ ~SoundChannel();
+
+ void stop();
+ void play(Sound *sound);
+ int16 getVolume();
+ void setVolume(int16 volume);
+ void setVolumeRight(int16 volume);
+ void setVolumeLeft(int16 volume);
+};
+
+void SysBeep(int x);
+void FlushEvents(int16 arg1, int16 arg2);
+
+void CLBlitter_CopyViewRect(View *view1, View *view2, Common::Rect *rect1, Common::Rect *rect2);
+void CLBlitter_Send2ScreenNextCopy(color_t *palette, uint16 first, uint16 count);
+void CLBlitter_OneBlackFlash();
+void CLBlitter_CopyView2ViewSimpleSize(byte *src, int16 srcw, int16 srcp, int16 srch,
+ byte *dst, int16 dstw, int16 dstp, int16 dsth);
+void CLBlitter_CopyView2ScreenCUSTOM(View *view);
+void CLBlitter_CopyView2Screen(View *view);
+void CLBlitter_UpdateScreen();
+void CLBlitter_FillView(View *view, unsigned int fill);
+void CLBlitter_FillScreenView(unsigned int fill);
+
+void CLPalette_Init();
+void CLPalette_SetLastPalette(color_t *palette, int16 first, int16 count);
+void CLPalette_GetLastPalette(color_t *palette);
+void CLPalette_SetRGBColor(color_t *palette, uint16 index, color3_t *rgb);
+void CLPalette_Macintize(int16 macintize);
+void CLPalette_SetInterval(uint16 first, uint16 last);
+void CLPalette_DeactivateInterval();
+void CLPalette_Send2Screen(struct color_t *palette, uint16 first, uint16 count);
+void CLPalette_BeSystem();
+
+void CRYOLib_ManagersInit();
+void CRYOLib_ManagersDone();
+
+} // End of namespace Cryo
+
+#endif
diff --git a/engines/cryo/debugger.cpp b/engines/cryo/debugger.cpp
new file mode 100644
index 0000000000..f19c616b72
--- /dev/null
+++ b/engines/cryo/debugger.cpp
@@ -0,0 +1,64 @@
+/* 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.
+ *
+ */
+
+#include "common/coroutines.h"
+#include "cryo/debugger.h"
+#include "cryo/cryo.h"
+
+namespace Cryo {
+
+Debugger::Debugger(CryoEngine *vm) : GUI::Debugger(), _vm(vm) {
+ registerCmd("showHotspots", WRAP_METHOD(Debugger, Cmd_ShowHotspots));
+ registerCmd("fullInventory", WRAP_METHOD(Debugger, Cmd_FullInventory));
+}
+
+/**
+ * This command enables/disables hotspot display
+ */
+bool Debugger::Cmd_ShowHotspots(int argc, const char **argv) {
+ if (argc != 1) {
+ debugPrintf("Usage: %s\n", argv[0]);
+ return true;
+ }
+
+ _vm->_showHotspots ^= 1;
+
+ return false;
+}
+
+bool Debugger::Cmd_FullInventory(int argc, const char **argv) {
+ if (argc != 1) {
+ debugPrintf("Usage: %s\n", argv[0]);
+ return true;
+ }
+
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ object_t *object = _vm->_game->getObjectPtr(i);
+ object->_flags |= ObjectFlags::ofFlag1;
+ object->_count++;
+ }
+
+ _vm->_game->showObjects();
+
+ return false;
+}
+} // End of namespace Cryo
diff --git a/engines/titanic/sound/music_wave.cpp b/engines/cryo/debugger.h
index 560fdd7513..ee765128ce 100644
--- a/engines/titanic/sound/music_wave.cpp
+++ b/engines/cryo/debugger.h
@@ -20,35 +20,29 @@
*
*/
-#include "titanic/sound/music_wave.h"
-#include "titanic/sound/sound_manager.h"
-#include "titanic/core/project_item.h"
+#ifndef CRYO_DEBUGGER_H
+#define CRYO_DEBUGGER_H
-namespace Titanic {
+#include "common/scummsys.h"
+#include "gui/debugger.h"
-CMusicWave::CMusicWave(CProjectItem *project, CSoundManager *soundManager, int index) :
- _soundManager(soundManager) {
-}
+namespace Cryo {
-void CMusicWave::setSize(uint count) {
- assert(_items.empty());
- _items.resize(count);
-}
+class CryoEngine;
-void CMusicWave::load(int index, const CString &filename, int v3) {
- assert(!_items[index]._waveFile);
- _items[index]._waveFile = createWaveFile(filename);
- _items[index]._value = v3;
-}
+class Debugger : public GUI::Debugger {
+private:
+ CryoEngine *_vm;
-CWaveFile *CMusicWave::createWaveFile(const CString &name) {
- if (name.empty())
- return nullptr;
- return _soundManager->loadSound(name);
-}
+public:
+ Debugger(CryoEngine *vm);
+ virtual ~Debugger() {}
-void CMusicWave::stop() {
+protected:
+ bool Cmd_ShowHotspots(int argc, const char **argv);
+ bool Cmd_FullInventory(int argc, const char **argv);
+};
-}
+} // End of namespace Cryo
-} // End of namespace Titanic
+#endif
diff --git a/engines/cryo/defs.h b/engines/cryo/defs.h
new file mode 100644
index 0000000000..617172d6e6
--- /dev/null
+++ b/engines/cryo/defs.h
@@ -0,0 +1,816 @@
+/* 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.
+ *
+ */
+
+#include "cryo/cryolib.h"
+
+#ifndef CRYO_DEFS_H
+#define CRYO_DEFS_H
+
+namespace Cryo {
+
+#define getElem(array, idx) \
+ ( (char *)(array) + READ_LE_UINT16((idx) * 2 + (char *)(array)) )
+
+///////////////// Game defs
+
+#define FONT_HEIGHT 9
+
+/*
+Glossary
+ room - a single game world's screen. referenced by 16-bit number 0xAALL, where AA - area# and LL - location#
+ area - geographic area - Mo, Chamaar, etc
+ location - coordinates of particular room in an area. usually in form of 0xXY, where X - map row, Y - map column
+ character - an unique character (human or dino.) Has their own voice/dialog lines
+ person - instance of a character. Usually tied to specific room, but some may travel with you
+ party - a group of characters that travel with you
+ object - inventory item
+ icon - clickable rectangle with some action tied to it
+ dialog - a set of of dialog lines for character. further divided by categories and each entry may have associated
+ condition to be validated
+ global - game-wide storage area. must be preserved when saving/loading
+ phase - current story progress. Incremented by 1 for minor events, by 0x10 for major advancements
+*/
+
+enum Phases {
+ phNewGame = 0
+};
+
+namespace Areas {
+enum Areas {
+ arMo = 1,
+ arTausCave,
+ arChamaar,
+ arUluru,
+ arKoto,
+ arTamara,
+ arCantura,
+ arShandovra,
+ arNarimsCave,
+ arEmbalmersCave,
+ arWhiteArch,
+ arMoorkusLair
+};
+}
+
+#define MKRM(a,l) (((a) << 8) | (l))
+
+enum OBJECT {
+ OBJ_0,
+ OBJ_1,
+ OBJ_2,
+ OBJ_3,
+ OBJ_4,
+ OBJ_PRISME, // 5
+ OBJ_6,
+ OBJ_7,
+ OBJ_OEUF, // 8
+ OBJ_9,
+ OBJ_10,
+ OBJ_CHAMPB, // 11
+ OBJ_CHAMPM, // 12
+ OBJ_COUTEAU, // 13
+ OBJ_NIDV, // 14
+ OBJ_NIDO, // 15
+ OBJ_OR, // 16
+ OBJ_17,
+ OBJ_18,
+ OBJ_SOLEIL, // 19
+ OBJ_CORNE, // 20
+ OBJ_21,
+ OBJ_22,
+ OBJ_23,
+ OBJ_24,
+ OBJ_25,
+ OBJ_26,
+ OBJ_27,
+ OBJ_28,
+ OBJ_29,
+ OBJ_30,
+ OBJ_31,
+ OBJ_32,
+ OBJ_33,
+ OBJ_34,
+ OBJ_35,
+ OBJ_36, // 36 is 1st plaque, 6 total
+ OBJ_37,
+ OBJ_PLAQUE, // 38
+ OBJ_39,
+ OBJ_40,
+ OBJ_41
+};
+
+namespace Objects {
+enum Objects {
+ obNone,
+ obWayStone,
+ obShell,
+ obTalisman,
+ obTooth,
+ obPrism, // 5
+ obFlute,
+ obApple,
+ obEgg, // 8
+ obRoot,
+ obUnused10,
+ obShroom, // 11
+ obBadShroom, // 12
+ obKnife, // 13
+ obNest, // 14
+ obFullNest, // 15
+ obGold, // 16
+ obMoonStone,
+ obBag,
+ obSunStone, // 19
+ obHorn, // 20
+ obSword,
+
+ obMaskOfDeath,
+ obMaskOfBonding,
+ obMaskOfBirth,
+
+ obEyeInTheStorm, // 25
+ obSkyHammer,
+ obFireInTheClouds,
+ obWithinAndWithout,
+ obEyeInTheCyclone,
+ obRiverThatWinds,
+
+ obTrumpet, // 31
+ obUnused32,
+ obDrum,
+ obUnused34,
+ obUnused35,
+ obRing,
+
+ obTablet1, // 37 is 1st plaque, 6 total
+ obTablet2,
+ obTablet3, // 39
+ obTablet4,
+ obTablet5,
+ obTablet6
+};
+}
+
+enum PERSO {
+ PER_KING = 0,
+ PER_DINA, // 0x12
+ PER_TAU, // 0x24
+ PER_MONK, // 0x36
+ PER_JABBER, // 0x48
+ PER_ELOI, // 0x5A
+ PER_MUNGO, // 0x6C
+ PER_EVE, // 0x7E
+ PER_SHAZIA, // 0x90
+ PER_MAMMI, // 0xA2
+ PER_MAMMI_1, // 0xB4
+ PER_MAMMI_2, // 0xC6
+ PER_MAMMI_3, // 0xD8
+ PER_MAMMI_4, // 0xEA
+ PER_MAMMI_5, // 0xFC
+ PER_MAMMI_6, // 0x10E
+ PER_BAMBOO, // 0x120
+ PER_KABUKA, // 0x132
+ PER_GUARDS, // 0x144
+ PER_UNKN_156, // 0x156
+ PER_FISHER, // 0x168
+ PER_MORKUS, // 0x17A
+ PER_UNKN_18C, // 0x18C
+ PER_UNKN_19E, // 0x19E
+ PER_UNKN_1B0, // 0x1B0
+ PER_UNKN_1C2, // 0x1C2
+ PER_UNKN_1D4, // 0x1D4
+ PER_UNKN_1E6, // 0x1E6
+ PER_UNKN_1F8, // 0x1F8
+ PER_UNKN_20A, // 0x20A
+ PER_UNKN_21C, // 0x21C
+ PER_UNKN_22E, // 0x22E
+ PER_UNKN_240, // 0x240
+ PER_UNKN_252, // 0x252
+ PER_UNKN_264, // 0x264
+ PER_UNKN_276, // 0x276
+ PER_UNKN_288, // 0x288
+ PER_UNKN_29A, // 0x29A
+ PER_UNKN_2AC, // 0x2AC
+ PER_UNKN_2BE, // 0x2BE
+ PER_UNKN_2D0, // 0x2D0
+ PER_UNKN_2E2, // 0x2E2
+ PER_UNKN_2F4, // 0x2F4
+ PER_UNKN_306, // 0x306
+ PER_UNKN_318, // 0x318
+ PER_UNKN_32A, // 0x32A
+ PER_UNKN_33C, // 0x33C
+ PER_UNKN_34E, // 0x34E
+ PER_UNKN_360, // 0x360
+ PER_UNKN_372, // 0x372
+ PER_UNKN_384, // 0x384
+ PER_UNKN_396, // 0x396
+ PER_UNKN_3A8, // 0x3A8
+ PER_UNKN_3BA, // 0x3BA
+ PER_UNKN_3CC, // 0x3CC
+ PER_UNKN_3DE, // 0x3DE
+ PER_UNKN_3F0, // 0x3F0
+ PER_UNKN_402 // 0x402
+};
+
+namespace PersonId {
+enum PersonId {
+ pidGregor = 0, // The King
+ pidDina, // Pink dino
+ pidTau, // Late grandpa
+ pidMonk, // Old wizard
+ pidJabber, // Executioner
+ pidEloi, // Evergreen ptero
+ pidMungo, // Dina's husband
+ pidEve, // Blonde girl
+ pidShazia, // Big boobs sis
+ pidLeadersBegin, // 9
+ pidChongOfChamaar = pidLeadersBegin, // Dogface
+ pidKommalaOfKoto, // Clones
+ pidUlanOfUlele, // Shaman
+ pidCabukaOfCantura, // Stone people
+ pidMarindaOfEmbalmers, // Gods
+ pidFuggOfTamara, // Boar-like
+ pidThugg, // Bodyguard
+ pidNarrator, // 16, Old Eloi, also BGM
+ pidNarrim, // Sea snake
+ pidMorkus, // Vicious tyran
+ pidDinosaur, // different species of friendly dino
+ pidEnemy // different species of enemy dino
+};
+}
+
+// person in room mask bits
+namespace PersonMask {
+enum PersonMask {
+ pmGregor = 1,
+ pmDina = 2,
+ pmTau = 4,
+ pmMonk = 8,
+ pmJabber = 0x10,
+ pmEloi = 0x20,
+ pmMungo = 0x40,
+ pmEve = 0x80,
+ pmShazia = 0x100,
+ pmLeader = 0x200, // valley tribe leader
+ pmThugg = 0x400,
+ pmQuest = 0x800, // special quest person
+ pmDino = 0x1000,
+ pmEnemy = 0x2000,
+ pmMorkus = 0x4000
+};
+}
+
+namespace PersonFlags {
+enum PersonFlags {
+ pfType0 = 0,
+ pftTyrann,
+ pfType2,
+ pfType3,
+ pfType4,
+ pfType5,
+ pfType6,
+ pfType7,
+ pfType8,
+ pftMosasaurus,
+ pftTriceraptor,
+ pftVelociraptor,
+ pfType12,
+ pfType13,
+ pfType14,
+ pfType15,
+ pfTypeMask = 0xF,
+ pf10 = 0x10,
+ pf20 = 0x20,
+ pfInParty = 0x40,
+ pf80 = 0x80
+};
+}
+
+#pragma pack(push, 1)
+struct perso_t {
+ uint16 _roomNum; // room this person currently in
+ uint16 _actionId; // TODO: checkme
+ uint16 _partyMask; // party bit mask
+ byte _id; // character
+ byte _flags; // flags and kind
+ byte _roomBankId;// index in _personRoomBankTable for specific room banks
+ byte _spriteBank; // sprite bank
+ uint16 _items; // inventory
+ uint16 _powers; // obj of power bitmask
+ byte _targetLoc; // For party member this is mini sprite index
+ byte _lastLoc; // For party member this is mini sprite x offset
+ byte _speed; // num ticks per step
+ byte _steps; // current ticks
+};
+
+class EdenGame;
+
+struct phase_t {
+ int16 _id;
+ void (EdenGame::*disp)();
+};
+
+namespace ObjectFlags {
+enum ObjectFlags {
+ ofFlag1 = 1,
+ ofInHands = 2 // Currently holding this object in hands
+};
+}
+
+#define MAX_OBJECTS 42
+struct object_t {
+ byte _id;
+ byte _flags;
+ int _locations; // index in _objectLocations
+ uint16 _itemMask;
+ uint16 _powerMask; // object of power bitmask
+ int16 _count;
+};
+
+namespace DialogFlags {
+enum DialogFlags {
+ df20 = 0x20,
+ dfRepeatable = 0x40,
+ dfSpoken = 0x80
+};
+}
+
+namespace DialogType {
+enum DialogType {
+ dtTalk = 0,
+ dtDinoAction,
+ dtDinoItem,
+ dtItem,
+ dtEvent,
+ dtInspect,
+ dtHint
+};
+}
+
+struct Dialog {
+ char _flags; // 0-3 - action index, 4 - highest bit of contidion index, rest is DialogFlags
+ char _condNumLow; // condition index low bits
+ char _textCondHiMask; // 0-1 text index hi bits, 2-5 - perso mask num, 6-7 condition index hi bits
+ char _textNumLow; // text line index low bits
+};
+
+struct tape_t {
+ int16 _textNum;
+ perso_t *_perso;
+ int16 _party;
+ int16 _roomNum;
+ int16 _backgroundBankNum;
+ Dialog *_dialog;
+};
+
+struct Follower { // Characters on Mirror screen
+ char _id; // character
+ char _spriteNum; // sprite number
+ int16 sx;
+ int16 sy;
+ int16 ex;
+ int16 ey;
+ int16 _spriteBank;
+ int16 ff_C;
+ int16 ff_E;
+};
+
+struct Icon {
+ int16 sx;
+ int16 sy;
+ int16 ex;
+ int16 ey;
+ uint16 _cursorId; // & 0x8000 - inactive/hidden
+ uint32 _actionId;
+ uint32 _objectId;
+};
+
+struct Goto {
+ byte _areaNum; // target area
+ byte _curAreaNum; // current area
+ byte _enterVideoNum;
+ byte _travelTime; // time to skip while in travel
+ byte _arriveVideoNum;
+};
+
+namespace RoomFlags {
+enum RoomFlags {
+ rf01 = 1,
+ rf02 = 2,
+ rf04 = 4,
+ rf08 = 8,
+ rfPanable = 0x10,
+ rfHasCitadel = 0x20,
+ rf40 = 0x40,
+ rf80 = 0x80
+};
+}
+
+struct Room {
+ byte _id;
+ byte _exits[4]; //TODO: signed?
+ byte _flags;
+ uint16 _bank;
+ uint16 _party;
+ byte _level; // Citadel level
+ byte _video;
+ byte _location;
+ byte _backgroundBankNum; // bg/mirror image number (relative)
+};
+
+namespace AreaFlags {
+enum AreaFlags {
+ afFlag1 = 1,
+ afFlag2 = 2,
+ afFlag4 = 4,
+ afFlag8 = 8,
+ afGaveGold = 0x10,
+ afFlag20 = 0x20,
+
+ HasTriceraptors = 0x100,
+ HasVelociraptors = 0x200,
+ HasTyrann = 0x400,
+
+ TyrannSighted = 0x4000,
+ afFlag8000 = 0x8000
+};
+}
+
+namespace AreaType {
+enum AreaType {
+ atCitadel = 1,
+ atValley = 2,
+ atCave = 3
+};
+}
+
+struct Area {
+ byte _num;
+ byte _type;
+ uint16 _flags;
+ uint16 _firstRoomIdx;
+ byte _citadelLevel;
+ byte _placeNum;
+ Room *_citadelRoomPtr;
+ int16 _visitCount;
+};
+
+namespace ValleyNews {
+enum ValleyNews {
+ vnAreaMask = 0xF,
+
+ vnTriceraptorsIn = 0x10,
+ vnVelociraptorsIn = 0x20,
+ vnTyrannIn = 0x30,
+ vnTyrannLost = 0x40,
+ vnCitadelLost = 0x50,
+ vnVelociraptorsLost = 0x60,
+
+ vnFree = 0,
+ vnHidden = 0x80,
+ vnEnd = 0xFF
+};
+}
+
+namespace DisplayFlags {
+enum DisplayFlags {
+ dfFlag1 = 1,
+ dfFlag2 = 2,
+ dfMirror = 4,
+ dfPerson = 8,
+ dfFrescoes = 0x10,
+ dfPanable = 0x20,
+ dfFlag40 = 0x40,
+ dfFlag80 = 0x80
+};
+}
+
+namespace DrawFlags {
+enum DrawFlags {
+ drDrawInventory = 1,
+ drDrawFlag2 = 2,
+ drDrawTopScreen = 4,
+ drDrawFlag8 = 8,
+ drDrawMenu = 0x10,
+ drDrawFlag20 = 0x20
+};
+}
+
+namespace MenuFlags {
+enum MenuFlags {
+ mfFlag1 = 1,
+ mfFlag2 = 2,
+ mfFlag4 = 4,
+ mfFlag8 = 8,
+ mfFlag10 = 0x10
+};
+}
+
+namespace MusicType {
+enum MusicType { //TODO: same as DialogType?
+ mtDontChange = 0,
+ mtNormal = 1,
+ mt2 = 2,
+ mtEvent = 4,
+ mtFF = 0xFF
+};
+}
+
+namespace EventType {
+enum EventType {
+ etEvent1 = 1,
+ etEvent2 = 2,
+ etEvent3 = 3,
+ etEvent4 = 4,
+ etEvent5 = 5,
+ etEvent6 = 6,
+ etEvent7 = 7,
+ etEvent8 = 8,
+ etEvent9 = 9,
+ etEventB = 11,
+ etEventC = 12,
+ etEventD = 13,
+ etEventE = 14,
+ etEventF = 15,
+ etEvent10 = 16,
+ etEvent12 = 18,
+ etGotoArea = 0x80 // + area id
+};
+}
+
+namespace GameFlags {
+enum GameFlags {
+ gfNone = 0,
+ gfMummyOpened = 1,
+ gfFlag2 = 2,
+ gfFlag4 = 4,
+ gfFlag8 = 8,
+ gfFlag10 = 0x10,
+ gfFlag20 = 0x20,
+ gfFlag40 = 0x40,
+ gfFlag80 = 0x80,
+ gfFlag100 = 0x100,
+ gfFlag200 = 0x200,
+ gfFlag400 = 0x400,
+ gfPrismAndMonk = 0x800,
+ gfFlag1000 = 0x1000,
+ gfFlag2000 = 0x2000,
+ gfFlag4000 = 0x4000,
+ gfFlag8000 = 0x8000
+};
+}
+
+struct global_t {
+ byte _areaNum;
+ byte _areaVisitCount;
+ byte _menuItemIdLo;
+ byte _menuItemIdHi; //TODO: pad?
+ uint16 _randomNumber; //TODO: this is randomized in pc ver and used by some conds. always zero on mac
+ uint16 _gameTime;
+ uint16 _gameDays;
+ uint16 _chrono;
+ uint16 _eloiDepartureDay;
+ uint16 _roomNum; // current room number
+ uint16 _newRoomNum; // target room number selected on world map
+ uint16 _phaseNum;
+ uint16 _metPersonsMask1;
+ uint16 _party;
+ uint16 _partyOutside;
+ uint16 _metPersonsMask2;
+ uint16 _var1C; //TODO: write-only?
+ uint16 _phaseActionsCount;
+ uint16 _curAreaFlags;
+ uint16 _curItemsMask;
+ uint16 _curPowersMask;
+ uint16 _curPersoItems;
+ uint16 _curCharacterPowers;
+ uint16 _wonItemsMask;
+ uint16 _wonPowersMask;
+ uint16 _stepsToFindAppleFast;
+ uint16 _stepsToFindAppleNormal;
+ uint16 _roomPersoItems; //TODO: write-only?
+ uint16 _roomCharacterPowers; //TODO: write-only?
+ uint16 _gameFlags;
+ uint16 _curVideoNum;
+ uint16 _morkusSpyVideoNum1; //TODO: pad?
+ uint16 _morkusSpyVideoNum2; //TODO: pad?
+ uint16 _morkusSpyVideoNum3; //TODO: pad?
+ uint16 _morkusSpyVideoNum4; //TODO: pad?
+ byte _newMusicType;
+ byte _var43;
+ byte _videoSubtitleIndex;
+ byte _partyInstruments; // &1 - Bell for Monk, &2 - Drum for Thugg
+ byte _monkGotRing;
+ byte _chronoFlag;
+ byte _curRoomFlags;
+ byte _endGameFlag;
+ byte _lastInfo;
+ bool _autoDialog;
+ byte _worldTyranSighted;
+ byte _var4D;
+ byte _var4E;
+ byte _worldGaveGold;
+ byte _worldHasTriceraptors;
+ byte _worldHasVelociraptors;
+ byte _worldHasTyran;
+ byte _var53;
+ byte _var54; //CHEKME: Used?
+ byte _var55; //TODO: pad?
+ byte _gameHours;
+ byte _textToken1;
+ byte _textToken2; //TODO: pad?
+ byte _eloiHaveNews;
+ byte _dialogFlags;
+ byte _curAreaType;
+ byte _curCitadelLevel;
+ byte _newLocation;
+ byte _prevLocation;
+ byte _curPersoFlags;
+ byte _var60;
+ byte _eventType;
+ byte _var62; //TODO: pad?
+ byte _curObjectId;
+ byte _curObjectFlags;
+ byte _var65; //TODO: pad?
+ byte _roomCharacterType;
+ byte _roomCharacterFlags;
+ byte _narratorSequence;
+ byte _var69;
+ byte _var6A;
+ byte _frescoNumber;
+ byte _var6C; //TODO: pad?
+ byte _var6D; //TODO: pad?
+ byte _labyrinthDirections;
+ byte _labyrinthRoom;
+ Dialog *_dialogPtr;
+ tape_t *_tapePtr;
+ Dialog *_nextDialogPtr;
+ Dialog *_narratorDialogPtr;
+ Dialog *_lastDialogPtr;
+ Icon *_nextRoomIcon;
+ byte *_sentenceBufferPtr;
+ Room *_roomPtr;
+ Area *_areaPtr;
+ Area *_lastAreaPtr;
+ Area *_curAreaPtr;
+ Room *_citaAreaFirstRoom;
+ perso_t *_characterPtr;
+ perso_t *_roomCharacterPtr;
+ byte _lastInfoIdx;
+ byte _nextInfoIdx;
+ byte *_persoSpritePtr;
+ byte *_persoSpritePtr2;
+ byte *_curCharacterAnimPtr;
+ byte *_varC2; //TODO: image desc arr
+ int16 _iconsIndex;
+ int16 _curObjectCursor; // TODO: useless?
+ int16 _varCA;
+ int16 _varCC; //TODO: unused/pad
+ int16 _characterImageBank; //TODO: unsigned?
+ uint16 _roomImgBank;
+ uint16 _characterBackgroundBankIdx;
+ uint16 _varD4; //TODO: unsigned?
+ uint16 _frescoeWidth;
+ uint16 _frescoeImgBank;
+ uint16 _varDA; //TODO: pad?
+ uint16 _varDC; //TODO: pad?
+ uint16 _roomBaseX;
+ uint16 _varE0; //TODO: pad?
+ uint16 _dialogType;
+ uint16 _varE4; //TODO: pad?
+ uint16 _currMusicNum;
+ int16 _textNum;
+ uint16 _travelTime;
+ uint16 _varEC; //TODO: pad?
+ byte _displayFlags;
+ byte _oldDisplayFlags;
+ byte _drawFlags;
+ byte _varF1;
+ byte _varF2;
+ byte _menuFlags;
+ byte _varF4; //TODO: write-only?
+ byte _varF5;
+ byte _varF6;
+ byte _varF7;
+ byte _varF8; //TODO: pad?
+ byte _varF9; //TODO: pad?
+ byte _varFA; //TODO: pad?
+ byte _animationFlags;
+ byte _giveObj1;
+ byte _giveObj2;
+ byte _giveObj3;
+ byte _var100;
+ byte _roomVidNum;
+ byte _mirrorEffect;
+ byte _var103;
+ byte _roomBackgroundBankNum;
+ byte _valleyVidNum;
+ byte _updatePaletteFlag;
+ byte _inventoryScrollPos;
+ byte _objCount;
+ byte _textBankIndex;
+ byte _prefLanguage;
+ byte _prefMusicVol[2];
+ byte _prefVoiceVol[2];
+ byte _prefSoundVolume[2];
+ byte _citadelAreaNum;
+ byte _var113;
+ byte _lastPlaceNum;
+ byte _saveEnd; // TODO: This has to be removed
+ int16 _textWidthLimit;
+ byte _numGiveObjs;
+ byte _var119; // unused
+};
+
+struct PakHeaderItem {
+ Common::String _name; //[16];
+ int32 _size;
+ int32 _offs;
+ char _flag;
+};
+
+class PakHeaderNode {
+public:
+ PakHeaderNode(int count);
+ ~PakHeaderNode();
+
+ uint16 _count;
+ PakHeaderItem* _files;
+};
+#pragma pack(pop)
+
+struct Citadel {
+ int16 _id;
+ int16 _bank[8];
+ int16 _video[8];
+};
+
+/*
+ Labyrinth of Mo
+
+ | | | | | | | |
+
+*/
+
+enum {
+ LAB_N = 1,
+ LAB_E,
+ LAB_S,
+ LAB_W
+};
+
+struct CubeFace {
+ int tri;
+ char ff_4;
+ char ff_5;
+
+ byte *_texturePtr;
+ uint16 *_indices;
+ int16 *_uv;
+};
+
+struct Point3D {
+ int16 x;
+ int16 y;
+ int16 z;
+};
+
+struct Cube {
+ int _num;
+ CubeFace **_faces;
+ Point3D *_projection; // projected XYZ coords
+ Point3D *_vertices;
+};
+
+struct XYZ {
+ signed short x, y, z;
+};
+
+struct CubeCursor {
+ uint8 _sides[6]; // spr idx for each side
+ uint8 _kind;
+ int8 _speed;
+};
+
+} // End of namespace Cryo
+
+#endif
diff --git a/engines/cryo/detection.cpp b/engines/cryo/detection.cpp
new file mode 100644
index 0000000000..2ae01f41dd
--- /dev/null
+++ b/engines/cryo/detection.cpp
@@ -0,0 +1,166 @@
+/* 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.
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+#include "common/file.h"
+
+#include "cryo/cryo.h"
+
+
+namespace Cryo {
+
+const char *CryoEngine::getGameId() const { return _gameDescription->gameId; }
+bool CryoEngine::isDemo() const { return _gameDescription->flags & ADGF_DEMO; }
+Common::Platform CryoEngine::getPlatform() const { return _gameDescription->platform; }
+
+}
+
+static const PlainGameDescriptor cryoGames[] = {
+ {"losteden", "Lost Eden"},
+ {0, 0}
+};
+
+namespace Cryo {
+
+static const ADGameDescription gameDescriptions[] = {
+
+ // Lost Eden PC non-interactive demo version
+ // Probably not worth it
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN6.HSQ", 0, 17093),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden PC interactive demo version
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", 0, 205473728),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden PC version
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", 0, 449853776),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden EN PC version
+ // Added by Strangerke
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", "2126f14fe38b47c7a132f7937c79a2f0", 451205552),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden FR PC version
+ // Added by Strangerke
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", "378b1260ac400ecf35f8843357adcca6", 448040496),
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden DE PC version
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", 0, 457719104),
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
+
+ // Lost Eden Mac version
+ {
+ "losteden",
+ 0,
+ AD_ENTRY1s("EDEN.DAT", 0, 489739536),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+} // End of namespace Cryo
+
+class CryoMetaEngine : public AdvancedMetaEngine {
+public:
+ CryoMetaEngine() : AdvancedMetaEngine(Cryo::gameDescriptions, sizeof(ADGameDescription), cryoGames) {
+ _singleId = "losteden";
+ }
+
+ virtual const char *getName() const {
+ return "Cryo Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Cryo Engine (C) Cryo Interactive";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+};
+
+bool CryoMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+}
+
+bool CryoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new Cryo::CryoEngine(syst, desc);
+ }
+ return desc != 0;
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(CRYO)
+REGISTER_PLUGIN_DYNAMIC(CRYO, PLUGIN_TYPE_ENGINE, CryoMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(CRYO, PLUGIN_TYPE_ENGINE, CryoMetaEngine);
+#endif
diff --git a/engines/cryo/eden.cpp b/engines/cryo/eden.cpp
new file mode 100644
index 0000000000..a9476f8199
--- /dev/null
+++ b/engines/cryo/eden.cpp
@@ -0,0 +1,7802 @@
+/* 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "gui/EventRecorder.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/fs.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+#include "graphics/screen.h"
+#include "graphics/palette.h"
+#include "common/timer.h"
+#include "audio/mixer.h"
+
+#include "cryo/defs.h"
+#include "cryo/cryo.h"
+#include "cryo/platdefs.h"
+#include "cryo/cryolib.h"
+#include "cryo/eden.h"
+#include "cryo/sound.h"
+
+namespace Cryo {
+
+#define Z_RESET -3400
+#define Z_STEP 200
+#define Z_UP 1
+#define Z_DOWN -1
+
+EdenGame::EdenGame(CryoEngine *vm) : _vm(vm), kMaxMusicSize(2200000) {
+ static uint8 statTab2CB1E[8][4] = {
+ { 0x10, 0x81, 1, 0x90},
+ { 0x90, 1, 0x81, 0x10},
+ { 1, 0x90, 0x10, 0x81},
+ { 1, 0x10, 0x90, 0x81},
+ { 1, 0x90, 0x10, 0x81},
+ { 0x81, 0x10, 0x90, 1},
+ { 0x81, 0x10, 0x90, 1},
+ { 0x81, 0x90, 1, 0x10}
+ };
+
+ _adamMapMarkPos = Common::Point(-1, -1);
+
+ _scrollPos = _oldScrollPos = 0;
+ _frescoTalk = false;
+ _torchCursor = false;
+ _curBankNum = 0;
+ _glowH = _glowW = _glowY = _glowX = 0;
+ _paletteUpdateRequired = false;
+ _cursorSaved = false;
+ _showBlackBars = false;
+ _backgroundSaved = false;
+ _bankData = nullptr;
+ _tyranPtr = nullptr;
+ _lastAnimFrameNumb = _curAnimFrameNumb = 0;
+ _lastAnimTicks = 0;
+ _curCharacterRect = nullptr;
+ _numAnimFrames = _maxPersoDesc = _numImgDesc = 0;
+ _restartAnimation = _animationActive = false;
+ _animationDelay = _animationIndex = _lastAnimationIndex = 0;
+ dword_30724 = dword_30728 = _mouthAnimations = _animationTable = nullptr;
+ _characterBankData = nullptr;
+ _savedUnderSubtitles = false;
+ _numTextLines = 0;
+ _textOutPtr = textout = nullptr;
+ _curSpecialObject = nullptr;
+ _lastDialogChoice = false;
+ parlemoiNormalFlag = false;
+ _closeCharacterDialog = false;
+ dword_30B04 = 0;
+ _lastPhrasesFile = 0;
+ _dialogSkipFlags = 0;
+ _voiceSamplesBuffer = nullptr;
+ _needToFade = false;
+ _mainBankBuf = nullptr;
+ _musicBuf = nullptr;
+ _gameLipsync = nullptr;
+ _gamePhrases = nullptr;
+ _gameDialogs = nullptr;
+ _gameConditions = nullptr;
+ _placeRawBuf = nullptr;
+ _bankDataBuf = nullptr;
+ _gameIcons = nullptr;
+ _gameRooms = nullptr;
+ _glowBuffer = nullptr;
+ _gameFont = nullptr;
+ _globals = nullptr;
+ _mouseCenterY = _mouseCenterX = 0;
+ _bufferAllocationErrorFl = _quitFlag2 = _quitFlag3 = false;
+ _gameStarted = false;
+ _soundAllocated = false;
+ _musicChannel = _voiceChannel = nullptr;
+ _hnmSoundChannel = nullptr;
+ _voiceSound = nullptr;
+ _view2 = _underSubtitlesView = _subtitlesView = _underBarsView = _mainView = _hnmView = nullptr;
+ _cirsorPanX = 0;
+ _inventoryScrollDelay = 0;
+ _cursorPosY = _cursorPosX = 0;
+ _currCursor = 0;
+ _currSpot = _curSpot2 = nullptr;
+ _mouseHeld = false;
+ _normalCursor = false;
+ _showVideoSubtitle = false;
+ _specialTextMode = false;
+ _voiceSamplesSize = 0;
+ _animateTalking = false;
+ _personTalking = false;
+ _musicFadeFlag = 0;
+ _musicPlayingFlag = false;
+ _musicSamplesPtr = _musicPatternsPtr = _musSequencePtr = nullptr;
+ _musicEnabledFlag = false;
+ _currentObjectLocation = nullptr;
+ byte_31D64 = false;
+ _noPalette = false;
+ _gameLoaded = false;
+ memset(_tapes, 0, sizeof(_tapes));
+ _confirmMode = 0;
+ _curSliderValuePtr = nullptr;
+ _lastMenuItemIdLo = 0;
+ _lastTapeRoomNum = 0;
+ _curSliderX = _curSliderY = 0;
+ _destinationRoom = 0;
+ word_31E7A = 0;
+ word_378CC = 0; //TODO: set by CLComputer_Init to 0
+ word_378CE = 0;
+
+ _rotationAngleY = _rotationAngleX = _rotationAngleZ = 0;
+ _translationY = _translationX = 0.0; //TODO: never changed, make consts?
+ _cursorOldTick = 0;
+
+ _invIconsBase = 19;
+// invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11;
+ _invIconsCount = 11;
+ _roomIconsBase = _invIconsBase + _invIconsCount;
+
+ _codePtr = nullptr;
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 4; j++)
+ tab_2CB1E[i][j] = statTab2CB1E[i][j];
+ }
+
+ _translationZ = Z_RESET;
+ _zDirection = Z_UP;
+
+ _torchTick = 0;
+ _glowIndex = 0;
+ _torchCurIndex = 0;
+ _cursCenter = 11;
+}
+
+void EdenGame::removeConsole() {
+}
+
+void EdenGame::scroll() {
+ restoreFriezes();
+ _mainView->_normal._srcLeft = _scrollPos;
+ _mainView->_zoom._srcLeft = _scrollPos;
+}
+
+void EdenGame::resetScroll() {
+ _oldScrollPos = _scrollPos;
+ _scrollPos = 0;
+ restoreFriezes(); //TODO: inlined scroll() ?
+ _mainView->_normal._srcLeft = 0;
+ _mainView->_zoom._srcLeft = 0;
+}
+
+void EdenGame::scrollFrescoes() {
+ if (_cursorPosY > 16 && _cursorPosY < 176) {
+ if (_cursorPosX >= 0 && _cursorPosX < 32 && _scrollPos > 3)
+ _scrollPos -= 4;
+ else if (_cursorPosX > 288 && _cursorPosX < 320 && _scrollPos < _globals->_frescoeWidth)
+ _scrollPos += 4;
+ }
+ scroll();
+}
+
+// Original name: afffresques
+void EdenGame::displayFrescoes() {
+ useBank(_globals->_frescoeImgBank);
+ drawSprite(0, 0, 16);
+ useBank(_globals->_frescoeImgBank + 1);
+ drawSprite(0, 320, 16);
+ _paletteUpdateRequired = true;
+}
+
+void EdenGame::gametofresques() {
+ _frescoTalk = false;
+ rundcurs();
+ saveFriezes();
+ displayFrescoes();
+ _globals->_displayFlags = DisplayFlags::dfFrescoes;
+}
+
+// Original name: dofresques
+void EdenGame::doFrescoes() {
+ _cursorSaved = false;
+ _torchCursor = true;
+ _glowX = -1;
+ _glowY = -1;
+ _globals->_gameFlags |= GameFlags::gfFlag20;
+ _globals->_varD4 = 0;
+ _globals->_curObjectId = 0;
+ _globals->_iconsIndex = 13;
+ _globals->_autoDialog = false;
+ gametofresques();
+ _globals->_frescoNumber = 3;
+}
+
+// Original name: finfresques
+void EdenGame::actionEndFrescoes() {
+ _torchCursor = false;
+ _cursorSaved = true;
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ resetScroll();
+ _globals->_var100 = 0xFF;
+ updateRoom(_globals->_roomNum);
+ if (_globals->_phaseNum == 114)
+ _globals->_narratorSequence = 1;
+ _globals->_eventType = EventType::etEvent8;
+ showEvents();
+}
+
+void EdenGame::scrollMirror() {
+ if (_cursorPosY > 16 && _cursorPosY < 165) {
+ if (_cursorPosX >= 0 && _cursorPosX < 16) {
+ if (_scrollPos > 3) {
+ _scrollPos--;
+ scroll();
+ }
+ } else if (_cursorPosX > 290 && _cursorPosX < 320) {
+ if (_scrollPos < 320) {
+ _scrollPos++;
+ scroll();
+ }
+ }
+ }
+}
+
+// Original name: scrollpano
+void EdenGame::scrollPanel() {
+ if (_cursorPosY > 16 && _cursorPosY < 165) {
+ if (_cursorPosX >= 0 && _cursorPosX < 16 && _scrollPos > 3)
+ _scrollPos--;
+ else if (_cursorPosX > 290 && _cursorPosX < 320 && _scrollPos < 320)
+ _scrollPos++;
+ }
+ scroll();
+}
+
+// Original name: affsuiveur
+void EdenGame::displayFollower(Follower *follower, int16 x, int16 y) {
+ useBank(follower->_spriteBank);
+ drawSprite(follower->_spriteNum, x, y + 16);
+}
+
+// Original name: persoinmiroir
+void EdenGame::characterInMirror() {
+ Icon *icon1 = &_gameIcons[3];
+ Icon *icon = &_gameIcons[_roomIconsBase];
+ Follower *suiveur = _followerList;
+ int16 num = 1;
+ for (int i = 0; i < 16; i++) {
+ if (_globals->_party & (1 << i))
+ num++;
+ }
+ icon += num;
+ icon->sx = -1;
+ icon--;
+ icon->sx = icon1->sx;
+ icon->sy = icon1->sy;
+ icon->ex = icon1->ex;
+ icon->ey = 170;
+ icon->_cursorId = icon1->_cursorId;
+ icon->_actionId = icon1->_actionId;
+ icon->_objectId = icon1->_objectId;
+ icon--;
+ displayFollower(suiveur, suiveur->sx, suiveur->sy);
+ for (; suiveur->_id != -1; suiveur++) {
+ perso_t *perso;
+ for (perso = _persons; perso != &_persons[PER_UNKN_156]; perso++) {
+ if (perso->_id != suiveur->_id)
+ continue;
+
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+
+ if ((perso->_flags & PersonFlags::pfInParty) == 0)
+ continue;
+
+ if (perso->_roomNum != _globals->_roomNum)
+ continue;
+
+ icon->sx = suiveur->sx;
+ icon->sy = suiveur->sy;
+ icon->ex = suiveur->ex;
+ icon->ey = suiveur->ey;
+ icon->_cursorId = 8;
+ icon->_actionId = perso->_actionId;
+ icon--;
+ displayFollower(suiveur, suiveur->sx, suiveur->sy);
+ break;
+ }
+ }
+}
+
+// Original name: gametomiroir
+void EdenGame::gameToMirror(byte arg1) {
+ if (_globals->_displayFlags != DisplayFlags::dfFlag2) {
+ rundcurs();
+ restoreFriezes();
+ drawTopScreen();
+ showObjects();
+ saveFriezes();
+ }
+ int16 bank = _globals->_roomBackgroundBankNum;
+ uint16 resNum = bank + 326;
+ if ((_vm->getPlatform() == Common::kPlatformMacintosh) && (bank == 76 || bank == 128))
+ resNum = 2487; // PCIMG.HSQ
+
+ useBank(resNum);
+ drawSprite(0, 0, 16);
+ useBank(resNum + 1);
+ drawSprite(0, 320, 16);
+ characterInMirror();
+ _paletteUpdateRequired = true;
+ _globals->_iconsIndex = 16;
+ _globals->_autoDialog = false;
+ _globals->_displayFlags = DisplayFlags::dfMirror;
+ _globals->_mirrorEffect = arg1;
+}
+
+void EdenGame::flipMode() {
+ if (_personTalking) {
+ endCharacterSpeech();
+ if (_globals->_displayFlags == DisplayFlags::dfPerson) {
+ if (_globals->_characterPtr == &_persons[PER_TAU] && _globals->_phaseNum >= 80)
+ displaySubtitles();
+ else {
+ getDataSync();
+ loadCurrCharacter();
+ addanim();
+ _restartAnimation = true;
+ animCharacter();
+ }
+ } else
+ displaySubtitles();
+ persovox();
+ } else {
+ if (_globals->_displayFlags != DisplayFlags::dfFrescoes && _globals->_displayFlags != DisplayFlags::dfFlag2) {
+ closeRoom();
+ if (_globals->_displayFlags & DisplayFlags::dfFlag1)
+ gameToMirror(1);
+ else {
+ quitMirror();
+ updateRoom(_globals->_roomNum);
+ if (byte_31D64) {
+ dialautoon();
+ parle_moi();
+ byte_31D64 = false;
+ }
+ }
+ }
+ }
+}
+
+// Original name: quitmiroir
+void EdenGame::quitMirror() {
+ rundcurs();
+ display();
+ resetScroll();
+ saveFriezes();
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ _globals->_var100 = 0xFF;
+ _globals->_eventType = EventType::etEventC;
+ _globals->_mirrorEffect = 1;
+}
+
+void EdenGame::clictimbre() {
+ flipMode();
+}
+
+// Original name: clicplanval
+void EdenGame::actionClickValleyPlan() {
+ if ((_globals->_partyOutside & PersonMask::pmDina) && _globals->_phaseNum == 371) {
+ quitMirror();
+ updateRoom(_globals->_roomNum);
+ return;
+ }
+ if (_globals->_roomNum == 8 || _globals->_roomNum < 16)
+ return;
+
+ rundcurs();
+ display();
+ if (_globals->_displayFlags == DisplayFlags::dfMirror)
+ quitMirror();
+ deplaval((_globals->_roomNum & 0xFF00) | 1); //TODO: check me
+}
+
+// Original name: gotolieu
+void EdenGame::gotoPlace(Goto *go) {
+ _globals->_valleyVidNum = go->_arriveVideoNum;
+ _globals->_travelTime = go->_travelTime * 256;
+ _globals->_stepsToFindAppleFast = 0;
+ _globals->_eventType = EventType::etEvent2;
+ setChoiceYes();
+ showEvents();
+ if (!isAnswerYes())
+ return;
+
+ if (_globals->_var113) {
+ waitEndSpeak();
+ if (!_vm->shouldQuit())
+ closeCharacterScreen();
+ }
+ if (go->_enterVideoNum) {
+ hideBars();
+ playHNM(go->_enterVideoNum);
+ _needToFade = true;
+ }
+ initPlace(_globals->_newRoomNum);
+ specialoutside();
+ faire_suivre(_globals->_newRoomNum);
+ closeRoom();
+ _adamMapMarkPos.x = -1;
+ _adamMapMarkPos.y = -1;
+ addTime(_globals->_travelTime);
+ _globals->_var100 = _globals->_roomPtr->_id;
+ _globals->_roomNum = _globals->_newRoomNum;
+ _globals->_areaNum = _globals->_roomNum >> 8;
+ _globals->_eventType = EventType::etEvent5;
+ _globals->_newMusicType = MusicType::mt2;
+ setCharacterHere();
+ musique();
+ updateRoom1(_globals->_roomNum);
+ drawTopScreen();
+ _adamMapMarkPos.x = -1;
+ _adamMapMarkPos.y = -1;
+}
+
+void EdenGame::deplaval(uint16 roomNum) {
+ _globals->_newLocation = roomNum & 0xFF;
+ _globals->_valleyVidNum = 0;
+ _globals->_phaseActionsCount++;
+ closeRoom();
+ endCharacterSpeech();
+ byte c1 = roomNum & 0xFF;
+ if (c1 == 0)
+ return;
+
+ if (c1 < 0x80) {
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ setChoiceYes();
+ _globals->_eventType = EventType::etEvent1;
+ showEvents();
+ if (!isAnswerYes())
+ return;
+
+ if (_globals->_var113) {
+ waitEndSpeak();
+ if (!_vm->shouldQuit())
+ closeCharacterScreen();
+ }
+ specialout();
+ if (_globals->_areaPtr->_type == AreaType::atValley) {
+ addTime(32);
+ _globals->_stepsToFindAppleFast++;
+ _globals->_stepsToFindAppleNormal++;
+ }
+ faire_suivre((roomNum & 0xFF00) | _globals->_newLocation);
+ _globals->_var100 = _globals->_roomPtr->_id;
+ _globals->_roomNum = roomNum;
+ _globals->_areaNum = roomNum >> 8;
+ _globals->_eventType = EventType::etEvent5;
+ setCharacterHere();
+ _globals->_newMusicType = MusicType::mtNormal;
+ musique();
+ updateRoom1(roomNum);
+ _globals->_chronoFlag = 0;
+ _globals->_chrono = 0;
+ _globals->_var54 = 0;
+ if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
+ setChrono(3000);
+ return;
+ }
+ if (c1 == 0xFF) {
+ _globals->_eventType = EventType::etEventE;
+ showEvents();
+ if (!_persons[PER_ELOI]._roomNum && checkEloiReturn())
+ setChrono(800);
+ return;
+ }
+ _globals->_stepsToFindAppleFast = 0;
+ byte newAreaNum = c1 & 0x7F;
+ byte curAreaNum = _globals->_roomNum >> 8;
+ int16 newRoomNum = newAreaNum << 8;
+ if (curAreaNum == Areas::arTausCave && newAreaNum == Areas::arMo)
+ newRoomNum |= 0x16;
+ else if (curAreaNum == Areas::arMoorkusLair)
+ newRoomNum |= 4;
+ else
+ newRoomNum |= 1;
+ _globals->_newRoomNum = newRoomNum;
+ if (newAreaNum == Areas::arTausCave)
+ gotoPlace(&_gotos[0]);
+ else {
+ for (Goto *go = _gotos + 1; go->_curAreaNum != 0xFF; go++) {
+ if (go->_curAreaNum == curAreaNum) {
+ gotoPlace(go);
+ break;
+ }
+ }
+ }
+}
+
+// Original name: deplacement
+void EdenGame::move(Direction dir) {
+ Room *room = _globals->_roomPtr;
+ int16 roomNum = _globals->_roomNum;
+ debug("move: from room %4X", roomNum);
+ char newLoc = 0;
+ rundcurs();
+ display();
+ _globals->_prevLocation = roomNum & 0xFF;
+ switch (dir) {
+ case kCryoNorth:
+ newLoc = room->_exits[0];
+ break;
+ case kCryoEast:
+ newLoc = room->_exits[1];
+ break;
+ case kCryoSouth:
+ newLoc = room->_exits[2];
+ break;
+ case kCryoWest:
+ newLoc = room->_exits[3];
+ break;
+ }
+ deplaval((roomNum & 0xFF00) | newLoc);
+}
+
+// Original name: deplacement2
+void EdenGame::move2(Direction dir) {
+ Room *room = _globals->_roomPtr;
+ int16 roomNum = _globals->_roomNum;
+ char newLoc = 0;
+ _globals->_prevLocation = roomNum & 0xFF;
+ switch (dir) {
+ case kCryoNorth:
+ newLoc = room->_exits[0];
+ break;
+ case kCryoEast:
+ newLoc = room->_exits[1];
+ break;
+ case kCryoSouth:
+ newLoc = room->_exits[2];
+ break;
+ case kCryoWest:
+ newLoc = room->_exits[3];
+ break;
+ }
+ deplaval((roomNum & 0xFF00) | newLoc);
+}
+
+// Original name: dinosoufle
+void EdenGame::actionDinoBlow() {
+ if (_globals->_curObjectId == 0) {
+ hideBars();
+ playHNM(148);
+ maj2();
+ }
+}
+
+// Original name: plaquemonk
+void EdenGame::actionPlateMonk() {
+ if (_globals->_curObjectId != 0) {
+ if (_globals->_curObjectId == Objects::obPrism) {
+ loseObject(Objects::obPrism);
+ hideBars();
+ _specialTextMode = true;
+ playHNM(89);
+ // CHECKME: Unused code
+ // word_2F514 |= 0x8000;
+ maj2();
+ _globals->_eventType = EventType::etEventB;
+ showEvents();
+ }
+ } else {
+ hideBars();
+ playHNM(7);
+ maj2();
+ _globals->_eventType = EventType::etEvent4;
+ showEvents();
+ }
+}
+
+// Original name: fresquesgraa
+void EdenGame::actionGraaFrescoe() {
+ if (_globals->_curObjectId == 0) {
+ _globals->_frescoeWidth = 320;
+ _globals->_frescoeImgBank = 113;
+ doFrescoes();
+ handleDinaDialog();
+ }
+}
+
+// Original name: fresqueslasc
+void EdenGame::actionLascFrescoe() {
+ if (_globals->_curObjectId == 0) {
+ _globals->_frescoeWidth = 112;
+ _globals->_frescoeImgBank = 315;
+ doFrescoes();
+ }
+}
+
+// Original name: pushpierre
+void EdenGame::actionPushStone() {
+ if (_globals->_curObjectId == 0) {
+ _gameRooms[22]._exits[0] = 17;
+ _gameRooms[26]._exits[2] = 9;
+ move(kCryoNorth);
+ }
+}
+
+// Original name: tetemomie
+void EdenGame::actionMummyHead() {
+ if (_globals->_curObjectId == Objects::obTooth) {
+ _globals->_gameFlags |= GameFlags::gfMummyOpened;
+ move(kCryoNorth);
+ } else if (_globals->_curObjectId == 0) {
+ if (_globals->_gameFlags & GameFlags::gfMummyOpened)
+ move(kCryoNorth);
+ else {
+ _globals->_eventType = EventType::etEvent6;
+ handleCharacterDialog(PersonId::pidMonk);
+ _globals->_eventType = 0;
+ }
+ }
+}
+
+// Original name: tetesquel
+void EdenGame::actionSkelettonHead() {
+ if (_globals->_curObjectId == Objects::obTooth) {
+ _gameRooms[22]._exits[0] = 16;
+ _gameRooms[26]._exits[2] = 13;
+ _gameIcons[16]._cursorId |= 0x8000;
+ loseObject(Objects::obTooth);
+ move(kCryoNorth);
+ }
+}
+
+// Original name: squelmoorkong
+void EdenGame::actionSkelettonMoorkong() {
+ _globals->_eventType = EventType::etEvent9;
+ showEvents();
+}
+
+// Original name: choisir
+void EdenGame::actionChoose() {
+ byte objid = _curSpot2->_objectId;
+ byte obj;
+ switch (objid) {
+ case 0:
+ obj = _globals->_giveObj1;
+ break;
+ case 1:
+ obj = _globals->_giveObj2;
+ break;
+ case 2:
+ obj = _globals->_giveObj3;
+ break;
+ default:
+ warning("Unexpected objid in actionChoose()");
+ return;
+ }
+ objectmain(obj);
+ winObject(obj);
+ _globals->_iconsIndex = 16;
+ _globals->_autoDialog = false;
+ _globals->_var60 = 0;
+ parle_moi();
+}
+
+// Original name: dinaparle
+void EdenGame::handleDinaDialog() {
+ perso_t *perso = &_persons[PER_DINA];
+ if (perso->_partyMask & (_globals->_party | _globals->_partyOutside)) {
+ if (_globals->_frescoNumber < 3)
+ _globals->_frescoNumber = 3;
+ _globals->_frescoNumber++;
+ if (_globals->_frescoNumber < 15) {
+ endCharacterSpeech();
+ if (_globals->_frescoNumber == 7 && _globals->_phaseNum == 113)
+ incPhase();
+ _globals->_characterPtr = perso;
+ _globals->_dialogType = DialogType::dtInspect;
+ int16 num = (perso->_id << 3) | DialogType::dtInspect; //TODO: combine
+ bool res = dialoscansvmas((Dialog *)getElem(_gameDialogs, num));
+ _frescoTalk = false;
+ if (res) {
+ restoreUnderSubtitles();
+ _frescoTalk = true;
+ persovox();
+ }
+ _globals->_varCA = 0;
+ _globals->_dialogType = DialogType::dtTalk;
+ } else
+ actionEndFrescoes();
+ }
+}
+
+// Original name: roiparle
+void EdenGame::handleKingDialog() {
+ if (_globals->_phaseNum <= 400)
+ handleCharacterDialog(0);
+}
+
+// Original name: roiparle1
+void EdenGame::actionKingDialog1() {
+ if (_globals->_curObjectId == Objects::obSword) {
+ _globals->_gameFlags |= GameFlags::gfFlag80;
+ hideBars();
+ playHNM(76);
+ move2(kCryoNorth);
+ } else {
+ _globals->_frescoNumber = 1;
+ handleKingDialog();
+ }
+}
+
+// Original name: roiparle2
+void EdenGame::actionKingDialog2() {
+ _globals->_frescoNumber = 2;
+ handleKingDialog();
+}
+
+// Original name: roiparle3
+void EdenGame::actionKingDialog3() {
+ _globals->_frescoNumber = 3;
+ handleKingDialog();
+}
+
+// Original name: getcouteau
+void EdenGame::actionGetKnife() {
+ if (_globals->_phaseNum >= 80) {
+ _gameRooms[113]._video = 0;
+ getObject(Objects::obKnife);
+ }
+ _globals->_eventType = EventType::etEvent7;
+ showEvents();
+}
+
+// Original name: getprisme
+void EdenGame::actionGetPrism() {
+ getObject(Objects::obPrism);
+ _globals->_eventType = EventType::etEvent7;
+ showEvents();
+}
+
+// Original name: getchampb
+void EdenGame::actionGetMushroom() {
+ getObject(Objects::obShroom);
+}
+
+// Original name: getchampm
+void EdenGame::actionGetBadMushroom() {
+ getObject(Objects::obBadShroom);
+}
+
+// Original name: getor
+void EdenGame::actionGetGold() {
+ getObject(Objects::obGold);
+}
+
+// Original name: getnido
+void EdenGame::actionGetFullNest() {
+ if (_globals->_curObjectId != 0)
+ return;
+ _globals->_roomPtr->_bank = 282; //TODO: fix me
+ _globals->_roomPtr--;
+ _globals->_roomPtr->_bank = 281; //TODO: fix me
+ _globals->_roomPtr->_id = 3;
+ getObject(Objects::obFullNest);
+}
+
+// Original name: getnidv
+void EdenGame::actionGetEmptyNest() {
+ if (_globals->_curObjectId != 0)
+ return;
+ _globals->_roomPtr->_bank = 282; //TODO: fix me
+ _globals->_roomPtr--;
+ _globals->_roomPtr->_bank = 281; //TODO: fix me
+ _globals->_roomPtr->_id = 3;
+ getObject(Objects::obNest);
+}
+
+// Original name: getcorne
+void EdenGame::actionGetHorn() {
+ if (_globals->_curObjectId != 0)
+ return;
+ getObject(Objects::obHorn);
+ _globals->_eventType = EventType::etEvent7;
+ showEvents();
+ bigphase1();
+ setCharacterHere();
+ _globals->_roomPtr = getRoom(_globals->_roomNum);
+}
+
+// Original name: getsoleil
+void EdenGame::actionGetSunStone() {
+ if (_globals->_curObjectId != 0)
+ return;
+ _gameRooms[238]._video = 0;
+ _gameRooms[238]._flags = RoomFlags::rf80;
+ getObject(Objects::obSunStone);
+}
+
+// Original name: getoueuf
+void EdenGame::actionGetEgg() {
+ if (_globals->_curObjectId != 0)
+ return;
+ _globals->_roomPtr->_flags = 0;
+ _globals->_roomPtr->_video = 0;
+ getObject(Objects::obEgg);
+}
+
+// Original name: getplaque
+void EdenGame::actionGetTablet() {
+ if (_globals->_curObjectId != 0 && _globals->_curObjectId < Objects::obTablet1)
+ return;
+ _globals->_curObjectId = 0;
+ getObject(Objects::obTablet2);
+ putObject();
+ for (int i = 0; i < 6; i++)
+ _objects[Objects::obTablet1 - 1 + i]._count = 0;
+ _globals->_curObjectFlags = 0;
+ _globals->_inventoryScrollPos = 0;
+ _globals->_curObjectCursor = 9;
+ _gameIcons[16]._cursorId |= 0x8000;
+ showObjects();
+ _gameRooms[131]._video = 0;
+ hideBars();
+ playHNM(149);
+ _globals->_varF1 = RoomFlags::rf04;
+ _globals->_drawFlags = DrawFlags::drDrawFlag20;
+ _normalCursor = true;
+ maj2();
+}
+
+// Original name: voirlac
+void EdenGame::actionLookLake() {
+ perso_t *perso = &_persons[PER_MORKUS];
+ Room *room = _globals->_roomPtr;
+ Area *area = _globals->_areaPtr;
+ int16 vid = _globals->_curObjectId == Objects::obApple ? 81 : 54;
+ for (++perso; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_roomNum != _globals->_roomNum)
+ continue;
+ vid++;
+ if (_globals->_curObjectId != Objects::obApple)
+ continue; //TODO: pc breaks here
+ if ((perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftMosasaurus)
+ continue;
+ if (!(perso->_flags & PersonFlags::pf80))
+ return;
+ perso->_flags &= ~PersonFlags::pf80; //TODO: useless? see above
+ area->_flags |= AreaFlags::afFlag8;
+ _globals->_curAreaFlags |= AreaFlags::afFlag8;
+ room->_id = 3;
+ }
+ debug("sea monster: room = %X, d0 = %X\n", _globals->_roomNum, _globals->_roomImgBank);
+ hideBars();
+ playHNM(vid);
+ updateRoom(_globals->_roomNum); //TODO: getting memory trashed here?
+ if (_globals->_curObjectId == Objects::obApple)
+ loseObject(Objects::obApple);
+ _globals->_eventType = EventType::etEventF;
+ showEvents();
+}
+
+// Original name: gotohall
+void EdenGame::actionGotoHall() {
+ _globals->_prevLocation = _globals->_roomNum & 0xFF;
+ deplaval((_globals->_roomNum & 0xFF00) | 6);
+}
+
+// Original name: demitourlabi
+void EdenGame::actionLabyrinthTurnAround() {
+ _globals->_prevLocation = _globals->_roomNum & 0xFF;
+ _globals->_var100 = 0xFF;
+ uint16 target = (_globals->_roomNum & 0xFF00) | _globals->_roomPtr->_exits[2];
+ faire_suivre(target);
+ _globals->_roomNum = target;
+ _globals->_eventType = EventType::etEvent5;
+ updateRoom(_globals->_roomNum);
+}
+
+// Original name: gotonido
+void EdenGame::actionGotoFullNest() {
+ _globals->_roomPtr++;
+ _globals->_eventType = 0;
+ _globals->_roomImgBank = _globals->_roomPtr->_bank;
+ _globals->_roomVidNum = _globals->_roomPtr->_video;
+ _globals->_curRoomFlags = _globals->_roomPtr->_flags;
+ _globals->_varF1 = _globals->_roomPtr->_flags;
+ animpiece();
+ _globals->_var100 = 0;
+ maj2();
+}
+
+// Original name: gotoval
+void EdenGame::actionGotoVal() {
+ uint16 target = _globals->_roomNum;
+ rundcurs();
+ display();
+ _scrollPos = 0;
+ char obj = _curSpot2->_objectId - 14; //TODO
+ _globals->_prevLocation = target & 0xFF;
+ deplaval((target & 0xFF00) | obj);
+}
+
+// Original name: visiter
+void EdenGame::actionVisit() {
+ hideBars();
+ playHNM(144);
+ _globals->_varF1 = RoomFlags::rf04;
+ maj2();
+}
+
+// Original name: final
+void EdenGame::actionFinal() {
+ if (_globals->_curObjectId != 0)
+ return;
+
+ hideBars();
+ *(int16 *)(_gameRooms + 0x6DC) = 319; //TODO
+ _globals->_roomImgBank = 319;
+ playHNM(97);
+ maj2();
+ _globals->_eventType = EventType::etEvent12;
+ showEvents();
+ _globals->_narratorSequence = 54;
+}
+
+// Original name: goto_nord
+void EdenGame::actionMoveNorth() {
+ if (_globals->_curObjectId == 0)
+ move(kCryoNorth);
+}
+
+// Original name: goto_est
+void EdenGame::actionMoveEast() {
+ if (_globals->_curObjectId == 0)
+ move(kCryoEast);
+}
+
+// Original name: goto_sud
+void EdenGame::actionMoveSouth() {
+ if (_globals->_curObjectId == 0)
+ move(kCryoSouth);
+}
+
+// Original name: goto_ouest
+void EdenGame::actionMoveWest() {
+ if (_globals->_curObjectId == 0)
+ move(kCryoWest);
+}
+
+// Original name: afficher
+void EdenGame::display() {
+ if (!_globals->_mirrorEffect && !_globals->_var103) {
+ if (_paletteUpdateRequired) {
+ _paletteUpdateRequired = false;
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+ }
+ CLBlitter_CopyView2Screen(_mainView);
+ } else {
+ if (_globals->_mirrorEffect)
+ displayEffect3();
+ else
+ displayEffect2();
+
+ _globals->_var103 = 0;
+ _globals->_mirrorEffect = 0;
+ }
+}
+
+void EdenGame::afficher128() {
+ if (_globals->_updatePaletteFlag == 16) {
+ CLPalette_Send2Screen(_globalPalette, 0, 129);
+ CLBlitter_CopyView2Screen(_mainView);
+ _globals->_updatePaletteFlag = 0;
+ } else {
+ clearScreen();
+ fadeToBlackLowPalette(1);
+ if (_showBlackBars)
+ drawBlackBars();
+ CLBlitter_CopyView2Screen(_mainView);
+ fadeFromBlackLowPalette(1);
+ }
+}
+
+// Original name: sauvefrises
+void EdenGame::saveFriezes() {
+ saveTopFrieze(0);
+ saveBottomFrieze();
+}
+
+// Original name: sauvefriseshaut
+void EdenGame::saveTopFrieze(int16 x) { // Save top bar
+ _underTopBarScreenRect = Common::Rect(x, 0, x + 320 - 1, 15);
+ _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 15);
+ CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+}
+
+// Original name: sauvefrisesbas
+void EdenGame::saveBottomFrieze() { // Save bottom bar
+ _underBottomBarScreenRect.left = 0;
+ _underBottomBarScreenRect.right = 320 - 1;
+ CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect);
+}
+
+// Original name: restaurefrises
+void EdenGame::restoreFriezes() {
+ restoreTopFrieze();
+ restoreBottomFrieze();
+}
+
+// Original name: restaurefriseshaut
+void EdenGame::restoreTopFrieze() {
+ _underTopBarScreenRect.left = _scrollPos;
+ _underTopBarScreenRect.right = _scrollPos + 320 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarBackupRect, &_underTopBarScreenRect);
+}
+
+// Original name: restaurefrisesbas
+void EdenGame::restoreBottomFrieze() {
+ _underBottomBarScreenRect.left = _scrollPos;
+ _underBottomBarScreenRect.right = _scrollPos + 320 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underBottomBarBackupRect, &_underBottomBarScreenRect);
+}
+
+void EdenGame::useMainBank() {
+ _bankData = _mainBankBuf;
+}
+
+void EdenGame::useCharacterBank() {
+ _bankData = _characterBankData;
+}
+
+// Original name: use_bank
+void EdenGame::useBank(int16 bank) {
+ if (bank > 2500)
+ error("attempt to load bad bank %d", bank);
+
+ _bankData = _bankDataBuf;
+ if (_curBankNum != bank) {
+ loadRawFile(bank, _bankDataBuf);
+ verifh(_bankDataBuf);
+ _curBankNum = bank;
+ }
+}
+
+void EdenGame::readPalette(byte *ptr) {
+ bool doit = true;
+ color3_t pal_entry;
+ while (doit) {
+ uint16 idx = *ptr++;
+ if (idx != 0xFF) {
+ uint16 cnt = *ptr++;
+ while (cnt--) {
+ if (idx == 0) {
+ pal_entry.r = 0;
+ pal_entry.g = 0;
+ pal_entry.b = 0;
+ ptr += 3;
+ } else {
+ pal_entry.r = *ptr++ << 10;
+ pal_entry.g = *ptr++ << 10;
+ pal_entry.b = *ptr++ << 10;
+ }
+ CLPalette_SetRGBColor(_globalPalette, idx, &pal_entry);
+ idx++;
+ }
+ } else
+ doit = false;
+ }
+}
+
+// Original name: sauvefondbouche
+void EdenGame::saveMouthBackground() {
+ rect_src.left = _curCharacterRect->left;
+ rect_src.top = _curCharacterRect->top;
+ rect_src.right = _curCharacterRect->right;
+ rect_src.bottom = _curCharacterRect->bottom;
+ rect_dst.left = _curCharacterRect->left + 320;
+ rect_dst.top = _curCharacterRect->top;
+ rect_dst.right = _curCharacterRect->right + 320;
+ rect_dst.bottom = _curCharacterRect->bottom;
+ CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst);
+ _backgroundSaved = true;
+}
+
+// Original name: restaurefondbouche
+void EdenGame::restoreMouthBackground() {
+ rect_src.left = _curCharacterRect->left;
+ rect_src.top = _curCharacterRect->top;
+ rect_src.right = _curCharacterRect->right;
+ rect_src.bottom = _curCharacterRect->bottom;
+ rect_dst.left = _curCharacterRect->left + 320;
+ rect_dst.top = _curCharacterRect->top;
+ rect_dst.right = _curCharacterRect->right + 320;
+ rect_dst.bottom = _curCharacterRect->bottom;
+ CLBlitter_CopyViewRect(_mainView, _mainView, &rect_dst, &rect_src);
+}
+
+void EdenGame::drawTopScreen() { // Draw top bar (location / party / map)
+ _globals->_drawFlags &= ~DrawFlags::drDrawTopScreen;
+ useBank(314);
+ drawSprite(36, 83, 0);
+ drawSprite(_globals->_areaPtr->_num - 1, 0, 0);
+ drawSprite(23, 145, 0);
+ for (perso_t *perso = &_persons[PER_DINA]; perso != &_persons[PER_UNKN_156]; perso++) {
+ if ((perso->_flags & PersonFlags::pfInParty) && !(perso->_flags & PersonFlags::pf80))
+ drawSprite(perso->_targetLoc + 18, perso->_lastLoc + 120, 0);
+ }
+ _adamMapMarkPos.x = -1;
+ _adamMapMarkPos.y = -1;
+ displayValleyMap();
+ _paletteUpdateRequired = true;
+}
+
+// Original name: affplanval
+void EdenGame::displayValleyMap() { // Draw mini-map
+ if (_globals->_areaPtr->_type == AreaType::atValley) {
+ drawSprite(_globals->_areaPtr->_num + 9, 266, 1);
+ for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
+ if (((perso->_roomNum >> 8) == _globals->_areaNum)
+ && !(perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pf20))
+ displayMapMark(33, perso->_roomNum & 0xFF);
+ }
+ if (_globals->_areaPtr->_citadelLevel)
+ displayMapMark(34, _globals->_areaPtr->_citadelRoomPtr->_location);
+ saveTopFrieze(0);
+ int16 loc = _globals->_roomNum & 0xFF;
+ if (loc >= 16)
+ displayAdamMapMark(loc);
+ restoreTopFrieze();
+ } else {
+ saveTopFrieze(0);
+ restoreTopFrieze();
+ }
+}
+
+// Original name: affrepere
+void EdenGame::displayMapMark(int16 index, int16 location) {
+ drawSprite(index, 269 + location % 16 * 4, 2 + (location - 16) / 16 * 3);
+}
+
+// Original name: affrepereadam
+void EdenGame::displayAdamMapMark(int16 location) {
+ int16 x = 269;
+ int16 y = 2;
+ restoreAdamMapMark();
+ if (location > 15 && location < 76) {
+ x += (location & 15) * 4;
+ y += ((location - 16) >> 4) * 3;
+ saveAdamMapMark(x, y);
+ byte *pix = _underBarsView->_bufferPtr;
+ int16 w = _underBarsView->_width;
+ pix += x + w * y;
+ pix[1] = 0xC3;
+ pix[2] = 0xC3;
+ pix += w;
+ pix[0] = 0xC3;
+ pix[1] = 0xC3;
+ pix[2] = 0xC3;
+ pix[3] = 0xC3;
+ pix += w;
+ pix[1] = 0xC3;
+ pix[2] = 0xC3;
+ }
+}
+
+// Original name: rest_repadam
+void EdenGame::restoreAdamMapMark() {
+ if (_adamMapMarkPos.x == -1 && _adamMapMarkPos.y == -1)
+ return;
+
+ int16 x = _adamMapMarkPos.x;
+ int16 y = _adamMapMarkPos.y;
+ byte *pix = _underBarsView->_bufferPtr;
+ int16 w = _underBarsView->_width;
+ pix += x + w * y;
+ pix[1] = _oldPix[0];
+ pix[2] = _oldPix[1];
+ pix += w;
+ pix[0] = _oldPix[2];
+ pix[1] = _oldPix[3];
+ pix[2] = _oldPix[4];
+ pix[3] = _oldPix[5];
+ pix += w;
+ pix[1] = _oldPix[6];
+ pix[2] = _oldPix[7];
+}
+
+// Original name: save_repadam
+void EdenGame::saveAdamMapMark(int16 x, int16 y) {
+ _adamMapMarkPos.x = x;
+ _adamMapMarkPos.y = y;
+ byte *pix = _underBarsView->_bufferPtr;
+ int16 w = _underBarsView->_width;
+ pix += x + w * y;
+ _oldPix[0] = pix[1];
+ _oldPix[1] = pix[2];
+ pix += w;
+ _oldPix[2] = pix[0];
+ _oldPix[3] = pix[1];
+ _oldPix[4] = pix[2];
+ _oldPix[5] = pix[3];
+ pix += w;
+ _oldPix[6] = pix[1];
+ _oldPix[7] = pix[2];
+}
+
+bool EdenGame::istrice(int16 roomNum) {
+ char loc = roomNum & 0xFF;
+ int16 area = roomNum & 0xFF00;
+ for (perso_t *perso = &_persons[PER_UNKN_18C]; perso != &_persons[PER_UNKN_372]; perso++) {
+ if ((perso->_flags & PersonFlags::pf80) || (perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftTriceraptor)
+ continue;
+ if (perso->_roomNum == (area | (loc - 16)))
+ return true;
+ if (perso->_roomNum == (area | (loc + 16)))
+ return true;
+ if (perso->_roomNum == (area | (loc - 1)))
+ return true;
+ if (perso->_roomNum == (area | (loc + 1)))
+ return true;
+ }
+ return false;
+}
+
+bool EdenGame::istyran(int16 roomNum) {
+ char loc = roomNum & 0xFF;
+ int16 area = roomNum & 0xFF00;
+ // TODO: orig bug: this ptr is not initialized when first called from getsalle
+ // PC version scans _persons[] directly and is not affected
+ if (!_tyranPtr)
+ return false;
+
+ for (; _tyranPtr->_roomNum != 0xFFFF; _tyranPtr++) {
+ if (_tyranPtr->_flags & PersonFlags::pf80)
+ continue;
+ if (_tyranPtr->_roomNum == (area | (loc - 16)))
+ return true;
+ if (_tyranPtr->_roomNum == (area | (loc + 16)))
+ return true;
+ if (_tyranPtr->_roomNum == (area | (loc - 1)))
+ return true;
+ if (_tyranPtr->_roomNum == (area | (loc + 1)))
+ return true;
+ }
+ return false;
+}
+
+void EdenGame::istyranval(Area *area) {
+ byte areaNum = area->_num;
+ area->_flags &= ~AreaFlags::HasTyrann;
+ for (perso_t *perso = &_persons[PER_UNKN_372]; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+
+ if ((perso->_roomNum >> 8) == areaNum) {
+ area->_flags |= AreaFlags::HasTyrann;
+ break;
+ }
+ }
+}
+
+char EdenGame::getDirection(perso_t *perso) {
+ char dir = -1;
+ byte trgLoc = perso->_targetLoc;
+ byte curLoc = perso->_roomNum & 0xFF; //TODO name
+ if (curLoc != trgLoc) {
+ curLoc &= 0xF;
+ trgLoc &= 0xF;
+ if (curLoc != trgLoc) {
+ dir = 2;
+ if (curLoc > trgLoc)
+ dir = 5;
+ }
+ trgLoc = perso->_targetLoc;
+ curLoc = perso->_roomNum & 0xFF;
+ curLoc &= 0xF0;
+ trgLoc &= 0xF0;
+ if (curLoc != trgLoc) {
+ if (curLoc > trgLoc)
+ dir++;
+ dir++;
+ }
+ }
+ return dir;
+}
+
+// Original name: caselibre
+bool EdenGame::canMoveThere(char loc, perso_t *perso) {
+ Room *room = _globals->_citaAreaFirstRoom;
+ if (loc <= 0x10 || loc > 76 || (loc & 0xF) >= 12 || loc == perso->_lastLoc)
+ return false;
+
+ int16 roomNum = (perso->_roomNum & ~0xFF) | loc; //TODO: danger! signed
+ if (roomNum == _globals->_roomNum)
+ return false;
+
+ for (; room->_id != 0xFF; room++) {
+ if (room->_location != loc)
+ continue;
+ if (!(room->_flags & RoomFlags::rf01))
+ return false;
+ for (perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+ if (perso->_roomNum == roomNum)
+ break;
+ }
+ if (perso->_roomNum != 0xFFFF)
+ return false;
+ return true;
+ }
+ return false;
+}
+
+// Original name: melange1
+void EdenGame::scramble1(uint8 elem[4]) {
+ if (_vm->_rnd->getRandomNumber(1) & 1)
+ SWAP(elem[1], elem[2]);
+}
+
+// Original name melange2
+void EdenGame::scramble2(uint8 elem[4]) {
+ if (_vm->_rnd->getRandomNumber(1) & 1)
+ SWAP(elem[0], elem[1]);
+
+ if (_vm->_rnd->getRandomNumber(1) & 1)
+ SWAP(elem[2], elem[3]);
+}
+
+// Original name: melangedir
+void EdenGame::scrambleDirections() {
+ scramble1(tab_2CB1E[0]);
+ scramble1(tab_2CB1E[1]);
+ scramble1(tab_2CB1E[2]);
+ scramble2(tab_2CB1E[3]);
+ scramble2(tab_2CB1E[4]);
+ scramble1(tab_2CB1E[5]);
+ scramble2(tab_2CB1E[6]);
+ scramble2(tab_2CB1E[7]);
+}
+
+bool EdenGame::naitredino(char persoType) {
+ for (perso_t *perso = &_persons[PER_MORKUS]; (++perso)->_roomNum != 0xFFFF;) {
+ char areaNum = perso->_roomNum >> 8;
+ if (areaNum != _globals->_citadelAreaNum)
+ continue;
+ if ((perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pfTypeMask) == persoType) {
+ perso->_flags &= ~PersonFlags::pf80;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Original name: newcita
+void EdenGame::newCitadel(char area, int16 level, Room *room) {
+ Citadel *cita = _citadelList;
+ while (cita->_id < level)
+ cita++;
+
+ uint16 index = ((room->_flags & 0xC0) >> 6); //TODO: this is very wrong
+ if (area == 4 || area == 6)
+ index++;
+
+ room->_bank = cita->_bank[index];
+ room->_video = cita->_video[index];
+ room->_flags |= RoomFlags::rf02;
+}
+
+// Original name: citaevol
+void EdenGame::evolveCitadel(int16 level) {
+ Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
+ perso_t *perso = &_persons[PER_UNKN_372];
+ byte loc = room->_location;
+ if (level >= 80 && !istrice((_globals->_citadelAreaNum << 8) | loc)) {
+ room->_level = 79;
+ return;
+ }
+
+ if (level > 160)
+ level = 160;
+
+ if (room->_level < 64 && level >= 64 && naitredino(PersonFlags::pftTriceraptor)) {
+ _globals->_curAreaPtr->_flags |= AreaFlags::HasTriceraptors;
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
+ }
+ if (room->_level < 40 && level >= 40 && naitredino(PersonFlags::pftVelociraptor)) {
+ _globals->_curAreaPtr->_flags |= AreaFlags::HasVelociraptors;
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn);
+ }
+ room->_level = level;
+ newCitadel(_globals->_citadelAreaNum, level, room);
+ byte speed = _dinoSpeedForCitadelLevel[room->_level >> 4];
+ for (; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+ if ((perso->_roomNum >> 8) == _globals->_citadelAreaNum && perso->_targetLoc == loc)
+ perso->_speed = speed;
+ }
+}
+
+// Original name: citacapoute
+void EdenGame::destroyCitadelRoom(int16 roomNum) {
+ perso_t *perso = &_persons[PER_UNKN_18C];
+ Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
+ room->_flags |= RoomFlags::rf01;
+ room->_flags &= ~RoomFlags::rfHasCitadel;
+ room->_bank = 193;
+ room->_video = 0;
+ room->_level = 0;
+ _globals->_curAreaPtr->_citadelLevel = 0;
+ _globals->_curAreaPtr->_citadelRoomPtr = 0;
+ roomNum = (roomNum & ~0xFF) | room->_location;
+ for (; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_roomNum == roomNum) {
+ perso->_flags &= ~PersonFlags::pf80;
+ removeInfo((roomNum >> 8) + ValleyNews::vnTyrannIn);
+ break;
+ }
+ }
+}
+
+// Original name: buildcita
+void EdenGame::narratorBuildCitadel() {
+ Area *area = _globals->_areaPtr;
+ _globals->_curAreaPtr = _globals->_areaPtr;
+ if (area->_citadelRoomPtr)
+ destroyCitadelRoom(_globals->_roomNum);
+ _globals->_var6A = _globals->_var69;
+ _globals->_narratorSequence = _globals->_var69 | 0x80;
+ area->_citadelRoomPtr = _globals->_roomPtr;
+ _globals->_roomPtr->_flags &= ~RoomFlags::rf01;
+ _globals->_roomPtr->_flags |= RoomFlags::rfHasCitadel;
+ _globals->_roomPtr->_level = 32;
+ newCitadel(_globals->_areaNum, 32, _globals->_roomPtr);
+ area->_flags &= ~AreaFlags::TyrannSighted;
+ if (!(area->_flags & AreaFlags::afFlag8000)) {
+ if (_globals->_phaseNum == 304 || _globals->_phaseNum != 384) //TODO: wha
+ handleEloiReturn();
+ area->_flags |= AreaFlags::afFlag8000;
+ }
+ _globals->_roomCharacterPtr->_flags |= PersonFlags::pf80;
+ _globals->_citadelAreaNum = _globals->_areaNum;
+ naitredino(1);
+ removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost);
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
+ if (_globals->_phaseNum == 193 && _globals->_areaNum == Areas::arUluru)
+ bigphase1();
+}
+
+// Original name: citatombe
+void EdenGame::citadelFalls(char level) {
+ if (level)
+ newCitadel(_globals->_citadelAreaNum, level, _globals->_curAreaPtr->_citadelRoomPtr);
+ else {
+ destroyCitadelRoom(_globals->_citadelAreaNum << 8);
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnCitadelLost);
+ }
+}
+
+// Original name: constcita
+void EdenGame::buildCitadel() {
+ if (!_globals->_curAreaPtr->_citadelLevel || !_globals->_curAreaPtr->_citadelRoomPtr)
+ return;
+
+ Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
+ byte loc = room->_location;
+ _tyranPtr = &_persons[PER_UNKN_372];
+ if (istyran((_globals->_citadelAreaNum << 8) | loc)) {
+ if (!(_globals->_curAreaPtr->_flags & AreaFlags::TyrannSighted)) {
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn);
+ _globals->_curAreaPtr->_flags |= AreaFlags::TyrannSighted;
+ }
+ byte level = room->_level - 1;
+ if (level < 32)
+ level = 32;
+ room->_level = level;
+ citadelFalls(level);
+ } else {
+ _globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted;
+ evolveCitadel(room->_level + 1);
+ }
+}
+
+// Original name: depladino
+void EdenGame::moveDino(perso_t *perso) {
+ int dir = getDirection(perso);
+ if (dir != -1) {
+ scrambleDirections();
+ uint8 *dirs = tab_2CB1E[dir];
+ byte loc = perso->_roomNum & 0xFF;
+ uint8 dir2 = dirs[0];
+ if (dir2 & 0x80)
+ dir2 = -(dir2 & ~0x80);
+ dir2 += loc;
+ if (!canMoveThere(dir2, perso)) {
+ dir2 = dirs[1];
+ if (dir2 & 0x80)
+ dir2 = -(dir2 & ~0x80);
+ dir2 += loc;
+ if (!canMoveThere(dir2, perso)) {
+ dir2 = dirs[2];
+ if (dir2 & 0x80)
+ dir2 = -(dir2 & ~0x80);
+ dir2 += loc;
+ if (!canMoveThere(dir2, perso)) {
+ dir2 = dirs[3];
+ if (dir2 & 0x80)
+ dir2 = -(dir2 & ~0x80);
+ dir2 += loc;
+ if (!canMoveThere(dir2, perso)) {
+ dir2 = perso->_lastLoc;
+ perso->_lastLoc = 0;
+ if (!canMoveThere(dir2, perso))
+ return;
+ }
+ }
+ }
+ }
+
+ perso->_lastLoc = perso->_roomNum & 0xFF;
+ perso->_roomNum &= ~0xFF;
+ perso->_roomNum |= dir2 & 0xFF;
+ if ((perso->_targetLoc - 16 == (perso->_roomNum & 0xFF))
+ || (perso->_targetLoc + 16 == (perso->_roomNum & 0xFF))
+ || (perso->_targetLoc - 1 == (perso->_roomNum & 0xFF))
+ || (perso->_targetLoc + 1 == (perso->_roomNum & 0xFF)))
+ perso->_targetLoc = 0;
+ } else
+ perso->_targetLoc = 0;
+}
+
+// Original name: deplaalldino
+void EdenGame::moveAllDino() {
+ for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
+ if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum)
+ continue;
+ if ((perso->_flags & PersonFlags::pf80) || !perso->_targetLoc)
+ continue;
+ if (--perso->_steps)
+ continue;
+ perso->_steps = 1;
+ if (perso->_roomNum == _globals->_roomNum)
+ continue;
+ perso->_steps = perso->_speed;
+ moveDino(perso);
+ }
+}
+
+// Original name: newvallee
+void EdenGame::newValley() {
+ static int16 roomNumList[] = { 2075, 2080, 2119, -1};
+
+ perso_t *perso = &_persons[PER_UNKN_372];
+ int16 *ptr = roomNumList;
+ int16 roomNum = *ptr++;
+ while (roomNum != -1) {
+ perso->_roomNum = roomNum;
+ perso->_flags &= ~PersonFlags::pf80;
+ perso->_flags &= ~PersonFlags::pf20;
+ perso++;
+ roomNum = *ptr++;
+ }
+ perso->_roomNum = 0xFFFF;
+ _areasTable[7]._flags |= AreaFlags::HasTyrann;
+ _globals->_worldHasTyran = 32;
+}
+
+char EdenGame::whereIsCita() {
+ char res = (char)-1;
+ for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) {
+ if (!(room->_flags & RoomFlags::rfHasCitadel))
+ continue;
+ res = room->_location;
+ break;
+ }
+ return res;
+}
+
+bool EdenGame::isCita(int16 loc) {
+ loc &= 0xFF;
+ for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) {
+ if (!(room->_flags & RoomFlags::rfHasCitadel))
+ continue;
+
+ if ((room->_location == loc + 16)
+ || (room->_location == loc - 16)
+ || (room->_location == loc - 1)
+ || (room->_location == loc + 1))
+ return true;
+ }
+ return false;
+}
+
+// Original name: lieuvava
+void EdenGame::placeVava(Area *area) {
+ if (area->_type == AreaType::atValley) {
+ istyranval(area);
+ area->_citadelLevel = 0;
+ if (area->_citadelRoomPtr)
+ area->_citadelLevel = _globals->_citaAreaFirstRoom->_level; //TODO: no search?
+ byte mask = ~(1 << (area->_num - Areas::arChamaar));
+ _globals->_worldTyranSighted &= mask;
+ _globals->_var4E &= mask;
+ _globals->_worldGaveGold &= mask;
+ _globals->_worldHasVelociraptors &= mask;
+ _globals->_worldHasTriceraptors &= mask;
+ _globals->_worldHasTyran &= mask;
+ _globals->_var53 &= mask;
+ mask = ~mask;
+ if (area->_flags & AreaFlags::TyrannSighted)
+ _globals->_worldTyranSighted |= mask;
+ if (area->_flags & AreaFlags::afFlag4)
+ _globals->_var4E |= mask;
+ if (area->_flags & AreaFlags::HasTriceraptors)
+ _globals->_worldHasTriceraptors |= mask;
+ if (area->_flags & AreaFlags::afGaveGold)
+ _globals->_worldGaveGold |= mask;
+ if (area->_flags & AreaFlags::HasVelociraptors)
+ _globals->_worldHasVelociraptors |= mask;
+ if (area->_flags & AreaFlags::HasTyrann)
+ _globals->_worldHasTyran |= mask;
+ if (area->_flags & AreaFlags::afFlag20)
+ _globals->_var53 |= mask;
+ if (area == _globals->_areaPtr) {
+ _globals->_curAreaFlags = area->_flags;
+ _globals->_curCitadelLevel = area->_citadelLevel;
+ }
+ }
+ _globals->_var4D &= _globals->_worldTyranSighted;
+}
+
+void EdenGame::vivredino() {
+ for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
+ if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum)
+ continue;
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+ switch (perso->_flags & PersonFlags::pfTypeMask) {
+ case PersonFlags::pftTyrann:
+ if (isCita(perso->_roomNum))
+ perso->_targetLoc = 0;
+ else if (!perso->_targetLoc) {
+ char cita = whereIsCita();
+ if (cita != (char)-1) {
+ perso->_targetLoc = cita;
+ perso->_speed = 2;
+ perso->_steps = 1;
+ }
+ }
+ break;
+ case PersonFlags::pftTriceraptor:
+ if (perso->_flags & PersonFlags::pfInParty) {
+ if (isCita(perso->_roomNum))
+ perso->_targetLoc = 0;
+ else if (!perso->_targetLoc) {
+ char cita = whereIsCita();
+ if (cita != (char)-1) {
+ perso->_targetLoc = cita;
+ perso->_speed = 3;
+ perso->_steps = 1;
+ }
+ }
+ }
+ break;
+ case PersonFlags::pftVelociraptor:
+ if (perso->_flags & PersonFlags::pf10) {
+ if (perso->_roomNum == _globals->_roomNum) {
+ perso_t *perso2 = &_persons[PER_UNKN_372];
+ bool found = false;
+ for (; perso2->_roomNum != 0xFFFF; perso2++) {
+ if ((perso->_roomNum & ~0xFF) == (perso2->_roomNum & ~0xFF)) {
+ if (perso2->_flags & PersonFlags::pf80)
+ continue;
+ perso->_targetLoc = perso2->_roomNum & 0xFF;
+ perso->_steps = 1;
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ } else {
+ _tyranPtr = &_persons[PER_UNKN_372];
+ if (istyran(perso->_roomNum)) {
+ if (_globals->_phaseNum < 481 && (perso->_powers & (1 << (_globals->_citadelAreaNum - 3)))) {
+ _tyranPtr->_flags |= PersonFlags::pf80;
+ _tyranPtr->_roomNum = 0;
+ perso->_flags &= ~PersonFlags::pf10;
+ perso->_flags |= PersonFlags::pfInParty;
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannLost);
+ removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn);
+ if (naitredino(PersonFlags::pftTriceraptor))
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
+ buildCitadel();
+ _globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted;
+ } else {
+ perso->_flags &= ~PersonFlags::pf10;
+ perso->_flags &= ~PersonFlags::pfInParty;
+ addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsLost);
+ }
+ continue;
+ }
+ }
+ }
+ if (!perso->_targetLoc) {
+ int16 loc;
+ perso->_lastLoc = 0;
+ do {
+ loc = (_vm->_rnd->getRandomNumber(63) & 63) + 16;
+ if ((loc & 0xF) >= 12)
+ loc &= ~4; //TODO: ??? same as -= 4
+ } while (!canMoveThere(loc, perso));
+ perso->_targetLoc = loc;
+ perso->_steps = 1;
+ }
+ break;
+ }
+ }
+}
+
+void EdenGame::vivreval(int16 areaNum) {
+ _globals->_citadelAreaNum = areaNum;
+ _globals->_curAreaPtr = &_areasTable[areaNum - 1];
+ _globals->_citaAreaFirstRoom = &_gameRooms[_globals->_curAreaPtr->_firstRoomIdx];
+ moveAllDino();
+ buildCitadel();
+ vivredino();
+ newMushroom();
+ newNestWithEggs();
+ newEmptyNest();
+ if (_globals->_phaseNum >= 226)
+ newGold();
+ placeVava(_globals->_curAreaPtr);
+}
+
+// Original name: chaquejour
+void EdenGame::handleDay() {
+ vivreval(3);
+ vivreval(4);
+ vivreval(5);
+ vivreval(6);
+ vivreval(7);
+ vivreval(8);
+ _globals->_drawFlags |= DrawFlags::drDrawTopScreen;
+}
+
+// Original name: temps_passe
+void EdenGame::addTime(int16 t) {
+ int16 days = _globals->_gameDays;
+ int16 lo = _globals->_gameHours + t;
+ if (lo > 255) {
+ days++;
+ lo &= 0xFF;
+ }
+
+ _globals->_gameHours = lo;
+ t = ((t >> 8) & 0xFF) + days;
+ t -= _globals->_gameDays;
+ if (t) {
+ _globals->_gameDays += t;
+ while (t--)
+ handleDay();
+ }
+}
+
+// Original name: anim_perso
+void EdenGame::animCharacter() {
+ if (_curBankNum != _globals->_characterImageBank)
+ loadCharacter(_globals->_characterPtr);
+ restoreUnderSubtitles();
+ if (_restartAnimation) {
+ _lastAnimTicks = _vm->_timerTicks;
+ _restartAnimation = false;
+ }
+ _curAnimFrameNumb = (_vm->_timerTicks - _lastAnimTicks) >> 2; // TODO: check me!!!
+ if (_curAnimFrameNumb > _numAnimFrames) // TODO: bug?
+ _animateTalking = false;
+ if (_globals->_curCharacterAnimPtr && !_globals->_animationFlags && _curAnimFrameNumb != _lastAnimFrameNumb) {
+ _lastAnimFrameNumb = _curAnimFrameNumb;
+ if (*_globals->_curCharacterAnimPtr == 0xFF)
+ getanimrnd();
+ useCharacterBank();
+ _numImgDesc = 0;
+ setCharacterSprite(_globals->_curCharacterAnimPtr);
+ _globals->_curCharacterAnimPtr += _numImgDesc + 1;
+ _mouthAnimations = _imageDesc + 200;
+ removeMouthSprite();
+ if (*_mouthAnimations)
+ displayImage();
+ _animationDelay--;
+ if (!_animationDelay) {
+ _globals->_animationFlags = 1;
+ _animationDelay = 8;
+ }
+ }
+
+ _animationDelay--;
+ if (!_animationDelay) {
+ getanimrnd();
+ //TODO: no reload?
+ }
+ if (_animateTalking) {
+ if (!_animationTable) {
+ _animationTable = _gameLipsync + 7262; //TODO: fix me
+ if (!_backgroundSaved)
+ saveMouthBackground();
+ }
+ if (!_personTalking)
+ _curAnimFrameNumb = _numAnimFrames - 1;
+ _animationIndex = _animationTable[_curAnimFrameNumb];
+ if (_animationIndex == 0xFF)
+ _animateTalking = false;
+ else if (_animationIndex != _lastAnimationIndex) {
+ useCharacterBank();
+ restoreMouthBackground();
+// debug("perso spr %d", animationIndex);
+ setCharacterSprite(_globals->_persoSpritePtr2 + _animationIndex * 2); //TODO: int16s?
+ _mouthAnimations = _imageDesc + 200;
+ if (*_mouthAnimations)
+ displayImage();
+ _lastAnimationIndex = _animationIndex;
+ }
+ }
+ displaySubtitles();
+}
+
+void EdenGame::getanimrnd() {
+ _animationDelay = 8;
+ int16 rnd = _vm->_rnd->getRandomNumber(65535) & (byte)~0x18; //TODO
+ dword_30724 = _globals->_persoSpritePtr + 16; //TODO
+ _globals->_curCharacterAnimPtr = _globals->_persoSpritePtr + ((dword_30724[1] << 8) + dword_30724[0]);
+ _globals->_animationFlags = 1;
+ if (rnd >= 8)
+ return;
+ _globals->_animationFlags = 0;
+ if (rnd <= 0)
+ return;
+ for (rnd *= 8; rnd > 0; rnd--) {
+ while (*_globals->_curCharacterAnimPtr)
+ _globals->_curCharacterAnimPtr++;
+ _globals->_curCharacterAnimPtr++;
+ }
+}
+
+void EdenGame::addanim() {
+ _lastAnimationIndex = 0xFF;
+ _lastAnimTicks = 0;
+ _globals->_animationFlags = 0xC0;
+ _globals->_curCharacterAnimPtr = _globals->_persoSpritePtr;
+ getanimrnd();
+ _animationActive = true;
+ if (_globals->_characterPtr == &_persons[PER_KING])
+ return;
+ setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr)); //TODO: GetElem(0)
+ _mouthAnimations = _imageDesc + 200;
+ if (_globals->_characterPtr->_id != PersonId::pidCabukaOfCantura && _globals->_characterPtr->_targetLoc != 7) //TODO: targetLoc is minisprite idx
+ removeMouthSprite();
+ if (*_mouthAnimations)
+ displayImage();
+}
+
+// Original name: virespritebouche
+void EdenGame::removeMouthSprite() {
+ byte *src = _mouthAnimations + 2;
+ byte *dst = src;
+ char cnt = _mouthAnimations[0];
+ while (cnt--) {
+ byte a = *src++;
+ byte b = *src++;
+ byte c = *src++;
+ dst[0] = a;
+ dst[1] = b;
+ dst[2] = c;
+ if (dword_30728[0] != 0xFF) {
+ if ((a < dword_30728[0] || a > dword_30728[1])
+ && (a < dword_30728[2] || a > dword_30728[3]))
+ dst += 3;
+ else
+ _mouthAnimations[0]--;
+ } else
+ dst += 3;
+ }
+}
+
+// Original name: anim_perfin
+void EdenGame::AnimEndCharacter() {
+ _globals->_animationFlags &= ~0x80;
+ _animationDelay = 0;
+ _animationActive = false;
+}
+
+// Original name: perso_spr
+void EdenGame::setCharacterSprite(byte *spr) {
+ byte *img = _imageDesc + 200 + 2;
+ int16 count = 0;
+ byte c;
+ while ((c = *spr++)) {
+ byte *src;
+ int16 index = 0;
+ byte cc = 0;
+ if (c == 1) {
+ cc = index;
+ c = *spr++;
+ }
+ _numImgDesc++;
+ index = (cc << 8) | c;
+ index -= 2;
+
+ if (index > _maxPersoDesc)
+ index = _maxPersoDesc;
+ index *= 2; //TODO: src = GetElem(ff_C2, index)
+ src = _globals->_varC2;
+ src += READ_LE_UINT16(src + index);
+ while ((c = *src++)) {
+ *img++ = c;
+ *img++ = *src++;
+ *img++ = *src++;
+ count++;
+ }
+ }
+ _imageDesc[200] = count & 0xFF;
+ _imageDesc[201] = count >> 8;
+}
+
+// Original name: af_perso1
+void EdenGame::displayCharacter1() {
+ setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr));
+ displayImage();
+}
+
+// Original name: af_perso
+void EdenGame::displayCharacter() {
+ loadCurrCharacter();
+ displayCharacter1();
+}
+
+void EdenGame::ef_perso() {
+ _globals->_animationFlags &= 0x3F;
+}
+
+// Original name: load_perso
+void EdenGame::loadCharacter(perso_t *perso) {
+ _characterBankData = nullptr;
+ if (!perso->_spriteBank)
+ return;
+
+ if (perso->_spriteBank != _globals->_characterImageBank) {
+ _curCharacterRect = &_characterRects[perso->_id]; //TODO: array of int16?
+ dword_30728 = _characterArray[perso->_id];
+ ef_perso();
+ _globals->_characterImageBank = perso->_spriteBank;
+ useBank(_globals->_characterImageBank);
+ _characterBankData = _bankData;
+ byte *ptr = _bankData;
+ ptr += READ_LE_UINT16(ptr);
+ byte *baseptr = ptr;
+ ptr += READ_LE_UINT16(ptr) - 2;
+ ptr = baseptr + READ_LE_UINT16(ptr) + 4;
+ _gameIcons[0].sx = READ_LE_UINT16(ptr);
+ _gameIcons[0].sy = READ_LE_UINT16(ptr + 2);
+ _gameIcons[0].ex = READ_LE_UINT16(ptr + 4);
+ _gameIcons[0].ey = READ_LE_UINT16(ptr + 6);
+ ptr += 8;
+ _globals->_varC2 = ptr + 2;
+ _maxPersoDesc = READ_LE_UINT16(ptr) / 2;
+ ptr += READ_LE_UINT16(ptr);
+ baseptr = ptr;
+ ptr += READ_LE_UINT16(ptr) - 2;
+ _globals->_persoSpritePtr = baseptr;
+ _globals->_persoSpritePtr2 = baseptr + READ_LE_UINT16(ptr);
+ debug("load perso: b6 len is %ld", _globals->_persoSpritePtr2 - _globals->_persoSpritePtr);
+ } else {
+ useBank(_globals->_characterImageBank);
+ _characterBankData = _bankData;
+ }
+}
+
+// Original name: load_perso_cour
+void EdenGame::loadCurrCharacter() {
+ loadCharacter(_globals->_characterPtr);
+}
+
+void EdenGame::fin_perso() {
+ _globals->_animationFlags &= 0x3F;
+ _globals->_curCharacterAnimPtr = nullptr;
+ _globals->_varCA = 0;
+ _globals->_characterImageBank = -1;
+ AnimEndCharacter();
+}
+
+void EdenGame::no_perso() {
+ if (_globals->_displayFlags == DisplayFlags::dfPerson) {
+ _globals->_displayFlags = _globals->_oldDisplayFlags;
+ fin_perso();
+ }
+ endCharacterSpeech();
+}
+
+// Original name: close_perso
+void EdenGame::closeCharacterScreen() {
+ endCharacterSpeech();
+ if (_globals->_displayFlags == DisplayFlags::dfPerson && _globals->_characterPtr->_id != PersonId::pidNarrator && _globals->_eventType != EventType::etEventE) {
+ rundcurs();
+ _savedUnderSubtitles = true;
+ restoreUnderSubtitles();
+ display();
+ _globals->_var103 = 16;
+ }
+ if (_globals->_characterPtr->_id == PersonId::pidNarrator)
+ _globals->_var103 = 69;
+ _globals->_eloiHaveNews &= 1;
+ _globals->_varCA = 0;
+ _globals->_varF6 = 0;
+ if (_globals->_displayFlags == DisplayFlags::dfPerson) {
+ _globals->_displayFlags = _globals->_oldDisplayFlags;
+ _globals->_animationFlags &= 0x3F;
+ _globals->_curCharacterAnimPtr = nullptr;
+ AnimEndCharacter();
+ if (_globals->_displayFlags & DisplayFlags::dfMirror) {
+ gameToMirror(1);
+ _scrollPos = _oldScrollPos;
+ scroll();
+ return;
+ }
+ if (_globals->_numGiveObjs) {
+ if (!(_globals->_displayFlags & DisplayFlags::dfFlag2))
+ showObjects();
+ _globals->_numGiveObjs = 0;
+ }
+ if (_globals->_varF2 & 1) {
+ _globals->_mirrorEffect = 6; // CHECKME: Verify the value
+ _globals->_varF2 &= ~1;
+ }
+ char oldLoc = _globals->_newLocation;
+ _globals->_newLocation = 0;
+ if (!(_globals->_narratorSequence & 0x80))
+ _globals->_var100 = 0xFF;
+ updateRoom(_globals->_roomNum);
+ _globals->_newLocation = oldLoc;
+ }
+
+ if (_globals->_chrono)
+ _globals->_chronoFlag = 1;
+}
+
+// Original name: af_fondsuiveur
+void EdenGame::displayBackgroundFollower() {
+ char id = _globals->_characterPtr->_id;
+ for (Follower *follower = _followerList; follower->_id != -1; follower++) {
+ if (follower->_id == id) {
+ int bank = 326;
+ if (follower->sx >= 320)
+ bank = 327;
+ useBank(bank + _globals->_roomBackgroundBankNum);
+ drawSprite(0, 0, 16, true);
+ break;
+ }
+ }
+}
+
+void EdenGame::displayNoFollower(int16 bank) {
+ if (bank) {
+ useBank(bank);
+ if (_globals->_characterPtr == &_persons[PER_UNKN_156])
+ drawSprite(0, 0, 16, true);
+ else
+ drawSprite(0, 0, 16);
+ }
+}
+
+// Original name: af_fondperso1
+void EdenGame::displayCharacterBackground1() {
+ byte bank;
+ char *ptab;
+ if (_globals->_characterPtr == &_persons[PER_ELOI]) {
+ _gameIcons[0].sx = 0;
+ _characterRects[PER_ELOI].left = 2;
+ bank = _globals->_characterBackgroundBankIdx;
+ if (_globals->_eventType == EventType::etEventE) {
+ _globals->_var103 = 1;
+ displayNoFollower(bank);
+ return;
+ }
+ _gameIcons[0].sx = 60;
+ _characterRects[PER_ELOI].left = 62;
+ }
+ if (_globals->_characterPtr == &_persons[PER_TAU]) {
+ bank = 37;
+ if (_globals->_curObjectId == Objects::obShell) {
+ displayNoFollower(bank);
+ return;
+ }
+ }
+ ptab = _personRoomBankTable + _globals->_characterPtr->_roomBankId;
+ bank = *ptab++;
+ if (!(_globals->_characterPtr->_partyMask & _globals->_party)) {
+ while ((bank = *ptab++) != 0xFF) {
+ if (bank == (_globals->_roomNum & 0xFF)) { //TODO: signed vs unsigned - chg bank to uns?
+ bank = *ptab;
+ break;
+ }
+ ptab++;
+ }
+ if (bank == 0xFF) {
+ ptab = _personRoomBankTable + _globals->_characterPtr->_roomBankId;
+ bank = *ptab++;
+ }
+ }
+ displayBackgroundFollower();
+ displayNoFollower(bank);
+}
+
+// Original name: af_fondperso
+void EdenGame::displayCharacterBackground() {
+ if (_globals->_characterPtr->_spriteBank) {
+ _backgroundSaved = false;
+ displayCharacterBackground1();
+ }
+}
+
+// Original name: setpersoicon
+void EdenGame::setCharacterIcon() {
+ if (_globals->_iconsIndex == 4)
+ return;
+
+ if (_globals->_characterPtr == &_persons[PER_ELOI] && _globals->_eventType == EventType::etEventE) {
+ _globals->_iconsIndex = 123;
+ return;
+ }
+ Icon *icon = _gameIcons;
+ Icon *icon2 = &_gameIcons[_roomIconsBase];
+
+ *icon2++ = *icon++; //TODO: is this ok?
+ *icon2++ = *icon++;
+ icon2->sx = -1;
+}
+
+// Original name: show_perso
+void EdenGame::showCharacter() {
+ perso_t *perso = _globals->_characterPtr;
+ if (perso->_spriteBank) {
+ closeRoom();
+ if (_globals->_displayFlags != DisplayFlags::dfPerson) {
+ if (_globals->_displayFlags & DisplayFlags::dfMirror)
+ resetScroll();
+ _globals->_oldDisplayFlags = _globals->_displayFlags;
+ _globals->_displayFlags = DisplayFlags::dfPerson;
+ loadCharacter(perso);
+ setCharacterIcon();
+ displayCharacterBackground();
+ if (perso == &_persons[PER_TAU] && _globals->_curObjectId == Objects::obShell) {
+ displaySubtitles();
+ updateCursor();
+ _paletteUpdateRequired = true;
+ display();
+ rundcurs();
+ return;
+ }
+ }
+ loadCurrCharacter();
+ addanim();
+ if (!_globals->_curCharacterAnimPtr) {
+ displayCharacter();
+ displaySubtitles();
+ }
+ _restartAnimation = true;
+ animCharacter();
+ if (perso != &_persons[PER_UNKN_156])
+ updateCursor();
+ _paletteUpdateRequired = true;
+ if (perso != &_persons[PER_UNKN_156])
+ rundcurs();
+ display();
+ } else {
+ displayPlace();
+ displaySubtitles();
+ }
+}
+
+// Original name: showpersopanel
+void EdenGame::displayCharacterPanel() {
+ perso_t *perso = _globals->_characterPtr;
+ loadCurrCharacter();
+ addanim();
+ if (!_globals->_curCharacterAnimPtr) {
+ displayCharacter();
+ displaySubtitles();
+ }
+ _restartAnimation = true;
+ _paletteUpdateRequired = true;
+ if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
+ return;
+ animCharacter();
+ if (perso != &_persons[PER_UNKN_156])
+ updateCursor();
+ display();
+ if (perso != &_persons[PER_UNKN_156])
+ rundcurs();
+ _globals->_drawFlags |= DrawFlags::drDrawFlag8;
+ _globals->_iconsIndex = 112;
+}
+
+void EdenGame::getDataSync() {
+ int16 num = _globals->_textNum;
+ if (_globals->_textBankIndex != 1)
+ num += 565;
+ if (_globals->_textBankIndex == 3)
+ num += 707;
+ if (num == 144)
+ num = 142;
+ _animateTalking = ReadDataSync(num - 1);
+ if (_animateTalking)
+ _numAnimFrames = readFrameNumber();
+ else
+ _numAnimFrames = 0;
+ if (_globals->_textNum == 144)
+ _numAnimFrames = 48;
+ _animationTable = 0;
+}
+
+// Original name: ReadNombreFrames
+int16 EdenGame::readFrameNumber() {
+ int16 num = 0;
+ _animationTable = _gameLipsync + 7260 + 2; //TODO: fix me
+ while (*_animationTable++ != 0xFF)
+ num++;
+ return num;
+}
+
+void EdenGame::waitEndSpeak() {
+ for (;;) {
+ if (_animationActive)
+ animCharacter();
+ musicspy();
+ display();
+ _vm->pollEvents();
+ if (_vm->shouldQuit()) {
+ closeCharacterScreen();
+ edenShudown();
+ break;
+ }
+ if (!_mouseHeld)
+ if (_vm->isMouseButtonDown())
+ break;
+ if (_mouseHeld)
+ if (!_vm->isMouseButtonDown())
+ _mouseHeld = false;
+ }
+ _mouseHeld = true;
+}
+
+void EdenGame::my_bulle() {
+ if (!_globals->_textNum)
+ return;
+
+ byte *icons = phraseIconsBuffer;
+ byte *linesp = _sentenceCoordsBuffer;
+ byte *sentencePtr = _sentenceBuffer;
+ _globals->_numGiveObjs = 0;
+ _globals->_giveObj1 = 0;
+ _globals->_giveObj2 = 0;
+ _globals->_giveObj3 = 0;
+ _globals->_textWidthLimit = _subtitlesXWidth;
+ byte *textPtr = getPhrase(_globals->_textNum);
+ _numTextLines = 0;
+ int16 wordsOnLine = 0;
+ int16 wordWidth = 0;
+ int16 lineWidth = 0;
+ byte c;
+ while ((c = *textPtr++) != 0xFF) {
+ if (c == 0x11 || c == 0x13) {
+ if (_globals->_phaseNum <= 272 || _globals->_phaseNum == 386) {
+ _globals->_eloiHaveNews = c & 0xF;
+ _globals->_var4D = _globals->_worldTyranSighted;
+ }
+ } else if (c >= 0x80 && c < 0x90)
+ SysBeep(1);
+ else if (c >= 0x90 && c < 0xA0) {
+ while (*textPtr++ != 0xFF) ;
+ textPtr--;
+ } else if (c >= 0xA0 && c < 0xC0)
+ _globals->_textToken1 = c & 0xF;
+ else if (c >= 0xC0 && c < 0xD0)
+ _globals->_textToken2 = c & 0xF;
+ else if (c >= 0xD0 && c < 0xE0) {
+ byte c1 = *textPtr++;
+ if (c == 0xD2)
+#ifdef FAKE_DOS_VERSION
+ _globals->_textWidthLimit = c1 + 160;
+#else
+ _globals->_textWidthLimit = c1 + _subtitlesXCenter; //TODO: signed? 160 in pc ver
+#endif
+ else {
+ byte c2 = *textPtr++;
+ switch (_globals->_numGiveObjs) {
+ case 0:
+ _globals->_giveObj1 = c2;
+ break;
+ case 1:
+ _globals->_giveObj2 = c2;
+ break;
+ case 2:
+ _globals->_giveObj3 = c2;
+ break;
+ }
+ _globals->_numGiveObjs++;
+ *icons++ = *textPtr++;
+ *icons++ = *textPtr++;
+ *icons++ = c2;
+ }
+ } else if (c >= 0xE0 && c < 0xFF)
+ SysBeep(1);
+ else if (c != '\r') {
+ *sentencePtr++ = c;
+ byte width = _gameFont[c];
+#ifdef FAKE_DOS_VERSION
+ if (c == ' ')
+ width = _spaceWidth;
+#endif
+ wordWidth += width;
+ lineWidth += width;
+ int16 overrun = lineWidth - _globals->_textWidthLimit;
+ if (overrun > 0) {
+ _numTextLines++;
+ if (c != ' ') {
+ *linesp++ = wordsOnLine;
+ *linesp++ = wordWidth + _spaceWidth - overrun;
+ lineWidth = wordWidth;
+ } else {
+ *linesp++ = wordsOnLine + 1;
+ *linesp++ = _spaceWidth - overrun; //TODO: checkme
+ lineWidth = 0;
+ }
+ wordWidth = 0;
+ wordsOnLine = 0;
+ } else {
+ if (c == ' ') {
+ wordsOnLine++;
+ wordWidth = 0;
+ }
+ }
+ }
+ }
+ _numTextLines++;
+ *linesp++ = wordsOnLine + 1;
+ *linesp++ = wordWidth;
+ *sentencePtr = c;
+ if (_globals->_textBankIndex == 2 && _globals->_textNum == 101 && _globals->_prefLanguage == 1)
+ patchSentence();
+ my_pr_bulle();
+ if (!_globals->_numGiveObjs)
+ return;
+ useMainBank();
+ if (_numTextLines < 3)
+ _numTextLines = 3;
+ icons = phraseIconsBuffer;
+ for (byte i = 0; i < _globals->_numGiveObjs; i++) {
+ byte x = *icons++;
+ byte y = *icons++;
+ byte s = *icons++;
+ drawSprite(52, x + _subtitlesXCenter, y - 1, false, true);
+ drawSprite(s + 9, x + _subtitlesXCenter + 1, y, false, true);
+ }
+}
+
+void EdenGame::my_pr_bulle() {
+ CLBlitter_FillView(_subtitlesView, 0);
+ if (_globals->_prefLanguage == 0)
+ return;
+
+ byte *coo = _sentenceCoordsBuffer;
+ bool done = false;
+ textout = _subtitlesViewBuf;
+ byte *textPtr = _sentenceBuffer;
+ int16 lines = 1;
+ while (!done) {
+ int16 numWords = *coo++; // num words on line
+ int16 padSize = *coo++; // amount of extra spacing
+ byte *currOut = textout;
+ int16 extraSpacing = numWords > 1 ? padSize / (numWords - 1) + 1 : 0;
+ if (lines == _numTextLines)
+ extraSpacing = 0;
+ byte c = *textPtr++;
+ while (!done && (numWords > 0)) {
+ if (c < 0x80 && c != '\r') {
+ if (c == ' ') {
+ numWords--;
+ if (padSize >= extraSpacing) {
+ textout += extraSpacing + _spaceWidth;
+ padSize -= extraSpacing;
+ } else {
+ textout += padSize + _spaceWidth;
+ padSize = 0;
+ }
+ } else {
+ int16 charWidth = _gameFont[c];
+ if (!(_globals->_drawFlags & DrawFlags::drDrawMenu)) {
+ textout += _subtitlesXWidth;
+ if (!_specialTextMode)
+ drawSubtitleChar(c, 195, charWidth);
+ textout++;
+ if (!_specialTextMode)
+ drawSubtitleChar(c, 195, charWidth);
+ textout -= _subtitlesXWidth + 1;
+ }
+ if (_specialTextMode)
+ drawSubtitleChar(c, 250, charWidth);
+ else
+ drawSubtitleChar(c, 230, charWidth);
+ textout += charWidth;
+ }
+ } else
+ error("my_pr_bulle: Unexpected format");
+
+ c = *textPtr++;
+ if (c == 0xFF)
+ done = true;
+ }
+ textout = currOut + _subtitlesXWidth * FONT_HEIGHT;
+ lines++;
+ textPtr--;
+ }
+}
+
+// Original name: charsurbulle
+void EdenGame::drawSubtitleChar(byte c, byte color, int16 width) {
+ byte *glyph = _gameFont + 256 + c * FONT_HEIGHT;
+ _textOutPtr = textout;
+ for (int16 h = 0; h < FONT_HEIGHT; h++) {
+ byte bits = *glyph++;
+ int16 mask = 0x80;
+ for (int16 w = 0; w < width; w++) {
+ if (bits & mask)
+ *_textOutPtr = color;
+ _textOutPtr++;
+ mask >>= 1;
+ }
+ _textOutPtr += _subtitlesXWidth - width;
+ }
+}
+
+// Original name: sauvefondbulle
+void EdenGame::saveUnderSubtitles(int16 y) {
+ _underSubtitlesScreenRect.top = y - _numTextLines * FONT_HEIGHT;
+ _underSubtitlesScreenRect.left = _scrollPos + _subtitlesXScrMargin;
+ _underSubtitlesScreenRect.right = _scrollPos + _subtitlesXScrMargin + _subtitlesXWidth - 1;
+ _underSubtitlesScreenRect.bottom = y;
+ _underSubtitlesBackupRect.top = 0;
+ _underSubtitlesBackupRect.bottom = _numTextLines * FONT_HEIGHT;
+ CLBlitter_CopyViewRect(_mainView, _underSubtitlesView, &_underSubtitlesScreenRect, &_underSubtitlesBackupRect);
+ _savedUnderSubtitles = true;
+}
+
+// Original name: restaurefondbulle
+void EdenGame::restoreUnderSubtitles() {
+ if (!_savedUnderSubtitles)
+ return;
+ CLBlitter_CopyViewRect(_underSubtitlesView, _mainView, &_underSubtitlesBackupRect, &_underSubtitlesScreenRect);
+ _savedUnderSubtitles = false;
+}
+
+// Original name: af_subtitlehnm
+void EdenGame::displayHNMSubtitle() {
+ byte *src = _subtitlesViewBuf;
+ byte *dst = _hnmViewBuf + _subtitlesXScrMargin + (158 - _numTextLines * FONT_HEIGHT) * 320;
+ for (int16 y = 0; y < _numTextLines * FONT_HEIGHT; y++) {
+ for (int16 x = 0; x < _subtitlesXWidth; x++) {
+ char c = *src++;
+ if (c)
+ *dst = c;
+ dst++;
+ }
+ dst += 320 - _subtitlesXWidth;
+ }
+}
+
+// Original name: patchPhrase
+void EdenGame::patchSentence() {
+ _sentenceBuffer[36] = 'c';
+}
+
+void EdenGame::vavapers() {
+ perso_t *perso = _globals->_characterPtr;
+ _globals->_curPersoFlags = perso->_flags;
+ _globals->_curPersoItems = perso->_items;
+ _globals->_curCharacterPowers = perso->_powers;
+}
+
+void EdenGame::citadelle() {
+ _globals->_var69++;
+ _globals->_varF6++;
+ parlemoiNormalFlag = true;
+ _closeCharacterDialog = true;
+}
+
+// Original name: choixzone
+void EdenGame::selectZone() {
+ if (_globals->_giveObj3)
+ _globals->_iconsIndex = 6;
+ else
+ _globals->_iconsIndex = 10;
+ _globals->_autoDialog = false;
+ putObject();
+}
+
+void EdenGame::showEvents1() {
+ _globals->_var113 = 0;
+ perso_ici(3);
+}
+
+void EdenGame::showEvents() {
+ if (_globals->_eventType && _globals->_displayFlags != DisplayFlags::dfPerson)
+ showEvents1();
+}
+
+void EdenGame::parle_mfin() {
+ perso_t *perso = _globals->_characterPtr;
+ if (_globals->_curObjectId) {
+ char curobj = _globals->_curObjectId;
+ if (_globals->_dialogType == DialogType::dtHint)
+ return;
+ object_t *obj = getObjectPtr(_globals->_curObjectId);
+ if (_globals->_dialogType == DialogType::dtDinoItem)
+ perso = _globals->_roomCharacterPtr;
+ if (isAnswerYes()) {
+ loseObject(_globals->_curObjectId);
+ perso->_powers |= obj->_powerMask;
+ }
+ perso->_items |= obj->_itemMask;
+ specialObjects(perso, curobj);
+ return;
+ }
+ if (!isAnswerYes())
+ return;
+ nextInfo();
+ if (!_globals->_lastInfo)
+ _closeCharacterDialog = true;
+ else {
+ _globals->_nextDialogPtr = nullptr;
+ _closeCharacterDialog = false;
+ }
+}
+
+void EdenGame::parlemoi_normal() {
+ Dialog *dial;
+ if (!_globals->_nextDialogPtr) {
+ perso_t *perso = _globals->_characterPtr;
+ if (perso) {
+ int16 num = (perso->_id << 3) | _globals->_dialogType;
+ dial = (Dialog *)getElem(_gameDialogs, num);
+ } else {
+ closeCharacterScreen();
+ return;
+ }
+ } else {
+ if (_closeCharacterDialog) {
+ closeCharacterScreen();
+ return;
+ }
+ dial = _globals->_nextDialogPtr;
+ }
+ char ok = dial_scan(dial);
+ _globals->_nextDialogPtr = _globals->_dialogPtr;
+ _closeCharacterDialog = false;
+ if (!ok)
+ closeCharacterScreen();
+ else
+ parle_mfin();
+}
+
+void EdenGame::parle_moi() {
+ endCharacterSpeech();
+ byte r28 = _globals->_varF6;
+ _globals->_varF6 = 0;
+ if (!r28) {
+ setChoiceNo();
+ if (_globals->_drawFlags & DrawFlags::drDrawInventory)
+ showObjects();
+ if (_globals->_drawFlags & DrawFlags::drDrawTopScreen)
+ drawTopScreen();
+ if (_globals->_curObjectId) {
+ if (_globals->_dialogType == DialogType::dtTalk) {
+ _globals->_dialogType = DialogType::dtItem;
+ _globals->_nextDialogPtr = nullptr;
+ _closeCharacterDialog = false;
+ }
+ parlemoi_normal();
+ return;
+ }
+ if (_globals->_dialogType == DialogType::dtItem) {
+ _globals->_dialogType = DialogType::dtTalk;
+ if (!_closeCharacterDialog)
+ _globals->_nextDialogPtr = nullptr;
+ }
+ if (parlemoiNormalFlag) {
+ parlemoi_normal();
+ return;
+ }
+ Dialog *dial;
+
+ if (!_globals->_lastDialogPtr) {
+ int16 num = 160;
+ if (_globals->_phaseNum >= 400)
+ num++;
+ dial = (Dialog *)getElem(_gameDialogs, num);
+ } else
+ dial = _globals->_lastDialogPtr;
+ char ok = dial_scan(dial);
+ _globals->_lastDialogPtr = _globals->_dialogPtr;
+ parlemoiNormalFlag = false;
+ if (!ok) {
+ parlemoiNormalFlag = true;
+ if (_globals->_var60) {
+ if (_globals->_characterPtr == &_persons[PER_ELOI]) {
+ _globals->_dialogType = DialogType::dtTalk;
+ if (_globals->_eloiHaveNews)
+ parlemoi_normal();
+ else
+ closeCharacterScreen();
+ } else
+ closeCharacterScreen();
+ } else
+ parlemoi_normal();
+ } else
+ parle_mfin();
+ } else
+ closeCharacterScreen();
+}
+
+// Original name: init_perso_ptr
+void EdenGame::initCharacterPointers(perso_t *perso) {
+ _globals->_metPersonsMask1 |= perso->_partyMask;
+ _globals->_metPersonsMask2 |= perso->_partyMask;
+ _globals->_nextDialogPtr = nullptr;
+ _closeCharacterDialog = false;
+ _dialogSkipFlags = DialogFlags::dfSpoken;
+ _globals->_var60 = 0;
+ _globals->_textToken1 = 0;
+}
+
+void EdenGame::perso1(perso_t *perso) {
+ _globals->_phaseActionsCount++;
+ if (perso == &_persons[PER_TAU])
+ _globals->_phaseActionsCount--;
+ _globals->_characterPtr = perso;
+ initCharacterPointers(perso);
+ parle_moi();
+}
+
+void EdenGame::perso_normal(perso_t *perso) {
+ _globals->_lastDialogPtr = nullptr;
+ _globals->_dialogType = DialogType::dtTalk;
+ parlemoiNormalFlag = false;
+ perso1(perso);
+}
+
+// Original name: persoparle
+void EdenGame::handleCharacterDialog(int16 pers) {
+ perso_t *perso = &_persons[pers];
+ _globals->_characterPtr = perso;
+ _globals->_dialogType = DialogType::dtInspect;
+ uint16 idx = perso->_id * 8 | _globals->_dialogType;
+ dialoscansvmas((Dialog *)getElem(_gameDialogs, idx));
+ displayPlace();
+ displaySubtitles();
+ persovox();
+ _globals->_varCA = 0;
+ _globals->_dialogType = DialogType::dtTalk;
+}
+
+// Original name: roi
+void EdenGame::actionKing() {
+ perso_normal(&_persons[PER_KING]);
+}
+
+// Original name: dina
+void EdenGame::actionDina() {
+ perso_normal(&_persons[PER_DINA]);
+}
+
+// Original name: thoo
+void EdenGame::actionThoo() {
+ perso_normal(&_persons[PER_TAU]);
+}
+
+// Original name: monk
+void EdenGame::actionMonk() {
+ perso_normal(&_persons[PER_MONK]);
+}
+
+// Original name: bourreau
+void EdenGame::actionTormentor() {
+ perso_normal(&_persons[PER_JABBER]);
+}
+
+// Original name: messager
+void EdenGame::actionMessenger() {
+ perso_normal(&_persons[PER_ELOI]);
+}
+
+// Original name: mango
+void EdenGame::actionMango() {
+ perso_normal(&_persons[PER_MUNGO]);
+}
+
+// Original name: eve
+void EdenGame::actionEve() {
+ perso_normal(&_persons[PER_EVE]);
+}
+
+// Original name: azia
+void EdenGame::actionAzia() {
+ perso_normal(&_persons[PER_SHAZIA]);
+}
+
+// Original name: mammi
+void EdenGame::actionMammi() {
+ perso_t *perso;
+ for (perso = &_persons[PER_MAMMI]; perso->_partyMask == PersonMask::pmLeader; perso++) {
+ if (perso->_roomNum == _globals->_roomNum) {
+ perso_normal(perso);
+ break;
+ }
+ }
+}
+
+// Original name: gardes
+void EdenGame::actionGuards() {
+ perso_normal(&_persons[PER_GUARDS]);
+}
+
+// Original name: bambou
+void EdenGame::actionBamboo() {
+ perso_normal(&_persons[PER_BAMBOO]);
+}
+
+// Original name: kabuka
+void EdenGame::actionKabuka() {
+ if (_globals->_roomNum == 0x711) perso_normal(&_persons[PER_KABUKA]);
+ else actionBamboo();
+}
+
+// Original name: fisher
+void EdenGame::actionFisher() {
+ if (_globals->_roomNum == 0x902) perso_normal(&_persons[PER_FISHER]);
+ else actionKabuka();
+}
+
+// Original name: dino
+void EdenGame::actionDino() {
+ perso_t *perso = _globals->_roomCharacterPtr;
+ if (!perso)
+ return;
+ parlemoiNormalFlag = true;
+ _globals->_dialogType = DialogType::dtTalk;
+ _globals->_roomCharacterFlags = perso->_flags;
+ _globals->_roomPersoItems = perso->_items;
+ _globals->_roomCharacterPowers = perso->_powers;
+ _globals->_characterPtr = perso;
+ initCharacterPointers(perso);
+ debug("beg dino talk");
+ parle_moi();
+ debug("end dino talk");
+ if (_globals->_areaNum == Areas::arWhiteArch)
+ return;
+ if (_globals->_var60)
+ waitEndSpeak();
+ if (_vm->shouldQuit())
+ return;
+ perso = &_persons[PER_MUNGO];
+ if (!(_globals->_party & PersonMask::pmMungo)) {
+ perso = &_persons[PER_DINA];
+ if (!(_globals->_party & PersonMask::pmDina)) {
+ perso = &_persons[PER_EVE];
+ if (!(_globals->_party & PersonMask::pmEve)) {
+ perso = &_persons[PER_GUARDS];
+ }
+ }
+ }
+ _globals->_dialogType = DialogType::dtDinoAction;
+ if (_globals->_curObjectId)
+ _globals->_dialogType = DialogType::dtDinoItem;
+ perso1(perso);
+ if (_globals->_roomCharacterType == PersonFlags::pftMosasaurus && !_globals->_curObjectId) {
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag20;
+ placeVava(_globals->_areaPtr);
+ }
+}
+
+// Original name: tyran
+void EdenGame::actionTyran() {
+ perso_t *perso = _globals->_roomCharacterPtr;
+ if (!perso)
+ return;
+
+ parlemoiNormalFlag = true;
+ _globals->_dialogType = DialogType::dtTalk;
+ _globals->_roomCharacterFlags = perso->_flags;
+ _globals->_characterPtr = perso;
+ initCharacterPointers(perso);
+ perso = &_persons[PER_MUNGO];
+ if (!(_globals->_party & PersonMask::pmMungo)) {
+ perso = &_persons[PER_DINA];
+ if (!(_globals->_party & PersonMask::pmDina)) {
+ perso = &_persons[PER_EVE];
+ if (!(_globals->_party & PersonMask::pmEve)) {
+ perso = &_persons[PER_GUARDS];
+ }
+ }
+ }
+ _globals->_dialogType = DialogType::dtDinoAction;
+ if (_globals->_curObjectId)
+ _globals->_dialogType = DialogType::dtDinoItem;
+ perso1(perso);
+}
+
+// Original name: morkus
+void EdenGame::actionMorkus() {
+ perso_normal(&_persons[PER_MORKUS]);
+}
+
+void EdenGame::comment() {
+ perso_t *perso = &_persons[PER_DINA];
+ if (!(_globals->_party & PersonMask::pmDina)) {
+ perso = &_persons[PER_EVE];
+ if (!(_globals->_party & PersonMask::pmEve)) {
+ perso = &_persons[PER_GUARDS];
+ if (!(_globals->_party & PersonMask::pmThugg))
+ return;
+ }
+ }
+ _globals->_dialogType = DialogType::dtHint;
+ perso1(perso);
+}
+
+// Original name: adam
+void EdenGame::actionAdam() {
+ resetScroll();
+ switch (_globals->_curObjectId) {
+ case Objects::obNone:
+ gotoPanel();
+ break;
+ case Objects::obRoot:
+ if (_globals->_roomNum == 2817
+ && _globals->_phaseNum > 496 && _globals->_phaseNum < 512) {
+ bigphase1();
+ loseObject(Objects::obRoot);
+ _globals->_var100 = 0xFF;
+ quitMirror();
+ updateRoom(_globals->_roomNum);
+ removeFromParty(PER_ELOI);
+ _globals->_eventType = EventType::etEvent3;
+ showEvents();
+ waitEndSpeak();
+ if (_vm->shouldQuit())
+ return;
+ closeCharacterScreen();
+ removeFromParty(PER_ELOI);
+ _globals->_roomNum = 2818;
+ _globals->_areaNum = Areas::arWhiteArch;
+ _globals->_eventType = EventType::etEvent5;
+ _globals->_valleyVidNum = 0;
+ _globals->_mirrorEffect = 6; // CHECKME: Verify the value
+ _globals->_newMusicType = MusicType::mtNormal;
+ updateRoom(_globals->_roomNum);
+ } else {
+ _globals->_dialogType = DialogType::dtHint;
+ perso1(&_persons[PER_EVE]);
+ }
+ break;
+ case Objects::obShell:
+ _globals->_dialogType = DialogType::dtHint;
+ perso1(&_persons[PER_TAU]);
+ break;
+ case Objects::obFlute:
+ case Objects::obTrumpet:
+ if (_globals->_roomCharacterType) {
+ quitMirror();
+ updateRoom(_globals->_roomNum);
+ actionDino();
+ } else
+ comment();
+ break;
+ case Objects::obTablet1:
+ case Objects::obTablet2:
+ case Objects::obTablet3:
+ case Objects::obTablet4:
+ case Objects::obTablet5:
+ case Objects::obTablet6: {
+ if ((_globals->_partyOutside & PersonMask::pmDina)
+ && _globals->_curObjectId == Objects::obTablet1 && _globals->_phaseNum == 370)
+ incPhase();
+ char *objvid = &_tabletView[(_globals->_curObjectId - Objects::obTablet1) * 2];
+ object_t *object = getObjectPtr(*objvid++);
+ int16 vid = 84;
+ if (!object->_count)
+ vid = *objvid;
+ hideBars();
+ _specialTextMode = true;
+ playHNM(vid);
+ _paletteUpdateRequired = true;
+ _globals->_mirrorEffect = 16; // CHECKME: Verify the value
+ showBars();
+ gameToMirror(0);
+ }
+ break;
+ case Objects::obApple:
+ case Objects::obShroom:
+ case Objects::obBadShroom:
+ case Objects::obNest:
+ case Objects::obFullNest:
+ case Objects::obDrum:
+ if (_globals->_party & PersonMask::pmThugg) {
+ _globals->_dialogType = DialogType::dtHint;
+ perso1(&_persons[PER_GUARDS]);
+ }
+ break;
+ default:
+ comment();
+ }
+}
+
+// Original name: oui and init_oui
+void EdenGame::setChoiceYes() {
+ _lastDialogChoice = true;
+}
+
+// Original name: non and init_non
+void EdenGame::setChoiceNo() {
+ _lastDialogChoice = false;
+}
+
+// Original name: verif_oui
+bool EdenGame::isAnswerYes() {
+ return _lastDialogChoice;
+}
+
+// Original name: SpcChampi
+void EdenGame::specialMushroom(perso_t *perso) {
+ perso->_flags |= PersonFlags::pf10;
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag2;
+ _globals->_curAreaFlags |= AreaFlags::afFlag2;
+}
+
+// Original name: SpcNidv
+void EdenGame::specialEmptyNest(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ perso->_flags |= PersonFlags::pf10;
+ _globals->_roomCharacterFlags |= PersonFlags::pf10;
+ _globals->_gameFlags |= GameFlags::gfFlag400;
+ if (_globals->_characterPtr == &_persons[PER_EVE]) {
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag4;
+ _globals->_curAreaFlags |= AreaFlags::afFlag4;
+ perso->_flags |= PersonFlags::pfInParty;
+ _globals->_roomCharacterFlags |= PersonFlags::pfInParty;
+ placeVava(_globals->_areaPtr);
+ } else {
+ perso->_flags &= ~PersonFlags::pf10;
+ _globals->_roomCharacterFlags &= ~PersonFlags::pf10;
+ }
+}
+
+// Original name: SpcNido
+void EdenGame::specialNestWithEggs(perso_t *perso) {
+ if (perso == &_persons[PER_GUARDS])
+ giveObject();
+}
+
+// Original name: SpcPomme
+void EdenGame::specialApple(perso_t *perso) {
+ perso->_flags |= PersonFlags::pf10;
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag8;
+ _globals->_curAreaFlags |= AreaFlags::afFlag8;
+ _globals->_gameFlags |= GameFlags::gfFlag200;
+}
+
+// Original name: SpcOr
+void EdenGame::specialGold(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ perso->_items = _curSpecialObject->_itemMask;
+ _globals->_roomPersoItems = _curSpecialObject->_itemMask;
+ perso->_flags |= PersonFlags::pf10;
+ perso->_flags &= ~PersonFlags::pfInParty;
+ perso->_targetLoc = 0;
+ _globals->_areaPtr->_flags |= AreaFlags::afGaveGold;
+ _globals->_curAreaFlags |= AreaFlags::afGaveGold;
+ if (_globals->_phaseNum == 226)
+ incPhase();
+}
+
+// Original name: SpcPrisme
+void EdenGame::specialPrism(perso_t *perso) {
+ if (perso == &_persons[PER_DINA]) {
+ if (_globals->_partyOutside & PersonMask::pmMonk)
+ _globals->_gameFlags |= GameFlags::gfPrismAndMonk;
+ }
+}
+
+// Original name: SpcTalisman
+void EdenGame::specialTalisman(perso_t *perso) {
+ if (perso == &_persons[PER_DINA])
+ addToParty(PER_DINA);
+}
+
+// Original name: SpcMasque
+void EdenGame::specialMask(perso_t *perso) {
+ if (perso == &_persons[PER_BAMBOO]) {
+ dialautoon();
+ parlemoiNormalFlag = true;
+ }
+}
+
+// Original name: SpcSac
+void EdenGame::specialBag(perso_t *perso) {
+ if (_globals->_textToken1 != 3)
+ return;
+ if (perso == &_persons[PER_KABUKA] || perso == &_persons[PER_MAMMI_3])
+ loseObject(_curSpecialObject->_id);
+}
+
+// Original name: SpcTrompet
+void EdenGame::specialTrumpet(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ _globals->_var54 = 4;
+ winObject(Objects::obTrumpet);
+ _globals->_drawFlags |= DrawFlags::drDrawInventory;
+ _closeCharacterDialog = true;
+ tyranDies(_globals->_roomCharacterPtr);
+}
+
+// Original name: SpcArmes
+void EdenGame::specialWeapons(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ perso->_powers = _curSpecialObject->_powerMask;
+ _globals->_roomCharacterPowers = _curSpecialObject->_powerMask;
+ giveObject();
+}
+
+// Original name: SpcInstru
+void EdenGame::specialInstrument(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ if (perso == &_persons[PER_MONK]) {
+ _globals->_partyInstruments &= ~1; //TODO: check me
+ if (_curSpecialObject->_id == Objects::obRing) {
+ _globals->_partyInstruments |= 1;
+ _globals->_monkGotRing++; //TODO: |= 1 ?
+ }
+ }
+ if (perso == &_persons[PER_GUARDS]) {
+ _globals->_partyInstruments &= ~2;
+ if (_curSpecialObject->_id == Objects::obDrum)
+ _globals->_partyInstruments |= 2;
+ }
+ perso->_powers = _curSpecialObject->_powerMask;
+ _globals->_curCharacterPowers = _curSpecialObject->_powerMask;
+ giveObject();
+}
+
+// Original name: SpcOeuf
+void EdenGame::specialEgg(perso_t *perso) {
+ if (!isAnswerYes())
+ return;
+ _gameIcons[131]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 62;
+ dialautoon();
+}
+
+// Original name: TyranMeurt
+void EdenGame::tyranDies(perso_t *perso) {
+ perso->_flags |= PersonFlags::pf80;
+ perso->_roomNum = 0;
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
+ _globals->_roomCharacterType = 0;
+ _globals->_roomCharacterFlags = 0;
+ _globals->_chronoFlag = 0;
+}
+
+void EdenGame::specialObjects(perso_t *perso, char objid) {
+#pragma pack(push, 1)
+ struct SpecialObject {
+ int8 _characterType;
+ int8 _objectId;
+ void (EdenGame::*dispFct)(perso_t *perso);
+ };
+#pragma pack(pop)
+
+ static SpecialObject kSpecialObjectActions[] = {
+ // persoType, objectId, dispFct
+ { PersonFlags::pfType8, Objects::obShroom, &EdenGame::specialMushroom },
+ { PersonFlags::pftTriceraptor, Objects::obNest, &EdenGame::specialEmptyNest },
+ { PersonFlags::pfType0, Objects::obFullNest, &EdenGame::specialNestWithEggs },
+ { PersonFlags::pftMosasaurus, Objects::obApple, &EdenGame::specialApple },
+ { PersonFlags::pftVelociraptor, Objects::obGold, &EdenGame::specialGold },
+ { PersonFlags::pfType0, Objects::obPrism, &EdenGame::specialPrism },
+ { PersonFlags::pfType0, Objects::obTalisman, &EdenGame::specialTalisman },
+ { PersonFlags::pfType2, Objects::obMaskOfDeath, &EdenGame::specialMask },
+ { PersonFlags::pfType2, Objects::obMaskOfBonding, &EdenGame::specialMask },
+ { PersonFlags::pfType2, Objects::obMaskOfBirth, &EdenGame::specialMask },
+ { PersonFlags::pfType0, Objects::obBag, &EdenGame::specialBag },
+ { PersonFlags::pfType2, Objects::obBag, &EdenGame::specialBag },
+ { PersonFlags::pftTyrann, Objects::obTrumpet, &EdenGame::specialTrumpet },
+ { PersonFlags::pftVelociraptor, Objects::obEyeInTheStorm, &EdenGame::specialWeapons },
+ { PersonFlags::pftVelociraptor, Objects::obSkyHammer, &EdenGame::specialWeapons },
+ { PersonFlags::pftVelociraptor, Objects::obFireInTheClouds, &EdenGame::specialWeapons },
+ { PersonFlags::pftVelociraptor, Objects::obWithinAndWithout, &EdenGame::specialWeapons },
+ { PersonFlags::pftVelociraptor, Objects::obEyeInTheCyclone, &EdenGame::specialWeapons },
+ { PersonFlags::pftVelociraptor, Objects::obRiverThatWinds, &EdenGame::specialWeapons },
+ { PersonFlags::pfType0, Objects::obTrumpet, &EdenGame::specialInstrument },
+ { PersonFlags::pfType0, Objects::obDrum, &EdenGame::specialInstrument },
+ { PersonFlags::pfType0, Objects::obRing, &EdenGame::specialInstrument },
+ { PersonFlags::pfType0, Objects::obEgg, &EdenGame::specialEgg },
+ { -1, -1, nullptr }
+ };
+
+ char characterType = perso->_flags & PersonFlags::pfTypeMask;
+ _curSpecialObject = &_objects[objid - 1];
+ for (SpecialObject *spcObj = kSpecialObjectActions; spcObj->_characterType != -1; spcObj++) {
+ if (spcObj->_objectId == objid && spcObj->_characterType == characterType) {
+ (this->*spcObj->dispFct)(perso);
+ break;
+ }
+ }
+}
+
+void EdenGame::dialautoon() {
+ _globals->_iconsIndex = 4;
+ _globals->_autoDialog = true;
+ putObject();
+}
+
+void EdenGame::dialautooff() {
+ _globals->_iconsIndex = 0x10;
+ _globals->_autoDialog = false;
+}
+
+void EdenGame::follow() {
+ if (_globals->_roomCharacterType == PersonFlags::pfType12) {
+ debug("follow: hiding person %ld", _globals->_roomCharacterPtr - _persons);
+ _globals->_roomCharacterPtr->_flags |= PersonFlags::pf80;
+ _globals->_roomCharacterPtr->_roomNum = 0;
+ _globals->_gameFlags |= GameFlags::gfFlag8;
+ _gameIcons[123]._objectId = 18;
+ _gameIcons[124]._objectId = 35;
+ _gameIcons[125]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 56;
+ } else
+ AddCharacterToParty();
+}
+
+void EdenGame::dialonfollow() {
+ _globals->_iconsIndex = 4;
+ _globals->_autoDialog = true;
+ follow();
+}
+
+// Original name: abortdial
+void EdenGame::abortDialogue() {
+ _globals->_varF6++;
+ if (_globals->_roomCharacterType != PersonFlags::pftTriceraptor || _globals->_characterPtr != &_persons[PER_EVE])
+ return;
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag4;
+ _globals->_curAreaFlags |= AreaFlags::afFlag4;
+ _globals->_roomCharacterPtr->_flags |= PersonFlags::pfInParty;
+ _globals->_roomCharacterFlags |= PersonFlags::pfInParty;
+ placeVava(_globals->_areaPtr);
+}
+
+void EdenGame::subHandleNarrator() {
+ _globals->_varF2 &= ~1; //TODO: check me
+ if (_globals->_narratorSequence > 50 && _globals->_narratorSequence <= 80)
+ _globals->_endGameFlag = 50;
+ if (_globals->_narratorSequence == 3)
+ setChrono(1200);
+ _globals->_narratorSequence = 0;
+}
+
+// Original name: narrateur
+void EdenGame::handleNarrator() {
+ if (!(_globals->_displayFlags & DisplayFlags::dfFlag1))
+ return;
+ if (!_globals->_narratorSequence) {
+ if (_globals->_var6A == _globals->_var69) {
+ subHandleNarrator();
+ return;
+ }
+
+ narratorBuildCitadel();
+ }
+ _globals->_varF5 |= 0x80;
+ _globals->_varF2 &= ~1; //TODO: check me
+ _globals->_characterPtr = &_persons[PER_UNKN_156];
+ _globals->_var60 = 0;
+ _globals->_eventType = 0;
+ _globals->_var103 = 69;
+ if (dialogEvent(&_persons[PER_UNKN_156])) {
+ _globals->_narratorDialogPtr = _globals->_dialogPtr;
+ dialautoon();
+ _globals->_varF2 |= 1;
+ waitEndSpeak();
+ if (_vm->shouldQuit())
+ return;
+ endCharacterSpeech();
+ while (dialoscansvmas(_globals->_narratorDialogPtr)) {
+ _globals->_narratorDialogPtr = _globals->_dialogPtr;
+ waitEndSpeak();
+ if (_vm->shouldQuit())
+ return;
+ endCharacterSpeech();
+ }
+ _globals->_narratorDialogPtr = _globals->_dialogPtr;
+ _globals->_mirrorEffect = 0;
+ _globals->_var103 = 0;
+ closeCharacterScreen();
+ placeVava(_globals->_areaPtr);
+ if (_globals->_narratorSequence == 8)
+ deplaval(134);
+ }
+ _globals->_var103 = 0;
+ if (_globals->_narratorSequence == 10) {
+ addToParty(PER_ELOI);
+ addToParty(PER_EVE);
+ addToParty(PER_MONK);
+ addToParty(PER_GUARDS);
+ removeFromParty(PER_MUNGO);
+ _globals->_eloiHaveNews = 0;
+ deplaval(139);
+ }
+ _globals->_eventType = EventType::etEventD;
+ showEvents();
+ _globals->_varF5 &= ~0x80;
+
+ subHandleNarrator();
+}
+
+// Original name: vrf_phrases_file
+void EdenGame::checkPhraseFile() {
+ int16 num = 3;
+ if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 48))
+ num = 1;
+ else if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 128))
+ num = 2;
+ _globals->_textBankIndex = num;
+ if (_globals->_prefLanguage)
+ num += (_globals->_prefLanguage - 1) * 3;
+ if (num == _lastPhrasesFile)
+ return;
+ _lastPhrasesFile = num;
+ num += 404;
+ loadRawFile(num, _gamePhrases);
+ verifh(_gamePhrases);
+}
+
+// Original name: gettxtad
+byte *EdenGame::getPhrase(int16 id) {
+ checkPhraseFile();
+ return (byte *)getElem(_gamePhrases, id - 1);
+}
+
+// Original name: gotocarte
+void EdenGame::actionGotoMap() {
+ Goto *go = &_gotos[_curSpot2->_objectId];
+ endCharacterSpeech();
+ byte newArea = go->_areaNum;
+ _globals->_newRoomNum = (go->_areaNum << 8) | 1;
+ _globals->_newLocation = 1;
+ _globals->_prevLocation = _globals->_roomNum & 0xFF;
+ char curArea = _globals->_roomNum >> 8;
+ if (curArea == go->_areaNum)
+ newArea = 0;
+ else {
+ for (; go->_curAreaNum != 0xFF; go++) {
+ if (go->_curAreaNum == curArea)
+ break;
+ }
+
+ if (go->_areaNum == 0xFF)
+ return;
+ }
+ _globals->_eventType = EventType::etGotoArea | newArea;
+ setChoiceYes();
+ showEvents1();
+ waitEndSpeak();
+ if (_vm->shouldQuit())
+ return;
+
+ closeCharacterScreen();
+ if (isAnswerYes())
+ gotoPlace(go);
+}
+
+void EdenGame::record() {
+ if (_globals->_curObjectId)
+ return;
+
+ if (_globals->_characterPtr >= &_persons[PER_UNKN_18C])
+ return;
+
+ if (_globals->_eventType == EventType::etEventE || _globals->_eventType >= EventType::etGotoArea)
+ return;
+
+ for (tape_t *tape = _tapes; tape != _tapes + MAX_TAPES; tape++) {
+ if (tape->_textNum == _globals->_textNum)
+ return;
+ }
+
+ tape_t *tape = _tapes;
+ for (int16 i = 0; i < MAX_TAPES - 1; i++) {
+ tape->_textNum = tape[+1]._textNum;
+ tape->_perso = tape[+1]._perso;
+ tape->_party = tape[+1]._party;
+ tape->_roomNum = tape[+1]._roomNum;
+ tape->_backgroundBankNum = tape[+1]._backgroundBankNum;
+ tape->_dialog = tape[+1]._dialog;
+ tape++;
+ }
+
+ perso_t *perso = _globals->_characterPtr;
+ if (perso == &_persons[PER_EVE])
+ perso = _globals->_phaseNum >= 352 ? &_persons[PER_UNKN_372]
+ : &_persons[PER_UNKN_402];
+ tape->_textNum = _globals->_textNum;
+ tape->_perso = perso;
+ tape->_party = _globals->_party;
+ tape->_roomNum = _globals->_roomNum;
+ tape->_backgroundBankNum = _globals->_roomBackgroundBankNum;
+ tape->_dialog = _globals->_dialogPtr;
+}
+
+bool EdenGame::dial_scan(Dialog *dial) {
+ if (_globals->_numGiveObjs) {
+ if (!(_globals->_displayFlags & DisplayFlags::dfFlag2))
+ showObjects();
+ _globals->_numGiveObjs = 0;
+ }
+ _globals->_dialogPtr = dial;
+ vavapers();
+ _globals->_sentenceBufferPtr = _sentenceBuffer;
+ byte hidx, lidx;
+ uint16 mask = 0;
+ bool skipFl = false;
+ for (;; _globals->_dialogPtr++) {
+ for (;; _globals->_dialogPtr++) {
+ if (_globals->_dialogPtr->_flags == -1 && _globals->_dialogPtr->_condNumLow == -1)
+ return false;
+ byte flags = _globals->_dialogPtr->_flags;
+ _globals->_dialogFlags = flags;
+ if (!(flags & DialogFlags::dfSpoken) || (flags & DialogFlags::dfRepeatable)) {
+ hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3;
+ lidx = _globals->_dialogPtr->_condNumLow;
+ if (flags & 0x10)
+ hidx |= 4;
+ if (testCondition(((hidx << 8) | lidx) & 0x7FF))
+ break;
+ } else {
+ if (flags & _dialogSkipFlags)
+ continue;
+ hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3;
+ lidx = _globals->_dialogPtr->_condNumLow;
+ if (flags & 0x10)
+ hidx |= 4;
+ if (testCondition(((hidx << 8) | lidx) & 0x7FF))
+ break;
+ }
+ }
+ char bidx = (_globals->_dialogPtr->_textCondHiMask >> 2) & 0xF;
+ if (!bidx) {
+ skipFl = true;
+ break;
+ }
+
+ mask = (_globals->_party | _globals->_partyOutside) & (1 << (bidx - 1));
+ if (mask)
+ break;
+ }
+
+ if (!skipFl) {
+ perso_t *perso;
+ for (perso = _persons; !(perso->_partyMask == mask && perso->_roomNum == _globals->_roomNum); perso++)
+ ; //Find matching
+
+ _globals->_characterPtr = perso;
+ initCharacterPointers(perso);
+ no_perso();
+ }
+
+ hidx = _globals->_dialogPtr->_textCondHiMask;
+ lidx = _globals->_dialogPtr->_textNumLow;
+ _globals->_textNum = ((hidx << 8) | lidx) & 0x3FF;
+ if (_globals->_sentenceBufferPtr != _sentenceBuffer) {
+ for (int16 i = 0; i < 32; i++)
+ SysBeep(1);
+ } else
+ my_bulle();
+ if (!dword_30B04) {
+ static void (EdenGame::*talk_subject[])() = {
+ &EdenGame::setChoiceYes,
+ &EdenGame::setChoiceNo,
+ &EdenGame::handleEloiDeparture,
+ &EdenGame::dialautoon,
+ &EdenGame::dialautooff,
+ &EdenGame::characterStayHere,
+ &EdenGame::follow,
+ &EdenGame::citadelle,
+ &EdenGame::dialonfollow,
+ &EdenGame::abortDialogue,
+ &EdenGame::incPhase,
+ &EdenGame::bigphase,
+ &EdenGame::giveObject,
+ &EdenGame::selectZone,
+ &EdenGame::lostObject
+ };
+ char pnum = _globals->_dialogPtr->_flags & 0xF;
+ if (pnum)
+ (this->*talk_subject[pnum - 1])();
+ _globals->_var60 = 1;
+ _globals->_dialogPtr->_flags |= DialogFlags::dfSpoken;
+ _globals->_dialogPtr++;
+ }
+ if (_globals->_dialogType != DialogType::dtInspect) {
+ record();
+ getDataSync();
+ showCharacter();
+ persovox();
+ }
+ return true;
+}
+
+bool EdenGame::dialoscansvmas(Dialog *dial) {
+ byte oldFlag = _dialogSkipFlags;
+ _dialogSkipFlags = DialogFlags::df20;
+ bool res = dial_scan(dial);
+ _dialogSkipFlags = oldFlag;
+ return res;
+}
+
+// Original name: dialo_even
+bool EdenGame::dialogEvent(perso_t *perso) {
+ _globals->_characterPtr = perso;
+ int num = (perso->_id << 3) | DialogType::dtEvent;
+ Dialog *dial = (Dialog *)getElem(_gameDialogs, num);
+ bool retVal = dialoscansvmas(dial);
+ _globals->_lastDialogPtr = nullptr;
+ parlemoiNormalFlag = false;
+ return retVal;
+}
+
+// Original name: stay_here
+void EdenGame::characterStayHere() {
+ if (_globals->_characterPtr == &_persons[PER_DINA] && _globals->_roomNum == 260)
+ _globals->_gameFlags |= GameFlags::gfFlag1000;
+ removeCharacterFromParty();
+}
+
+// Original name: mort
+void EdenGame::endDeath(int16 vid) {
+ hideBars();
+ playHNM(vid);
+ fadeToBlack(2);
+ CLBlitter_FillScreenView(0);
+ CLBlitter_FillView(_mainView, 0);
+ showBars();
+ _globals->_narratorSequence = 51;
+ _globals->_newMusicType = MusicType::mtNormal;
+ musique();
+ musicspy();
+}
+
+// Original name: evenchrono
+void EdenGame::chronoEvent() {
+ if (!(_globals->_displayFlags & DisplayFlags::dfFlag1))
+ return;
+
+ uint16 oldGameTime = _globals->_gameTime;
+ _currentTime = _vm->_timerTicks / 100;
+ _globals->_gameTime = _currentTime;
+ if (_globals->_gameTime <= oldGameTime)
+ return;
+ addTime(5);
+ if (!(_globals->_chronoFlag & 1))
+ return;
+ _globals->_chrono -= 200;
+ if (_globals->_chrono == 0)
+ _globals->_chronoFlag |= 2;
+ if (!(_globals->_chronoFlag & 2))
+ return;
+ _globals->_chronoFlag = 0;
+ _globals->_chrono = 0;
+ if (_globals->_roomCharacterType == PersonFlags::pftTyrann) {
+ int16 vid = 272;
+ if (_globals->_curRoomFlags & 0xC0) {
+ vid += 2;
+ if ((_globals->_curRoomFlags & 0xC0) != 0x80) {
+ vid += 2;
+ endDeath(vid);
+ return;
+ }
+ }
+ if (_globals->_areaNum == Areas::arUluru || _globals->_areaNum == Areas::arTamara)
+ endDeath(vid);
+ else
+ endDeath(vid + 1);
+ return;
+ }
+ if (_globals->_roomNum == 2817) {
+ addToParty(PER_ELOI);
+ _globals->_gameFlags |= GameFlags::gfFlag40;
+ dialautoon();
+ } else
+ handleEloiReturn();
+ _globals->_eventType = EventType::etEvent10;
+ showEvents();
+}
+
+// Original name: chronoon
+void EdenGame::setChrono(int16 t) {
+ _globals->_chrono = t;
+ _globals->_chronoFlag = 1;
+}
+
+void EdenGame::wait(int howlong) {
+ int t = g_system->getMillis();
+
+ for (int t2 = t; t2 - t < howlong; t2 = g_system->getMillis())
+ g_system->delayMillis(10); // waste time
+}
+
+//////
+
+// Original name: ajouinfo
+void EdenGame::addInfo(byte info) {
+ byte idx = _globals->_nextInfoIdx;
+ if (_persons[PER_ELOI]._roomNum)
+ info |= 0x80;
+ _infoList[idx] = info;
+ if (idx == _globals->_lastInfoIdx)
+ _globals->_lastInfo = info;
+ idx++;
+ if (idx == 16)
+ idx = 0;
+ _globals->_nextInfoIdx = idx;
+}
+
+void EdenGame::unlockInfo() {
+ for (byte idx = 0; idx < 16; idx++) {
+ if (_infoList[idx] != 0xFF)
+ _infoList[idx] &= ~0x80;
+ }
+ _globals->_lastInfo &= ~0x80;
+}
+
+void EdenGame::nextInfo() {
+ do {
+ byte idx = _globals->_lastInfoIdx;
+ _infoList[idx] = 0;
+ idx++;
+ if (idx == 16)
+ idx = 0;
+ _globals->_lastInfoIdx = idx;
+ _globals->_lastInfo = _infoList[idx];
+ } while (_globals->_lastInfo == 0xFF);
+}
+
+// Original name: delinfo
+void EdenGame::removeInfo(byte info) {
+ for (byte idx = 0; idx < 16; idx++) {
+ if ((_infoList[idx] & ~0x80) == info) {
+ _infoList[idx] = 0xFF;
+ if (idx == _globals->_lastInfoIdx)
+ nextInfo();
+ break;
+ }
+ }
+}
+
+void EdenGame::updateInfoList() {
+ for (int idx = 0; idx < 16; idx++)
+ _infoList[idx] = 0;
+}
+
+void EdenGame::initGlobals() {
+ _gameIcons[16]._cursorId |= 0x8000;
+
+ _globals->_areaNum = Areas::arMo;
+ _globals->_areaVisitCount = 1;
+ _globals->_menuItemIdLo = 0;
+ _globals->_menuItemIdHi = 0;
+ _globals->_randomNumber = 0;
+ _globals->_gameTime = 0;
+ _globals->_gameDays = 0;
+ _globals->_chrono = 0;
+ _globals->_eloiDepartureDay = 0;
+ _globals->_roomNum = 259;
+ _globals->_newRoomNum = 0;
+ _globals->_phaseNum = 0;
+ _globals->_metPersonsMask1 = 0;
+ _globals->_party = 0;
+ _globals->_partyOutside = 0;
+ _globals->_metPersonsMask2 = 0;
+ _globals->_phaseActionsCount = 0;
+ _globals->_curAreaFlags = 0;
+ _globals->_curItemsMask = 0;
+ _globals->_curPowersMask = 0;
+ _globals->_curPersoItems = 0;
+ _globals->_curCharacterPowers = 0;
+ _globals->_wonItemsMask = 0;
+ _globals->_wonPowersMask = 0;
+ _globals->_stepsToFindAppleFast = 0;
+ _globals->_stepsToFindAppleNormal = 0;
+ _globals->_roomPersoItems = 0;
+ _globals->_roomCharacterPowers = 0;
+ _globals->_gameFlags = GameFlags::gfNone;
+ _globals->_curVideoNum = 0;
+ _globals->_morkusSpyVideoNum1 = 89;
+ _globals->_morkusSpyVideoNum2 = 88;
+ _globals->_morkusSpyVideoNum3 = 83;
+ _globals->_morkusSpyVideoNum4 = 94;
+ _globals->_newMusicType = MusicType::mtDontChange;
+ _globals->_var43 = 0;
+ _globals->_videoSubtitleIndex = 0;
+ _globals->_partyInstruments = 0;
+ _globals->_monkGotRing = 0;
+ _globals->_chronoFlag = 0;
+ _globals->_curRoomFlags = 0;
+ _globals->_endGameFlag = 0;
+ _globals->_lastInfo = 0;
+ _globals->_autoDialog = false;
+ _globals->_worldTyranSighted = 0;
+ _globals->_var4D = 0;
+ _globals->_var4E = 0;
+ _globals->_worldGaveGold = 0;
+ _globals->_worldHasTriceraptors = 0;
+ _globals->_worldHasVelociraptors = 0;
+ _globals->_worldHasTyran = 0;
+ _globals->_var53 = 0;
+ _globals->_var54 = 0;
+ _globals->_var55 = 0;
+ _globals->_gameHours = 0;
+ _globals->_textToken1 = 0;
+ _globals->_textToken2 = 0;
+ _globals->_eloiHaveNews = 0;
+ _globals->_dialogFlags = 0;
+ _globals->_curAreaType = 0;
+ _globals->_curCitadelLevel = 0;
+ _globals->_newLocation = 0;
+ _globals->_prevLocation = 0;
+ _globals->_curPersoFlags = 0;
+ _globals->_var60 = 0;
+ _globals->_eventType = EventType::etEvent5;
+ _globals->_var62 = 0;
+ _globals->_curObjectId = 0;
+ _globals->_curObjectFlags = 0;
+ _globals->_var65 = 1;
+ _globals->_roomCharacterType = 0;
+ _globals->_roomCharacterFlags = 0;
+ _globals->_narratorSequence = 0;
+ _globals->_var69 = 0;
+ _globals->_var6A = 0;
+ _globals->_frescoNumber = 0;
+ _globals->_var6C = 0;
+ _globals->_var6D = 0;
+ _globals->_labyrinthDirections = 0;
+ _globals->_labyrinthRoom = 0;
+ _globals->_curCharacterAnimPtr = nullptr;
+ _globals->_characterImageBank = 0;
+ _globals->_roomImgBank = 0;
+ _globals->_characterBackgroundBankIdx = 55;
+ _globals->_varD4 = 0;
+ _globals->_frescoeWidth = 0;
+ _globals->_frescoeImgBank = 0;
+ _globals->_varDA = 0;
+ _globals->_varDC = 0;
+ _globals->_roomBaseX = 0;
+ _globals->_varE0 = 0;
+ _globals->_dialogType = DialogType::dtTalk;
+ _globals->_varE4 = 0;
+ _globals->_currMusicNum = 0;
+ _globals->_textNum = 0;
+ _globals->_travelTime = 0;
+ _globals->_varEC = 0;
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ _globals->_oldDisplayFlags = 1;
+ _globals->_drawFlags = 0;
+ _globals->_varF1 = 0;
+ _globals->_varF2 = 0;
+ _globals->_menuFlags = 0;
+ _globals->_varF5 = 0;
+ _globals->_varF6 = 0;
+ _globals->_varF7 = 0;
+ _globals->_varF8 = 0;
+ _globals->_varF9 = 0;
+ _globals->_varFA = 0;
+ _globals->_animationFlags = 0;
+ _globals->_giveObj1 = 0;
+ _globals->_giveObj2 = 0;
+ _globals->_giveObj3 = 0;
+ _globals->_var100 = 0;
+ _globals->_roomVidNum = 0;
+ _globals->_mirrorEffect = 0;
+ _globals->_var103 = 0;
+ _globals->_roomBackgroundBankNum = 0;
+ _globals->_valleyVidNum = 0;
+ _globals->_updatePaletteFlag = 0;
+ _globals->_inventoryScrollPos = 0;
+ _globals->_objCount = 0;
+ _globals->_textBankIndex = 69;
+ _globals->_citadelAreaNum = 0;
+ _globals->_var113 = 0;
+ _globals->_lastPlaceNum = 0;
+ _globals->_dialogPtr = nullptr;
+ _globals->_tapePtr = _tapes;
+ _globals->_nextDialogPtr = nullptr;
+ _globals->_narratorDialogPtr = nullptr;
+ _globals->_lastDialogPtr = nullptr;
+ _globals->_nextRoomIcon = nullptr;
+ _globals->_sentenceBufferPtr = nullptr;
+ _globals->_roomPtr = nullptr;
+ _globals->_areaPtr = nullptr;
+ _globals->_lastAreaPtr = nullptr;
+ _globals->_curAreaPtr = nullptr;
+ _globals->_citaAreaFirstRoom = 0;
+ _globals->_characterPtr = nullptr;
+ _globals->_roomCharacterPtr = 0;
+ _globals->_lastInfoIdx = 0;
+ _globals->_nextInfoIdx = 0;
+ _globals->_iconsIndex = 16;
+ _globals->_persoSpritePtr = nullptr;
+ _globals->_numGiveObjs = 0;
+
+ initRects();
+
+ _underSubtitlesScreenRect.top = 0;
+ _underSubtitlesScreenRect.left = _subtitlesXScrMargin;
+ _underSubtitlesScreenRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1;
+ _underSubtitlesScreenRect.bottom = 176 - 1;
+
+ _underSubtitlesBackupRect.top = 0;
+ _underSubtitlesBackupRect.left = _subtitlesXScrMargin;
+ _underSubtitlesBackupRect.right = _subtitlesXScrMargin + _subtitlesXWidth - 1;
+ _underSubtitlesBackupRect.bottom = 60 - 1;
+}
+
+void EdenGame::initRects() {
+ _underTopBarScreenRect = Common::Rect(0, 0, 320 - 1, 16 - 1);
+ _underTopBarBackupRect = Common::Rect(0, 0, 320 - 1, 16 - 1);
+ _underBottomBarScreenRect = Common::Rect(0, 176, 320 - 1, 200 - 1); //TODO: original bug? this cause crash in copyrect (this, underBottomBarBackupRect)
+ _underBottomBarBackupRect = Common::Rect(0, 16, 320 - 1, 40 - 1);
+}
+
+// Original name: closesalle
+void EdenGame::closeRoom() {
+ if (_globals->_displayFlags & DisplayFlags::dfPanable) {
+ _globals->_displayFlags &= ~DisplayFlags::dfPanable;
+ resetScroll();
+ }
+}
+
+// Original name: aflieu
+void EdenGame::displayPlace() {
+ no_perso();
+ if (!_vm->shouldQuit()) {
+ _globals->_iconsIndex = 16;
+ _globals->_autoDialog = false;
+ }
+ _globals->_nextRoomIcon = &_gameIcons[_roomIconsBase];
+ displayRoom();
+ _paletteUpdateRequired = true;
+}
+
+// Original name: loadsal
+void EdenGame::loadPlace(int16 num) {
+ if (num == _globals->_lastPlaceNum)
+ return;
+ _globals->_lastPlaceNum = num;
+ loadRawFile(num + 419, _placeRawBuf);
+}
+
+void EdenGame::specialoutside() {
+ if (_globals->_lastAreaPtr->_type == AreaType::atValley && (_globals->_party & PersonMask::pmLeader))
+ perso_ici(5);
+}
+
+void EdenGame::specialout() {
+ if (_globals->_gameDays - _globals->_eloiDepartureDay > 2) {
+ if (checkEloiReturn())
+ handleEloiReturn();
+ }
+
+ if (_globals->_phaseNum >= 32 && _globals->_phaseNum < 48) {
+ if (_globals->_newLocation == 9 || _globals->_newLocation == 4 || _globals->_newLocation == 24) {
+ _persons[PER_ELOI]._roomNum = 263;
+ return;
+ }
+ }
+
+ if ((_globals->_phaseNum == 434) && (_globals->_newLocation == 5)) {
+ removeFromParty(PER_JABBER);
+ _persons[PER_JABBER]._roomNum = 264;
+ return;
+ }
+
+ if (_globals->_phaseNum < 400) {
+ if ((_globals->_gameFlags & GameFlags::gfFlag4000) && _globals->_prevLocation == 1
+ && (_globals->_party & PersonMask::pmEloi) && _globals->_curAreaType == AreaType::atValley)
+ handleEloiDeparture();
+ }
+
+ if (_globals->_phaseNum == 386) {
+ if (_globals->_prevLocation == 1
+ && (_globals->_party & PersonMask::pmEloi) && _globals->_areaNum == Areas::arCantura)
+ handleEloiDeparture();
+ }
+}
+
+void EdenGame::specialin() {
+ if (!(_globals->_party & PersonMask::pmEloi) && (_globals->_partyOutside & PersonMask::pmEloi) && (_globals->_roomNum & 0xFF) == 1) {
+ addToParty(PER_ELOI);
+ _globals->_eloiHaveNews = 1;
+ }
+ if (_globals->_roomNum == 288)
+ _globals->_gameFlags |= GameFlags::gfFlag100 | GameFlags::gfFlag2000;
+ if (_globals->_roomNum == 3075 && _globals->_phaseNum == 546) {
+ incPhase();
+ if (_globals->_curItemsMask & 0x2000) { // Morkus' tablet
+ hideBars();
+ playHNM(92);
+ _gameRooms[129]._exits[0] = 0;
+ _gameRooms[129]._exits[2] = 1;
+ _globals->_roomNum = 3074;
+ _persons[PER_MUNGO]._roomNum = 3074;
+ _globals->_eventType = EventType::etEvent5;
+ updateRoom(_globals->_roomNum);
+ return;
+ }
+ _globals->_narratorSequence = 53;
+ }
+ if (_globals->_roomNum == 1793 && _globals->_phaseNum == 336)
+ handleEloiDeparture();
+ if (_globals->_roomNum == 259 && _globals->_phaseNum == 129)
+ _globals->_narratorSequence = 12;
+ if (_globals->_roomNum >= 289 && _globals->_roomNum < 359)
+ _globals->_labyrinthDirections = _labyrinthPath[(_globals->_roomNum & 0xFF) - 33];
+ if (_globals->_roomNum == 305 && _globals->_prevLocation == 103)
+ _globals->_gameFlags &= ~GameFlags::gfFlag2000;
+ if (_globals->_roomNum == 304 && _globals->_prevLocation == 105)
+ _globals->_gameFlags &= ~GameFlags::gfFlag2000;
+ if (_globals->_phaseNum < 226) {
+ if (_globals->_roomNum == 842)
+ _globals->_gameFlags |= GameFlags::gfFlag2;
+ if (_globals->_roomNum == 1072)
+ _globals->_gameFlags |= GameFlags::gfFlag4;
+ if (_globals->_roomNum == 1329)
+ _globals->_gameFlags |= GameFlags::gfFlag8000;
+ }
+}
+
+void EdenGame::animpiece() {
+ Room *room = _globals->_roomPtr;
+ if (_globals->_roomVidNum && _globals->_var100 != 0xFF) {
+ if (_globals->_valleyVidNum || !room->_level || (room->_flags & RoomFlags::rfHasCitadel)
+ || room->_level == _globals->_var100) {
+ hideBars();
+ _globals->_updatePaletteFlag = 16;
+ if (!(_globals->_narratorSequence & 0x80)) //TODO: bug? !() @ 100DC
+ _globals->_mirrorEffect = 0;
+ if (!_needToFade)
+ _needToFade = room->_flags & RoomFlags::rf02;
+ playHNM(_globals->_roomVidNum);
+ return;
+ }
+ }
+ _globals->_varF1 &= ~RoomFlags::rf04;
+}
+
+void EdenGame::getdino(Room *room) {
+ assert(tab_2CEF0[4] == 0x25);
+
+ room->_flags &= ~0xC;
+ for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
+ if (perso->_flags & PersonFlags::pf80)
+ continue;
+ if (perso->_roomNum != _globals->_roomNum)
+ continue;
+ byte persoType = perso->_flags & PersonFlags::pfTypeMask;
+ if (persoType == PersonFlags::pftVelociraptor)
+ removeInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn);
+ if (persoType == PersonFlags::pftTriceraptor)
+ removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
+ perso->_flags |= PersonFlags::pf20;
+ int16 *tab = tab_2CF70;
+ if (_globals->_areaNum != Areas::arUluru && _globals->_areaNum != Areas::arTamara)
+ tab = tab_2CEF0;
+ byte r27 = (room->_flags & 0xC0) >> 2; //TODO: check me (like pc)
+ persoType = perso->_flags & PersonFlags::pfTypeMask;
+ if (persoType == PersonFlags::pftTyrann)
+ persoType = 13;
+ r27 |= (persoType & 7) << 1; //TODO: check me 13 & 7 = ???
+ tab += r27;
+ _globals->_roomVidNum = *tab++;
+ int16 bank = *tab;
+ if (bank & 0x8000) {
+ bank &= ~0x8000;
+ room->_flags |= RoomFlags::rf08;
+ }
+ room->_flags |= RoomFlags::rf04 | RoomFlags::rf02;
+ _globals->_roomImgBank = bank;
+ break;
+ }
+}
+
+// Original name: getsalle
+Room *EdenGame::getRoom(int16 loc) { //TODO: byte?
+ debug("get room for %X, starting from %d, looking for %X", loc, _globals->_areaPtr->_firstRoomIdx, _globals->_partyOutside);
+ Room *room = &_gameRooms[_globals->_areaPtr->_firstRoomIdx];
+ loc &= 0xFF;
+ for (;; room++) {
+ for (; room->_location != loc; room++) {
+ if (room->_id == 0xFF)
+ return nullptr;
+ }
+ if (_globals->_partyOutside == room->_party || room->_party == 0xFFFF)
+ break;
+ }
+ debug("found room: party = %X, bank = %X", room->_party, room->_bank);
+ _globals->_roomImgBank = room->_bank;
+ _globals->_labyrinthRoom = 0;
+ if (_globals->_roomImgBank > 104 && _globals->_roomImgBank <= 112)
+ _globals->_labyrinthRoom = _globals->_roomImgBank - 103;
+ if (_globals->_valleyVidNum)
+ _globals->_roomVidNum = _globals->_valleyVidNum;
+ else
+ _globals->_roomVidNum = room->_video;
+ if ((room->_flags & 0xC0) == RoomFlags::rf40 || (room->_flags & RoomFlags::rf01))
+ getdino(room);
+ if (room->_flags & RoomFlags::rfHasCitadel) {
+ removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost);
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
+ removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost);
+ }
+ if (istyran(_globals->_roomNum))
+ _globals->_gameFlags |= GameFlags::gfFlag10;
+ else
+ _globals->_gameFlags &= ~GameFlags::gfFlag10;
+ return room;
+}
+
+// Original name: initlieu
+void EdenGame::initPlace(int16 roomNum) {
+ _globals->_gameFlags |= GameFlags::gfFlag4000;
+ _gameIcons[18]._cursorId |= 0x8000;
+ _globals->_lastAreaPtr = _globals->_areaPtr;
+ _globals->_areaPtr = &_areasTable[((roomNum >> 8) & 0xFF) - 1];
+ Area *area = _globals->_areaPtr;
+ area->_visitCount++;
+ _globals->_areaVisitCount = area->_visitCount;
+ _globals->_curAreaFlags = area->_flags;
+ _globals->_curAreaType = area->_type;
+ _globals->_curCitadelLevel = area->_citadelLevel;
+ if (_globals->_curAreaType == AreaType::atValley)
+ _gameIcons[18]._cursorId &= ~0x8000;
+ loadPlace(area->_placeNum);
+}
+
+void EdenGame::maj2() {
+ displayPlace();
+ assert(_vm->_screenView->_pitch == 320);
+ if (_globals->_roomNum == 273 && _globals->_prevLocation == 18)
+ _globals->_mirrorEffect = 1;
+ if (_globals->_eventType == EventType::etEventC) {
+ drawTopScreen();
+ showObjects();
+ }
+ FRDevents();
+ assert(_vm->_screenView->_pitch == 320);
+ bool r30 = false;
+ if (_globals->_curAreaType == AreaType::atValley && !(_globals->_displayFlags & DisplayFlags::dfPanable))
+ r30 = true;
+ //TODO: ^^ inlined func?
+
+ if (_globals->_mirrorEffect || _globals->_var103)
+ display();
+ else if (_globals->_varF1 == (RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01)) {
+ drawBlackBars();
+ displayEffect1();
+ } else if (_globals->_varF1 && !(_globals->_varF1 & RoomFlags::rf04) && !r30) {
+ if (!(_globals->_displayFlags & DisplayFlags::dfPanable))
+ drawBlackBars();
+ else if (_globals->_valleyVidNum)
+ drawBlackBars();
+ displayEffect1();
+ } else if (r30 && !(_globals->_varF1 & RoomFlags::rf04))
+ effetpix();
+ else
+ afficher128();
+ musique();
+ if (_globals->_eventType != EventType::etEventC) {
+ drawTopScreen();
+ showObjects();
+ }
+ showBars();
+ showEvents();
+ _globals->_labyrinthDirections = 0;
+ specialin();
+}
+
+// Original name: majsalle1
+void EdenGame::updateRoom1(int16 roomNum) {
+ Room *room = getRoom(roomNum & 0xFF);
+ _globals->_roomPtr = room;
+ debug("DrawRoom: room 0x%X, arg = 0x%X", _globals->_roomNum, roomNum);
+ _globals->_curRoomFlags = room->_flags;
+ _globals->_varF1 = room->_flags;
+ animpiece();
+ _globals->_var100 = 0;
+ maj2();
+}
+
+// Original name: maj_salle
+void EdenGame::updateRoom(uint16 roomNum) {
+ setCharacterHere();
+ updateRoom1(roomNum);
+}
+
+// Original name: initbuf
+void EdenGame::allocateBuffers() {
+#define ALLOC(ptr, size, typ) if (!((ptr) = (typ*)malloc(size))) _bufferAllocationErrorFl = true;
+ ALLOC(_gameRooms, 0x4000, Room);
+ ALLOC(_gameIcons, 0x4000, Icon);
+ ALLOC(_bankDataBuf, 0x10000, byte);
+ ALLOC(_globals, sizeof(*_globals), global_t);
+ ALLOC(_placeRawBuf, 2048, byte);
+ ALLOC(_gameConditions, 0x4800, byte);
+ ALLOC(_gameDialogs, 0x2800, byte);
+ ALLOC(_gamePhrases, 0x10000, byte);
+ ALLOC(_mainBankBuf, 0x9400, byte);
+ ALLOC(_glowBuffer, 0x2800, byte);
+ ALLOC(_gameFont, 0x900, byte);
+ ALLOC(_gameLipsync, 0x205C, byte);
+ ALLOC(_musicBuf, kMaxMusicSize, byte);
+#undef ALLOC
+}
+
+void EdenGame::freebuf() {
+ delete(_bigfileHeader);
+ _bigfileHeader = nullptr;
+
+ free(_gameRooms);
+ free(_gameIcons);
+ free(_bankDataBuf);
+ free(_globals);
+ free(_placeRawBuf);
+ free(_gameConditions);
+ free(_gameDialogs);
+ free(_gamePhrases);
+ free(_mainBankBuf);
+ free(_glowBuffer);
+ free(_gameFont);
+ free(_gameLipsync);
+ free(_musicBuf);
+}
+
+void EdenGame::EmergencyExit() {
+ SysBeep(1);
+}
+
+void EdenGame::run() {
+ _invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11;
+ _roomIconsBase = _invIconsBase + _invIconsCount;
+
+ word_378CE = 0;
+ CRYOLib_ManagersInit();
+ _vm->_video->setupSound(11025, false, false);
+ _vm->_video->setForceZero2Black(true);
+ _vm->_video->setupTimer(12.5);
+ _voiceSound = new Sound(0, 11025 * 65536.0, 8, 0);
+ _hnmSoundChannel = _vm->_video->getSoundChannel();
+ _voiceSound->setWantsDesigned(1); // CHECKME: Used?
+
+ _musicChannel = new CSoundChannel(_vm->_mixer, 11025, false);
+ _voiceChannel = new CSoundChannel(_vm->_mixer, 11025, false);
+
+ allocateBuffers();
+ openbigfile();
+ openWindow();
+ loadpermfiles();
+
+ if (!_bufferAllocationErrorFl) {
+ LostEdenMac_InitPrefs();
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ initCubeMac();
+ else
+ initCubePC();
+
+ while (!_quitFlag2) {
+ initGlobals();
+ _quitFlag3 = false;
+ _normalCursor = true;
+ _torchCursor = false;
+ _cursKeepPos = Common::Point(-1, -1);
+ if (!_gameLoaded)
+ intro();
+ edmain();
+ startmusique(1);
+ drawBlackBars();
+ display();
+ fadeToBlack(3);
+ clearScreen();
+ playHNM(95);
+ if (_globals->_endGameFlag == 50) {
+ loadrestart();
+ _gameLoaded = false;
+ }
+ fademusica0(2);
+ _musicChannel->stop();
+ _musicPlayingFlag = false;
+ _musicEnabledFlag = false;
+ }
+ // LostEdenMac_SavePrefs();
+ }
+
+ delete _voiceChannel;
+ delete _musicChannel;
+
+ fadeToBlack(4);
+ closebigfile();
+ freebuf();
+ CRYOLib_ManagersDone();
+}
+
+void EdenGame::edmain() {
+ //TODO
+ enterGame();
+ while (!_bufferAllocationErrorFl && !_quitFlag3 && _globals->_endGameFlag != 50) {
+ if (!_gameStarted) {
+ // if in demo mode, reset game after a while
+ _demoCurrentTicks = _vm->_timerTicks;
+ if (_demoCurrentTicks - _demoStartTicks > 3000) {
+ rundcurs();
+ display();
+ fademusica0(2);
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0);
+ CLBlitter_FillView(_mainView, 0);
+ _musicChannel->stop();
+ _musicPlayingFlag = false;
+ _musicEnabledFlag = false;
+ intro();
+ enterGame();
+ }
+ }
+ rundcurs();
+ musicspy();
+ FRDevents();
+ handleNarrator();
+ chronoEvent();
+ if (_globals->_drawFlags & DrawFlags::drDrawInventory)
+ showObjects();
+ if (_globals->_drawFlags & DrawFlags::drDrawTopScreen)
+ drawTopScreen();
+ if ((_globals->_displayFlags & DisplayFlags::dfPanable) && (_globals->_displayFlags != DisplayFlags::dfPerson))
+ scrollPanel();
+ if ((_globals->_displayFlags & DisplayFlags::dfMirror) && (_globals->_displayFlags != DisplayFlags::dfPerson))
+ scrollMirror();
+ if ((_globals->_displayFlags & DisplayFlags::dfFrescoes) && (_globals->_displayFlags != DisplayFlags::dfPerson))
+ scrollFrescoes();
+ if (_globals->_displayFlags & DisplayFlags::dfFlag2)
+ noclicpanel();
+ if (_animationActive)
+ animCharacter();
+ updateCursor();
+ display();
+ }
+}
+
+void EdenGame::intro() {
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ // Play intro videos in HQ
+ _hnmSoundChannel->stop();
+ _vm->_video->closeSound();
+ _vm->_video->setupSound(22050, false, true);
+ _hnmSoundChannel = _vm->_video->getSoundChannel();
+ playHNM(2012);
+ playHNM(171);
+ CLBlitter_FillScreenView(0);
+ _specialTextMode = false;
+ playHNM(2001);
+ _hnmSoundChannel->stop();
+ _vm->_video->closeSound();
+ _vm->_video->setupSound(11025, false, false);
+ _hnmSoundChannel = _vm->_video->getSoundChannel();
+ } else {
+ if (_vm->isDemo()) {
+ playHNM(171); // Virgin logo
+ playHNM(98); // Cryo logo
+ }
+ else {
+ playHNM(98); // Cryo logo
+ playHNM(171); // Virgin logo
+ }
+ CLBlitter_FillScreenView(0);
+ _specialTextMode = false;
+ startmusique(2); // INTRO.MUS is played during intro video
+ playHNM(170); // Intro video
+ }
+}
+
+void EdenGame::enterGame() {
+ char flag = 0;
+ _currentTime = _vm->_timerTicks / 100;
+ _globals->_gameTime = _currentTime;
+ _demoStartTicks = _vm->_timerTicks;
+ _gameStarted = false;
+ if (!_gameLoaded) {
+ _globals->_roomNum = 279;
+ _globals->_areaNum = Areas::arMo;
+ _globals->_var100 = 0xFF;
+ initPlace(_globals->_roomNum);
+ _globals->_currMusicNum = 0;
+ startmusique(1);
+ } else {
+ flag = _globals->_autoDialog; //TODO
+ initafterload();
+ byte lastMusicNum = _globals->_currMusicNum; //TODO: ???
+ _globals->_currMusicNum = 0;
+ startmusique(lastMusicNum);
+ _globals->_inventoryScrollPos = 0;
+ _gameStarted = true;
+ }
+ showObjects();
+ drawTopScreen();
+ saveFriezes();
+ _showBlackBars = true;
+ _globals->_mirrorEffect = 1;
+ updateRoom(_globals->_roomNum);
+ if (flag) {
+ _globals->_iconsIndex = 4;
+ _globals->_autoDialog = true;
+ parle_moi();
+ }
+}
+
+void EdenGame::signon(const char *s) {
+}
+
+void EdenGame::FRDevents() {
+ _vm->pollEvents();
+
+ int16 mouseY;
+ int16 mouseX;
+ _vm->getMousePosition(&mouseX, &mouseY);
+ mouseX -= _mouseCenterX;
+ mouseY -= _mouseCenterY;
+ _vm->setMousePosition(_mouseCenterX , _mouseCenterY);
+ _cursorPosX += mouseX;
+ _cursorPosX = CLIP<int16>(_cursorPosX, 4, 292);
+ _cursorPosY += mouseY;
+
+ int16 maxY = _globals->_displayFlags == DisplayFlags::dfFlag2 ? 190 : 170;
+ _cursorPosY = CLIP<int16>(_cursorPosY, 4, maxY);
+ _cirsorPanX = _cursorPosX;
+
+ if (_cursorPosY >= 10 && _cursorPosY <= 164 && !(_globals->_displayFlags & DisplayFlags::dfFrescoes))
+ _cirsorPanX += _scrollPos;
+ if (_normalCursor) {
+ _currCursor = 0;
+ _currSpot = scan_icon_list(_cirsorPanX + _cursCenter, _cursorPosY + _cursCenter, _globals->_iconsIndex);
+ if (_currSpot)
+ _currCursor = _currSpot->_cursorId;
+ }
+ if (_cursCenter == 0 && _currCursor != 53) {
+ _cursCenter = 11;
+ _cursorPosX -= 11;
+ }
+ if (_cursCenter == 11 && _currCursor == 53) {
+ _cursCenter = 0;
+ _cursorPosX += 11;
+ }
+ if (_globals->_displayFlags & DisplayFlags::dfPanable) {
+ //TODO: _currSpot may be zero (due to scan_icon_list failure) if cursor slips between hot areas.
+ //fix me here or above?
+ if (_currSpot) { // ok, plug it here
+ _curSpot2 = _currSpot;
+ displayAdamMapMark(_curSpot2->_actionId - 14);
+ }
+ }
+ if (_globals->_displayFlags == DisplayFlags::dfFlag2 && _currSpot)
+ _curSpot2 = _currSpot;
+ if (_globals->_displayFlags & DisplayFlags::dfFrescoes) {
+ if (_frescoTalk)
+ restoreUnderSubtitles();
+ if (_currCursor == 9 && !_torchCursor) {
+ rundcurs();
+ _torchCursor = true;
+ _glowX = -1;
+ }
+ if (_currCursor != 9 && _torchCursor) {
+ unglow();
+ _torchCursor = false;
+ _cursorSaved = false;
+ }
+ }
+ if (_vm->isMouseButtonDown()) {
+ if (!_mouseHeld) {
+ _mouseHeld = true;
+ _gameStarted = true;
+ mouse();
+ }
+ } else
+ _mouseHeld = false;
+ if (_globals->_displayFlags != DisplayFlags::dfFlag2) {
+ if (--_inventoryScrollDelay <= 0) {
+ if (_globals->_objCount > _invIconsCount && _cursorPosY > 164) {
+ if (_cursorPosX > 284 && _globals->_inventoryScrollPos + _invIconsCount < _globals->_objCount) {
+ _globals->_inventoryScrollPos++;
+ _inventoryScrollDelay = 20;
+ showObjects();
+ }
+
+ if (_cursorPosX < 30 && _globals->_inventoryScrollPos != 0) {
+ _globals->_inventoryScrollPos--;
+ _inventoryScrollDelay = 20;
+ showObjects();
+ }
+ }
+ }
+ }
+ if (_inventoryScrollDelay < 0)
+ _inventoryScrollDelay = 0;
+
+ if (_vm->shouldQuit())
+ edenShudown();
+}
+
+Icon *EdenGame::scan_icon_list(int16 x, int16 y, int16 index) {
+ for (Icon *icon = &_gameIcons[index]; icon->sx >= 0; icon++) {
+ if (icon->_cursorId & 0x8000)
+ continue;
+#if 0
+ // MAC version use this check. Same check is present in PC version, but never used
+ // Because of x >= clause two adjacent rooms has 1-pixel wide dead zone between them
+ // On valley view screens if cursor slips in this zone a crash in FRDevents occurs
+ // due to lack of proper checks
+ if (x < icon->ff_0 || x >= icon->ff_4
+ || y < icon->ff_2 || y >= icon->ff_6)
+#else
+ // PC version has this check inlined in FRDevents
+ // Should we keep it or fix edge coordinates in afroom() instead?
+ if (x < icon->sx || x > icon->ex
+ || y < icon->sy || y > icon->ey)
+#endif
+ continue;
+ return icon;
+ }
+ return nullptr;
+}
+
+void EdenGame::updateCursor() {
+ if (++_torchTick > 3)
+ _torchTick = 0;
+ if (!_torchTick) {
+ _torchCurIndex++;
+ _glowIndex++;
+ }
+ if (_torchCurIndex > 8)
+ _torchCurIndex = 0;
+ if (_glowIndex > 4)
+ _glowIndex = 0;
+
+ if (!_torchCursor) {
+ useMainBank();
+ sundcurs(_cursorPosX + _scrollPos, _cursorPosY);
+ if (_currCursor != 53 && _currCursor < 10) { //TODO: cond
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ engineMac();
+ else
+ enginePC();
+ } else
+ drawSprite(_currCursor, _cursorPosX + _scrollPos, _cursorPosY);
+ _glowX = 1;
+ } else {
+ useBank(117);
+ if (_cursorPosX > 294)
+ _cursorPosX = 294;
+ unglow();
+ glow(_glowIndex);
+ drawSprite(_torchCurIndex, _cursorPosX + _scrollPos, _cursorPosY);
+ if (_frescoTalk)
+ displaySubtitles();
+ }
+}
+
+void EdenGame::mouse() {
+ static void (EdenGame::*mouse_actions[])() = {
+ &EdenGame::actionMoveNorth,
+ &EdenGame::actionMoveEast,
+ &EdenGame::actionMoveSouth,
+ &EdenGame::actionMoveWest,
+ &EdenGame::actionPlateMonk,
+ &EdenGame::actionGraaFrescoe,
+ &EdenGame::actionPushStone,
+ &EdenGame::actionSkelettonHead,
+ &EdenGame::actionMummyHead,
+ &EdenGame::actionMoveNorth,
+ &EdenGame::actionKingDialog1,
+ &EdenGame::actionKingDialog2,
+ &EdenGame::actionKingDialog3,
+ &EdenGame::actionGotoHall,
+ &EdenGame::actionLabyrinthTurnAround,
+ &EdenGame::actionSkelettonMoorkong,
+ &EdenGame::actionGotoFullNest,
+ &EdenGame::actionLookLake,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionFinal,
+ &EdenGame::actionMoveNorth,
+ &EdenGame::actionMoveSouth,
+ &EdenGame::actionVisit,
+ &EdenGame::actionDinoBlow,
+ &EdenGame::actionLascFrescoe,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ &EdenGame::actionGotoVal,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionGetPrism,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionGetEgg,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionGetMushroom,
+ &EdenGame::actionGetBadMushroom,
+ &EdenGame::actionGetKnife,
+ &EdenGame::actionGetEmptyNest,
+ &EdenGame::actionGetFullNest,
+ &EdenGame::actionGetGold,
+ nullptr,
+ &EdenGame::actionNop,
+ &EdenGame::actionGetSunStone,
+ &EdenGame::actionGetHorn,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ &EdenGame::actionNop,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionGetTablet,
+ &EdenGame::actionClickValleyPlan,
+ &EdenGame::actionEndFrescoes,
+ &EdenGame::actionChoose,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::actionKing,
+ &EdenGame::actionDina,
+ &EdenGame::actionThoo,
+ &EdenGame::actionMonk,
+ &EdenGame::actionTormentor,
+ &EdenGame::actionMessenger,
+ &EdenGame::actionMango,
+ &EdenGame::actionEve,
+ &EdenGame::actionAzia,
+ &EdenGame::actionMammi,
+ &EdenGame::actionGuards,
+ &EdenGame::actionFisher,
+ &EdenGame::actionDino,
+ &EdenGame::actionTyran,
+ &EdenGame::actionMorkus,
+ &EdenGame::actionNop,
+ &EdenGame::parle_moi,
+ &EdenGame::actionAdam,
+ &EdenGame::actionTakeObject,
+ &EdenGame::putObject,
+ &EdenGame::clictimbre,
+ &EdenGame::handleDinaDialog,
+ &EdenGame::closeCharacterScreen,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &EdenGame::generique,
+ &EdenGame::choseSubtitleOption,
+ &EdenGame::edenQuit,
+ &EdenGame::restart,
+ &EdenGame::cancel2,
+ &EdenGame::testvoice,
+ &EdenGame::changeVolume,
+ &EdenGame::load,
+ &EdenGame::save,
+ &EdenGame::cliccurstape,
+ &EdenGame::playtape,
+ &EdenGame::stoptape,
+ &EdenGame::rewindtape,
+ &EdenGame::forwardtape,
+ &EdenGame::confirmYes,
+ &EdenGame::confirmNo,
+ &EdenGame::actionGotoMap
+ };
+
+ if (!(_currSpot = scan_icon_list(_cirsorPanX + _cursCenter,
+ _cursorPosY + _cursCenter, _globals->_iconsIndex)))
+ return;
+ _curSpot2 = _currSpot;
+ debug("invoking mouse action %d", _currSpot->_actionId);
+ if (mouse_actions[_currSpot->_actionId])
+ (this->*mouse_actions[_currSpot->_actionId])();
+}
+
+////// sound.c
+void EdenGame::musique() {
+ if (_globals->_newMusicType == MusicType::mtDontChange)
+ return;
+
+ Dialog *dial = (Dialog *)getElem(_gameDialogs, 128);
+ for (;;dial++) {
+ if (dial->_flags == -1 && dial->_condNumLow == -1)
+ return;
+ byte flag = dial->_flags;
+ byte hidx = (dial->_textCondHiMask & 0xC0) >> 6;
+ byte lidx = dial->_condNumLow; //TODO: fixme - unsigned = signed
+ if (flag & 0x10)
+ hidx |= 4;
+ if (testCondition(((hidx << 8) | lidx) & 0x7FF))
+ break;
+ }
+ byte mus = dial->_textNumLow;
+ _globals->_newMusicType = MusicType::mtDontChange;
+ if (mus != 0 && mus != 2 && mus < 50)
+ startmusique(mus);
+}
+
+void EdenGame::startmusique(byte num) {
+ if (num == _globals->_currMusicNum)
+ return;
+
+ if (_musicPlayingFlag) {
+ fademusica0(1);
+ _musicChannel->stop();
+ }
+ loadmusicfile(num);
+ _globals->_currMusicNum = num;
+ _musSequencePtr = _musicBuf + 32; //TODO: rewrite it properly
+ int16 seq_size = READ_LE_UINT16(_musicBuf + 30);
+ _musicPatternsPtr = _musicBuf + 30 + seq_size;
+ int16 pat_size = READ_LE_UINT16(_musicBuf + 27);
+ _musicSamplesPtr = _musicBuf + 32 + 4 + pat_size;
+ int16 freq = READ_LE_UINT16(_musicSamplesPtr - 2);
+
+ delete _musicChannel;
+ _musicChannel = new CSoundChannel(_vm->_mixer, freq == 166 ? 11025 : 22050, false);
+ _musicEnabledFlag = true;
+
+ _musicSequencePos = 0;
+ _musicLeftVol = _globals->_prefMusicVol[0];
+ _musicRightVol = _globals->_prefMusicVol[1];
+ _musicChannel->setVolume(_musicLeftVol, _musicRightVol);
+}
+
+void EdenGame::musicspy() {
+ if (!_musicEnabledFlag)
+ return;
+ _musicLeftVol = _globals->_prefMusicVol[0];
+ _musicRightVol = _globals->_prefMusicVol[1];
+ if (_musicFadeFlag & 3)
+ fademusicup();
+ if (_personTalking && !_voiceChannel->numQueued())
+ _musicFadeFlag = 3;
+ if (_musicChannel->numQueued() < 3) {
+ byte patnum = _musSequencePtr[(int)_musicSequencePos];
+ if (patnum == 0xFF) {
+ // rewind
+ _musicSequencePos = 0;
+ patnum = _musSequencePtr[(int)_musicSequencePos];
+ }
+ _musicSequencePos++;
+ byte *patptr = _musicPatternsPtr + patnum * 6;
+ int ofs = patptr[0] + (patptr[1] << 8) + (patptr[2] << 16);
+ int len = patptr[3] + (patptr[4] << 8) + (patptr[5] << 16);
+ _musicChannel->queueBuffer(_musicSamplesPtr + ofs, len);
+ _musicPlayingFlag = true;
+ }
+}
+
+void EdenGame::persovox() {
+ int16 num = _globals->_textNum;
+ if (_globals->_textBankIndex != 1)
+ num += 565;
+ if (_globals->_textBankIndex == 3)
+ num += 707;
+ _voiceSamplesSize = loadSound(num);
+ int16 volumeLeft = _globals->_prefSoundVolume[0];
+ int16 volumeRight = _globals->_prefSoundVolume[1];
+ int16 stepLeft = _musicChannel->_volumeLeft < volumeLeft ? 1 : -1;
+ int16 stepRight = _musicChannel->_volumeRight < volumeRight ? 1 : -1;
+ do {
+ if (volumeLeft != _musicChannel->_volumeLeft)
+ _musicChannel->setVolumeLeft(_musicChannel->_volumeLeft + stepLeft);
+ if (volumeRight != _musicChannel->_volumeRight)
+ _musicChannel->setVolumeRight(_musicChannel->_volumeRight + stepRight);
+ } while (_musicChannel->_volumeLeft != volumeLeft || _musicChannel->_volumeRight != volumeRight);
+ volumeLeft = _globals->_prefVoiceVol[0];
+ volumeRight = _globals->_prefVoiceVol[1];
+ _voiceChannel->setVolume(volumeLeft, volumeRight);
+ _voiceChannel->queueBuffer(_voiceSamplesBuffer, _voiceSamplesSize, true);
+ _personTalking = true;
+ _musicFadeFlag = 0;
+ _lastAnimTicks = _vm->_timerTicks;
+}
+
+// Original name: endpersovox
+void EdenGame::endCharacterSpeech() {
+ restoreUnderSubtitles();
+ if (_personTalking) {
+ _voiceChannel->stop();
+ _personTalking = false;
+ _musicFadeFlag = 3;
+ }
+
+ if (_soundAllocated) {
+ free(_voiceSamplesBuffer);
+ _voiceSamplesBuffer = nullptr;
+ _soundAllocated = false;
+ }
+}
+
+void EdenGame::fademusicup() {
+ if (_musicFadeFlag & 2) {
+ int16 vol = _musicChannel->_volumeLeft;
+ if (vol < _musicLeftVol) {
+ vol += 8;
+ if (vol > _musicLeftVol)
+ vol = _musicLeftVol;
+ } else {
+ vol -= 8;
+ if (vol < _musicLeftVol)
+ vol = _musicLeftVol;
+ }
+ _musicChannel->setVolumeLeft(vol);
+ if (vol == _musicLeftVol)
+ _musicFadeFlag &= ~2;
+ }
+ if (_musicFadeFlag & 1) {
+ int16 vol = _musicChannel->_volumeRight;
+ if (vol < _musicRightVol) {
+ vol += 8;
+ if (vol > _musicRightVol)
+ vol = _musicRightVol;
+ } else {
+ vol -= 8;
+ if (vol < _musicRightVol)
+ vol = _musicRightVol;
+ }
+ _musicChannel->setVolumeRight(vol);
+ if (vol == _musicRightVol)
+ _musicFadeFlag &= ~1;
+ }
+}
+
+void EdenGame::fademusica0(int16 delay) {
+ int16 volume;
+ while ((volume = _musicChannel->getVolume()) > 2) {
+ volume -= 2;
+ if (volume < 2)
+ volume = 2;
+ _musicChannel->setVolume(volume, volume);
+ wait(delay);
+ }
+}
+
+//// obj.c
+
+// Original name: getobjaddr
+object_t *EdenGame::getObjectPtr(int16 id) {
+ int i;
+ for (i = 0; i < MAX_OBJECTS; i++) {
+ if (_objects[i]._id == id)
+ break;
+ }
+
+ return &_objects[i];
+}
+
+void EdenGame::countObjects() {
+ int16 index = 0;
+ byte total = 0;
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ int16 count = _objects[i]._count;
+ if (count == 0)
+ continue;
+
+ if (_objects[i]._flags & ObjectFlags::ofInHands)
+ count--;
+
+ if (count) {
+ total += count;
+ while (count--)
+ _ownObjects[index++] = _objects[i]._id;
+ }
+ }
+ _globals->_objCount = total;
+}
+
+void EdenGame::showObjects() {
+ Icon *icon = &_gameIcons[_invIconsBase];
+ _globals->_drawFlags &= ~(DrawFlags::drDrawInventory | DrawFlags::drDrawFlag2);
+ countObjects();
+ int16 total = _globals->_objCount;
+ for (int16 i = _invIconsCount; i--; icon++) {
+ if (total) {
+ icon->_cursorId &= ~0x8000;
+ total--;
+ } else
+ icon->_cursorId |= 0x8000;
+ }
+ useMainBank();
+ drawSprite(55, 0, 176);
+ icon = &_gameIcons[_invIconsBase];
+ total = _globals->_objCount;
+ int16 index = _globals->_inventoryScrollPos;
+ for (int16 i = _invIconsCount; total-- && i--; icon++) {
+ char obj = _ownObjects[index++];
+ icon->_objectId = obj;
+ drawSprite(obj + 9, icon->sx, 178);
+ }
+ _paletteUpdateRequired = true;
+ if ((_globals->_displayFlags & DisplayFlags::dfMirror) || (_globals->_displayFlags & DisplayFlags::dfPanable)) {
+ saveBottomFrieze();
+ scroll();
+ }
+}
+
+void EdenGame::winObject(int16 id) {
+ object_t *object = getObjectPtr(id);
+ object->_flags |= ObjectFlags::ofFlag1;
+ object->_count++;
+ _globals->_curItemsMask |= object->_itemMask;
+ _globals->_wonItemsMask |= object->_itemMask;
+ _globals->_curPowersMask |= object->_powerMask;
+ _globals->_wonPowersMask |= object->_powerMask;
+}
+
+void EdenGame::loseObject(int16 id) {
+ object_t *object = getObjectPtr(id);
+ if (object->_count > 0)
+ object->_count--;
+ if (!object->_count) {
+ object->_flags &= ~ObjectFlags::ofFlag1;
+ _globals->_curItemsMask &= ~object->_itemMask;
+ _globals->_curPowersMask &= ~object->_powerMask;
+ }
+ _globals->_curObjectId = 0;
+ _globals->_curObjectFlags = 0;
+ _globals->_curObjectCursor = 9;
+ _gameIcons[16]._cursorId |= 0x8000;
+ object->_flags &= ~ObjectFlags::ofInHands;
+ _normalCursor = true;
+ _currCursor = 0;
+ _torchCursor = false;
+}
+
+void EdenGame::lostObject() {
+ parlemoiNormalFlag = true;
+ if (_globals->_curObjectId)
+ loseObject(_globals->_curObjectId);
+}
+
+// Original name: objecthere
+bool EdenGame::isObjectHere(int16 id) {
+ object_t *object = getObjectPtr(id);
+ for (_currentObjectLocation = &_objectLocations[object->_locations]; *_currentObjectLocation != 0xFFFF; _currentObjectLocation++) {
+ if (*_currentObjectLocation == _globals->_roomNum)
+ return true;
+ }
+ return false;
+}
+
+void EdenGame::objectmain(int16 id) {
+ object_t *object = getObjectPtr(id);
+ _gameIcons[16]._cursorId &= ~0x8000;
+ _globals->_curObjectId = object->_id;
+ _globals->_curObjectCursor = _globals->_curObjectId + 9;
+ object->_flags |= ObjectFlags::ofInHands;
+ _globals->_curObjectFlags = object->_flags;
+ _currCursor = _globals->_curObjectId + 9;
+ _normalCursor = false;
+}
+
+void EdenGame::getObject(int16 id) {
+ Room *room = _globals->_roomPtr;
+ if (_globals->_curObjectId)
+ return;
+ if (!isObjectHere(id))
+ return;
+ *_currentObjectLocation |= 0x8000;
+ objectmain(id);
+ winObject(id);
+ showObjects();
+ _globals->_roomImgBank = room->_bank;
+ _globals->_roomVidNum = room->_video;
+ displayPlace();
+}
+
+void EdenGame::putObject() {
+ if (!_globals->_curObjectId)
+ return;
+ _gameIcons[16]._cursorId |= 0x8000;
+ object_t *object = getObjectPtr(_globals->_curObjectId);
+ _globals->_curObjectCursor = 9;
+ _globals->_curObjectId = 0;
+ _globals->_curObjectFlags = 0;
+ object->_flags &= ~ObjectFlags::ofInHands;
+ _globals->_nextDialogPtr = nullptr;
+ _closeCharacterDialog = false;
+ _globals->_dialogType = DialogType::dtTalk;
+ showObjects();
+ _normalCursor = true;
+}
+
+void EdenGame::newObject(int16 id, int16 arg2) {
+ object_t *object = getObjectPtr(id);
+ uint16 e, *t = &_objectLocations[object->_locations];
+ while ((e = *t) != 0xFFFF) {
+ e &= ~0x8000;
+ if ((e >> 8) == arg2)
+ *t = e;
+ t++;
+ }
+}
+
+void EdenGame::giveobjectal(int16 id) {
+ if (id == Objects::obKnife)
+ _objectLocations[2] = 0;
+ if (id == Objects::obApple)
+ _globals->_stepsToFindAppleNormal = 0;
+ if (id >= Objects::obEyeInTheStorm && id < (Objects::obRiverThatWinds + 1) && _globals->_roomCharacterType == PersonFlags::pftVelociraptor) {
+ //TODO: fix that cond above
+ object_t *object = getObjectPtr(id);
+ _globals->_roomCharacterPtr->_powers &= ~object->_powerMask;
+ }
+ winObject(id);
+}
+
+void EdenGame::giveObject() {
+ byte id = _globals->_giveObj1;
+ if (id) {
+ _globals->_giveObj1 = 0;
+ giveobjectal(id);
+ }
+ id = _globals->_giveObj2;
+ if (id) {
+ _globals->_giveObj2 = 0;
+ giveobjectal(id);
+ }
+ id = _globals->_giveObj3;
+ if (id) {
+ _globals->_giveObj3 = 0;
+ giveobjectal(id);
+ }
+}
+
+// Original name: takeObject
+void EdenGame::actionTakeObject() {
+ objectmain(_curSpot2->_objectId);
+ _globals->_nextDialogPtr = nullptr;
+ _closeCharacterDialog = false;
+ _globals->_dialogType = DialogType::dtTalk;
+ if (_globals->_inventoryScrollPos)
+ _globals->_inventoryScrollPos--;
+ showObjects();
+}
+////
+
+// Original name: newchampi
+void EdenGame::newMushroom() {
+ if (_objects[Objects::obShroom - 1]._count == 0) {
+ newObject(Objects::obShroom, _globals->_citadelAreaNum);
+ newObject(Objects::obBadShroom, _globals->_citadelAreaNum);
+ }
+}
+
+// Original name: newnidv
+void EdenGame::newEmptyNest() {
+ Room *room = _globals->_citaAreaFirstRoom;
+ if (_objects[Objects::obNest - 1]._count)
+ return;
+ object_t *obj = getObjectPtr(Objects::obNest);
+ for (uint16 *ptr = _objectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) {
+ if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum)
+ continue;
+ *ptr &= ~0x8000;
+ for (; room->_id != 0xFF; room++) {
+ if (room->_location == (*ptr & 0xFF)) {
+ room->_bank = 279;
+ room->_id = 9;
+ room++;
+ room->_bank = 280;
+ return;
+ }
+ }
+ }
+}
+
+// Original name: newnido
+void EdenGame::newNestWithEggs() {
+ Room *room = _globals->_citaAreaFirstRoom;
+ if (_objects[Objects::obFullNest - 1]._count)
+ return;
+ if (_objects[Objects::obNest - 1]._count)
+ return;
+ object_t *obj = getObjectPtr(Objects::obFullNest);
+ for (uint16 *ptr = _objectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) {
+ if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum)
+ continue;
+ *ptr &= ~0x8000;
+ for (; room->_id != 0xFF; room++) {
+ if (room->_location == (*ptr & 0xFF)) {
+ room->_bank = 277;
+ room->_id = 9;
+ room++;
+ room->_bank = 278;
+ return;
+ }
+ }
+ }
+}
+
+// Original name: newor
+void EdenGame::newGold() {
+ if (_objects[Objects::obGold - 1]._count == 0)
+ newObject(Objects::obGold, _globals->_citadelAreaNum);
+}
+
+void EdenGame::gotoPanel() {
+ if (_vm->shouldQuit())
+ byte_31D64 = _globals->_autoDialog; //TODO: check me
+ _noPalette = false;
+ _globals->_iconsIndex = 85;
+ _globals->_characterPtr = nullptr;
+ _globals->_drawFlags |= DrawFlags::drDrawMenu;
+ _globals->_displayFlags = DisplayFlags::dfFlag2;
+ _globals->_menuFlags = 0;
+ displayPanel();
+ fadeToBlack(3);
+ displayTopPanel();
+ CLBlitter_CopyView2Screen(_mainView);
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+ _cursorPosX = 320 / 2;
+ _cursorPosY = 200 / 2;
+ _vm->setMousePosition(_mouseCenterX, _mouseCenterY);
+}
+
+void EdenGame::noclicpanel() {
+ if (_globals->_menuFlags & MenuFlags::mfFlag4) {
+ depcurstape();
+ return;
+ }
+ if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
+ return;
+ if (_globals->_menuFlags & MenuFlags::mfFlag1) {
+ changervol();
+ return;
+ }
+ byte num;
+ if (_curSpot2 >= &_gameIcons[119]) {
+ debug("noclic: objid = %p, glob3,2 = %2X %2X", (void *)_curSpot2, _globals->_menuItemIdHi, _globals->_menuItemIdLo);
+ if (_curSpot2->_objectId == (uint16)((_globals->_menuItemIdLo + _globals->_menuItemIdHi) << 8)) //TODO: check me
+ return;
+ } else {
+ int idx = _curSpot2 - &_gameIcons[105];
+ if (idx == 0) {
+ _globals->_menuItemIdLo = 1;
+ num = 1;
+ goto skip;
+ }
+ num = (idx & 0x7F) + 1;
+ if (num >= 5)
+ num = 1;
+ if (num == _globals->_var43)
+ return;
+ _globals->_var43 = 0;
+ }
+ num = _globals->_menuItemIdLo;
+ _globals->_menuItemIdLo = _curSpot2->_objectId & 0xFF;
+skip:
+ ;
+ _globals->_menuItemIdHi = (_curSpot2->_objectId & 0xFF00) >> 8;
+ debug("noclic: new glob3,2 = %2X %2X", _globals->_menuItemIdHi, _globals->_menuItemIdLo);
+ displayResult();
+ num &= 0xF0;
+ if (num != 0x30)
+ num = _globals->_menuItemIdLo & 0xF0;
+ if (num == 0x30)
+ displayCursors();
+}
+
+void EdenGame::generique() {
+ drawBlackBars();
+ display();
+ fadeToBlack(3);
+ clearScreen();
+ int oldmusic = _globals->_currMusicNum;
+ playHNM(95);
+ displayPanel();
+ displayTopPanel();
+ _paletteUpdateRequired = true;
+ startmusique(oldmusic);
+}
+
+void EdenGame::cancel2() {
+ drawTopScreen();
+ showObjects();
+ _globals->_iconsIndex = 16;
+ _globals->_drawFlags &= ~DrawFlags::drDrawMenu;
+ gameToMirror(1);
+}
+
+void EdenGame::testvoice() {
+ _globals->_frescoNumber = 0;
+ _globals->_characterPtr = _persons;
+ _globals->_dialogType = DialogType::dtInspect;
+ int16 num = (_persons[PER_KING]._id << 3) | _globals->_dialogType;
+ dialoscansvmas((Dialog *)getElem(_gameDialogs, num));
+ restoreUnderSubtitles();
+ displaySubtitles();
+ persovox();
+ waitEndSpeak();
+ endCharacterSpeech();
+ _globals->_varCA = 0;
+ _globals->_dialogType = DialogType::dtTalk;
+}
+
+void EdenGame::load() {
+ char name[132];
+ _gameLoaded = false;
+ byte oldMusic = _globals->_currMusicNum; //TODO: from uint16 to byte?!
+ fademusica0(1);
+ desktopcolors();
+ FlushEvents(-1, 0);
+// if(OpenDialog(0, 0)) //TODO: write me
+ {
+ // TODO
+ strcpy(name, "edsave1.000");
+ loadgame(name);
+ }
+ _vm->hideMouse();
+ CLBlitter_FillScreenView(0xFFFFFFFF);
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0);
+ if (!_gameLoaded) {
+ _musicFadeFlag = 3;
+ musicspy();
+ _paletteUpdateRequired = true;
+ return;
+ }
+ if ((oldMusic & 0xFF) != _globals->_currMusicNum) { //TODO: r30 is uns char/bug???
+ oldMusic = _globals->_currMusicNum;
+ _globals->_currMusicNum = 0;
+ startmusique(oldMusic);
+ } else {
+ _musicFadeFlag = 3;
+ musicspy();
+ }
+ bool talk = _globals->_autoDialog; //TODO check me
+ initafterload();
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0);
+ CLBlitter_FillView(_mainView, 0);
+ drawTopScreen();
+ _globals->_inventoryScrollPos = 0;
+ showObjects();
+ updateRoom(_globals->_roomNum);
+ if (talk) {
+ _globals->_iconsIndex = 4;
+ _globals->_autoDialog = true;
+ parle_moi();
+ }
+
+}
+
+void EdenGame::initafterload() {
+ _globals->_characterImageBank = 0;
+ _globals->_lastPlaceNum = 0;
+ loadPlace(_globals->_areaPtr->_placeNum);
+ _gameIcons[18]._cursorId |= 0x8000;
+ if (_globals->_curAreaType == AreaType::atValley)
+ _gameIcons[18]._cursorId &= ~0x8000;
+ _personRoomBankTable[30] = 27;
+ if (_globals->_phaseNum >= 352)
+ _personRoomBankTable[30] = 26;
+ _animateTalking = false;
+ _animationActive = false;
+ _globals->_var100 = 0;
+ _globals->_eventType = EventType::etEventC;
+ _globals->_valleyVidNum = 0;
+ _globals->_drawFlags &= ~DrawFlags::drDrawMenu;
+ _currentTime = _vm->_timerTicks / 100;
+ _globals->_gameTime = _currentTime;
+ if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
+ setChrono(3000);
+ _adamMapMarkPos.x = -1;
+ _adamMapMarkPos.y = -1;
+}
+
+void EdenGame::save() {
+ char name[260];
+ fademusica0(1);
+ desktopcolors();
+ FlushEvents(-1, 0);
+ //SaveDialog(byte_37150, byte_37196->ff_A);
+ //TODO
+ strcpy(name, "edsave1.000");
+ saveGame(name);
+ _vm->hideMouse();
+ CLBlitter_FillScreenView(0xFFFFFFFF);
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0);
+ _musicFadeFlag = 3;
+ musicspy();
+ _paletteUpdateRequired = true;
+}
+
+void EdenGame::desktopcolors() {
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0xFFFFFFFF);
+ CLPalette_BeSystem();
+ _vm->showMouse();
+}
+
+void EdenGame::panelrestart() {
+ _gameLoaded = false;
+ byte curmus = _globals->_currMusicNum;
+ byte curlng = _globals->_prefLanguage;
+ loadrestart();
+ _globals->_prefLanguage = curlng;
+ if (!_gameLoaded) //TODO always?
+ return;
+ _globals->_characterImageBank = 0;
+ _globals->_lastPlaceNum = 0;
+ loadPlace(_globals->_areaPtr->_placeNum);
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ _gameIcons[18]._cursorId |= 0x8000;
+ if (_globals->_curAreaType == AreaType::atValley)
+ _gameIcons[18]._cursorId &= ~0x8000;
+ _personRoomBankTable[30] = 27;
+ if (_globals->_phaseNum >= 352)
+ _personRoomBankTable[30] = 26;
+ _animateTalking = false;
+ _animationActive = false;
+ _globals->_var100 = 0;
+ _globals->_eventType = 0;
+ _globals->_valleyVidNum = 0;
+ _globals->_drawFlags &= ~DrawFlags::drDrawMenu;
+ _globals->_inventoryScrollPos = 0;
+ _adamMapMarkPos.x = -1;
+ _adamMapMarkPos.y = -1;
+ if (curmus != _globals->_currMusicNum) {
+ curmus = _globals->_currMusicNum;
+ _globals->_currMusicNum = 0;
+ startmusique(curmus);
+ }
+ fadeToBlack(3);
+ CLBlitter_FillScreenView(0);
+ CLBlitter_FillView(_mainView, 0);
+ drawTopScreen();
+ showObjects();
+ saveFriezes();
+ _showBlackBars = true;
+ updateRoom(_globals->_roomNum);
+}
+
+void EdenGame::reallyquit() {
+ _quitFlag3 = true;
+ _quitFlag2 = true;
+}
+
+void EdenGame::confirmer(char mode, char yesId) {
+ _globals->_iconsIndex = 119;
+ _gameIcons[119]._objectId = yesId;
+ _confirmMode = mode;
+ useBank(65);
+ drawSprite(12, 117, 74);
+ _cursorPosX = 156;
+ if (_vm->shouldQuit())
+ _cursorPosX = 136;
+ _cursorPosY = 88;
+}
+
+void EdenGame::confirmYes() {
+ displayPanel();
+ _globals->_iconsIndex = 85;
+ switch (_confirmMode) {
+ case 1:
+ panelrestart();
+ break;
+ case 2:
+ reallyquit();
+ break;
+ }
+}
+
+void EdenGame::confirmNo() {
+ displayPanel();
+ _globals->_iconsIndex = 85;
+// pomme_q = false;
+}
+
+void EdenGame::restart() {
+ confirmer(1, _curSpot2->_objectId);
+}
+
+void EdenGame::edenQuit() {
+ confirmer(2, _curSpot2->_objectId);
+}
+
+// Original name: choixsubtitle
+void EdenGame::choseSubtitleOption() {
+ byte lang = _curSpot2->_objectId & 0xF;
+ if (lang == _globals->_prefLanguage)
+ return;
+ if (lang > 5)
+ return;
+ _globals->_prefLanguage = lang;
+ langbuftopanel();
+ displayLanguage();
+}
+
+// Original name: reglervol
+void EdenGame::changeVolume() {
+ byte *valptr = &_globals->_prefMusicVol[_curSpot2->_objectId & 7];
+ _cursorPosY = 104 - ((*valptr >> 2) & 0x3F); // TODO: check me
+ _curSliderValuePtr = valptr;
+ _globals->_menuFlags |= MenuFlags::mfFlag1;
+ if (_curSpot2->_objectId & 8)
+ _globals->_menuFlags |= MenuFlags::mfFlag2;
+ _curSliderX = _curSpot2->sx;
+ _curSliderY = _cursorPosY;
+}
+
+void EdenGame::changervol() {
+ if (_mouseHeld) {
+ restrictCursorArea(_curSliderX - 1, _curSliderX + 3, 40, 110);
+ int16 delta = _curSliderY - _cursorPosY;
+ if (delta == 0)
+ return;
+ newvol(_curSliderValuePtr, delta);
+ if (_globals->_menuFlags & MenuFlags::mfFlag2)
+ newvol(_curSliderValuePtr + 1, delta);
+ cursbuftopanel();
+ displayCursors();
+ _curSliderY = _cursorPosY;
+ } else
+ _globals->_menuFlags &= ~(MenuFlags::mfFlag1 | MenuFlags::mfFlag2);
+}
+
+void EdenGame::newvol(byte *volptr, int16 delta) {
+ int16 vol = *volptr / 4;
+ vol += delta;
+ if (vol < 0)
+ vol = 0;
+ if (vol > 63)
+ vol = 63;
+ *volptr = vol * 4;
+ _musicChannel->setVolume(_globals->_prefMusicVol[0], _globals->_prefMusicVol[1]);
+}
+
+void EdenGame::playtape() {
+ if (_globals->_menuItemIdHi & 8)
+ _globals->_tapePtr++;
+ for (;; _globals->_tapePtr++) {
+ if (_globals->_tapePtr == &_tapes[MAX_TAPES]) {
+ _globals->_tapePtr--;
+ stoptape();
+ return;
+ }
+ if (_globals->_tapePtr->_textNum)
+ break;
+ }
+ _globals->_menuFlags |= MenuFlags::mfFlag8;
+ _globals->_drawFlags &= ~DrawFlags::drDrawMenu;
+ uint16 oldRoomNum = _globals->_roomNum;
+ uint16 oldParty = _globals->_party;
+ byte oldBack = _globals->_roomBackgroundBankNum;
+ perso_t *oldPerso = _globals->_characterPtr;
+ _globals->_party = _globals->_tapePtr->_party;
+ _globals->_roomNum = _globals->_tapePtr->_roomNum;
+ _globals->_roomBackgroundBankNum = _globals->_tapePtr->_backgroundBankNum;
+ _globals->_dialogPtr = _globals->_tapePtr->_dialog;
+ _globals->_characterPtr = _globals->_tapePtr->_perso;
+ endCharacterSpeech();
+ affcurstape();
+ if (_globals->_characterPtr != oldPerso
+ || _globals->_roomNum != _lastTapeRoomNum) {
+ _lastTapeRoomNum = _globals->_roomNum;
+ _globals->_curCharacterAnimPtr = nullptr;
+ _globals->_varCA = 0;
+ _globals->_characterImageBank = -1;
+ AnimEndCharacter();
+ loadCurrCharacter();
+ }
+ displayCharacterBackground();
+ _globals->_textNum = _globals->_tapePtr->_textNum;
+ my_bulle();
+ getDataSync();
+ displayCharacterPanel();
+ persovox();
+ _globals->_roomBackgroundBankNum = oldBack;
+ _globals->_party = oldParty;
+ _globals->_roomNum = oldRoomNum;
+}
+
+void EdenGame::rewindtape() {
+ if (_globals->_tapePtr > _tapes) {
+ _globals->_tapePtr--;
+ _globals->_menuFlags &= ~MenuFlags::mfFlag8;
+ affcurstape();
+ }
+}
+
+void EdenGame::depcurstape() {
+ if (_mouseHeld) {
+ restrictCursorArea(95, 217, 179, 183);
+ int idx = (_cursorPosX - 97);
+ if (idx < 0)
+ idx = 0;
+
+ idx /= 8;
+ tape_t *tape = _tapes + idx;
+ if (tape >= _tapes + 16)
+ tape = _tapes + 16 - 1;
+
+ if (tape != _globals->_tapePtr) {
+ _globals->_tapePtr = tape;
+ affcurstape();
+ _globals->_menuFlags &= ~MenuFlags::mfFlag8;
+ }
+ } else
+ _globals->_menuFlags &= ~MenuFlags::mfFlag4;
+}
+
+void EdenGame::affcurstape() {
+ if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
+ _noPalette = true;
+ useBank(65);
+ drawSprite(2, 0, 176);
+ int x = (_globals->_tapePtr - _tapes) * 8 + 97;
+ _gameIcons[112].sx = x - 3;
+ _gameIcons[112].ex = x + 3;
+ drawSprite(5, x, 179);
+ _noPalette = false;
+}
+
+void EdenGame::forwardtape() {
+ if (_globals->_tapePtr < _tapes + 16) {
+ _globals->_tapePtr++;
+ _globals->_menuFlags &= ~MenuFlags::mfFlag8;
+ affcurstape();
+ }
+}
+
+void EdenGame::stoptape() {
+ if (!(_globals->_drawFlags & DrawFlags::drDrawFlag8))
+ return;
+ _globals->_menuFlags &= ~MenuFlags::mfFlag8;
+ _globals->_drawFlags &= ~DrawFlags::drDrawFlag8;
+ _globals->_menuFlags |= MenuFlags::mfFlag10;
+ _globals->_iconsIndex = 85;
+ _globals->_characterPtr = nullptr;
+ _lastTapeRoomNum = 0;
+ endCharacterSpeech();
+ fin_perso();
+ displayPanel();
+ displayTopPanel();
+ _paletteUpdateRequired = true;
+}
+
+void EdenGame::cliccurstape() {
+ _globals->_menuFlags |= MenuFlags::mfFlag4;
+}
+
+void EdenGame::paneltobuf() {
+ setSrcRect(0, 16, 320 - 1, 169 - 1);
+ setDestRect(320, 16, 640 - 1, 169 - 1);
+ CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst);
+}
+
+void EdenGame::cursbuftopanel() {
+ setSrcRect(434, 40, 525 - 1, 111 - 1);
+ setDestRect(114, 40, 205 - 1, 111 - 1);
+ CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst);
+}
+
+void EdenGame::langbuftopanel() {
+ setSrcRect(328, 42, 407 - 1, 97 - 1);
+ setDestRect(8, 42, 87 - 1, 97 - 1);
+ CLBlitter_CopyViewRect(_mainView, _mainView, &rect_src, &rect_dst);
+}
+
+// Original name: affpanel
+void EdenGame::displayPanel() {
+ useBank(65);
+ drawSprite(0, 0, 16);
+ paneltobuf();
+ displayLanguage();
+ displayCursors();
+ affcurstape();
+}
+
+// Original name: afflangue
+void EdenGame::displayLanguage() {
+ useBank(65);
+ if (_globals->_prefLanguage > 5)
+ return;
+ drawSprite(6, 8, _globals->_prefLanguage * 9 + 43); //TODO: * FONT_HEIGHT
+ drawSprite(7, 77, _globals->_prefLanguage * 9 + 44);
+}
+
+// Original name: affcursvol
+void EdenGame::displayVolCursor(int16 x, int16 vol1, int16 vol2) {
+ int16 slider = 3;
+ if (_lastMenuItemIdLo && (_lastMenuItemIdLo & 9) != 1) //TODO check me
+ slider = 4;
+ drawSprite(slider, x, 104 - vol1);
+ slider = 3;
+ if ((_lastMenuItemIdLo & 9) != 0)
+ slider = 4;
+ drawSprite(slider, x + 12, 104 - vol2);
+}
+
+// Original name: affcurseurs
+void EdenGame::displayCursors() {
+ useBank(65);
+ if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
+ return;
+ selectCursor(48);
+ displayVolCursor(114, _globals->_prefMusicVol[0] / 4, _globals->_prefMusicVol[1] / 4);
+ selectCursor(50);
+ displayVolCursor(147, _globals->_prefVoiceVol[0] / 4, _globals->_prefVoiceVol[1] / 4);
+ selectCursor(52);
+ displayVolCursor(179, _globals->_prefSoundVolume[0] / 4, _globals->_prefSoundVolume[1] / 4);
+}
+
+// Original name: curseurselect
+void EdenGame::selectCursor(int itemId) {
+ _lastMenuItemIdLo = _globals->_menuItemIdLo;
+ if ((_lastMenuItemIdLo & ~9) != itemId)
+ _lastMenuItemIdLo = 0;
+}
+
+// Original name: afftoppano
+void EdenGame::displayTopPanel() {
+ drawSprite(1, 0, 0);
+}
+
+// Original name: affresult
+void EdenGame::displayResult() {
+ restoreUnderSubtitles();
+ _globals->_characterPtr = &_persons[19];
+ _globals->_dialogType = DialogType::dtInspect;
+ int16 num = (_persons[PER_UNKN_156]._id << 3) | _globals->_dialogType;
+ if (dialoscansvmas((Dialog *)getElem(_gameDialogs, num)))
+ displaySubtitles();
+ _globals->_varCA = 0;
+ _globals->_dialogType = DialogType::dtTalk;
+ _globals->_characterPtr = nullptr;
+}
+
+// Original name: limitezonecurs
+void EdenGame::restrictCursorArea(int16 xmin, int16 xmax, int16 ymin, int16 ymax) {
+ _cursorPosX = CLIP(_cursorPosX, xmin, xmax);
+ _cursorPosY = CLIP(_cursorPosY, ymin, ymax);
+}
+
+// Original name: PommeQ
+void EdenGame::edenShudown() {
+ Icon *icon = &_gameIcons[85];
+ if (_globals->_displayFlags & DisplayFlags::dfFrescoes) {
+ _torchCursor = false;
+ _cursorSaved = true;
+ if (_globals->_displayFlags & DisplayFlags::dfPerson)
+ closeCharacterScreen();
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ resetScroll();
+ _globals->_var100 = 0xFF;
+ updateRoom(_globals->_roomNum);
+ }
+ if (_globals->_displayFlags & DisplayFlags::dfPerson)
+ closeCharacterScreen();
+ if (_globals->_displayFlags & DisplayFlags::dfPanable)
+ resetScroll();
+ if (_globals->_displayFlags & DisplayFlags::dfMirror)
+ resetScroll();
+ if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
+ stoptape();
+ if (_personTalking)
+ endCharacterSpeech();
+ _globals->_var103 = 0;
+ _globals->_mirrorEffect = 0;
+ putObject();
+ _currCursor = 53;
+ if (_globals->_displayFlags != DisplayFlags::dfFlag2)
+ gotoPanel();
+ _curSpot2 = icon + 7; //TODO
+ edenQuit();
+}
+
+void EdenGame::habitants(perso_t *perso) {
+ char persType = perso->_flags & PersonFlags::pfTypeMask; //TODO rename
+ if (persType && persType != PersonFlags::pfType2) {
+ _globals->_roomCharacterPtr = perso;
+ _globals->_roomCharacterType = persType;
+ _globals->_roomCharacterFlags = perso->_flags;
+ _globals->_roomPersoItems = perso->_items;
+ _globals->_roomCharacterPowers = perso->_powers;
+ _globals->_partyOutside |= perso->_partyMask;
+ if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor)
+ removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn);
+ else if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor)
+ removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsIn);
+ } else if (!(perso->_flags & PersonFlags::pfInParty))
+ _globals->_partyOutside |= perso->_partyMask;
+}
+
+void EdenGame::suiveurs(perso_t *perso) {
+ char persType = perso->_flags & PersonFlags::pfTypeMask;
+ if (persType == 0 || persType == PersonFlags::pfType2) {
+ if (perso->_flags & PersonFlags::pfInParty)
+ _globals->_party |= perso->_partyMask;
+ }
+}
+
+void EdenGame::evenements(perso_t *perso) {
+ if (_globals->_var113)
+ return;
+
+ if (perso >= &_persons[PER_UNKN_18C])
+ return;
+
+ if (!dialogEvent(perso))
+ return;
+
+ _globals->_var113++;
+ _globals->_oldDisplayFlags = 1;
+ perso = _globals->_characterPtr;
+ initCharacterPointers(perso);
+ if (!(perso->_partyMask & PersonMask::pmLeader))
+ _globals->_var60 = 1;
+ _globals->_eventType = 0;
+}
+
+void EdenGame::followme(perso_t *perso) {
+ if (perso->_flags & PersonFlags::pfTypeMask)
+ return;
+ if (perso->_flags & PersonFlags::pfInParty)
+ perso->_roomNum = _destinationRoom;
+}
+
+void EdenGame::rangermammi(perso_t *perso, Room *room) {
+ Room *found_room = nullptr;
+ if (!(perso->_partyMask & PersonMask::pmLeader))
+ return;
+ for (; room->_id != 0xFF; room++) {
+ if (room->_flags & RoomFlags::rfHasCitadel) {
+ found_room = room;
+ break;
+ }
+ if (room->_party != 0xFFFF && (room->_party & PersonMask::pmLeader))
+ found_room = room; //TODO: no brk?
+ }
+ if (!found_room)
+ return;
+ perso->_roomNum &= ~0xFF;
+ perso->_roomNum |= found_room->_location;
+ perso->_flags &= ~PersonFlags::pfInParty;
+ _globals->_party &= ~perso->_partyMask;
+}
+
+void EdenGame::perso_ici(int16 action) {
+ perso_t *perso = &_persons[PER_UNKN_156];
+// room_t *room = p_global->last_area_ptr->room_ptr; //TODO: compiler opt bug? causes access to zero ptr??? last_area_ptr == 0
+ switch (action) {
+ case 0:
+ suiveurs(perso);
+ break;
+ case 1:
+ habitants(perso);
+ break;
+ case 3:
+ evenements(perso);
+ break;
+ case 4:
+ followme(perso);
+ break;
+ case 5:
+ rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr);
+ break;
+ }
+ perso = _persons;
+ do {
+ if (perso->_roomNum == _globals->_roomNum && !(perso->_flags & PersonFlags::pf80)) {
+ switch (action) {
+ case 0:
+ suiveurs(perso);
+ break;
+ case 1:
+ habitants(perso);
+ break;
+ case 3:
+ evenements(perso);
+ break;
+ case 4:
+ followme(perso);
+ break;
+ case 5:
+ rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr);
+ break;
+ }
+ }
+ perso++;
+ } while (perso->_roomNum != 0xFFFF);
+}
+
+// Original name: setpersohere
+void EdenGame::setCharacterHere() {
+ debug("setCharacterHere, perso is %ld", _globals->_characterPtr - _persons);
+ _globals->_partyOutside = 0;
+ _globals->_party = 0;
+ _globals->_roomCharacterPtr = nullptr;
+ _globals->_roomCharacterType = 0;
+ _globals->_roomCharacterFlags = 0;
+ perso_ici(1);
+ perso_ici(0);
+ if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
+ if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor)
+ removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn);
+ if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor) {
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
+ removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
+ removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost);
+ }
+}
+
+void EdenGame::faire_suivre(int16 roomNum) {
+ _destinationRoom = roomNum;
+ perso_ici(4);
+}
+
+// Original name: suis_moi5
+void EdenGame::AddCharacterToParty() {
+ debug("adding person %ld to party", _globals->_characterPtr - _persons);
+ _globals->_characterPtr->_flags |= PersonFlags::pfInParty;
+ _globals->_characterPtr->_roomNum = _globals->_roomNum;
+ _globals->_party |= _globals->_characterPtr->_partyMask;
+ _globals->_drawFlags |= DrawFlags::drDrawTopScreen;
+}
+
+// Original name: suis_moi
+void EdenGame::addToParty(int16 index) {
+ perso_t *old_perso = _globals->_characterPtr;
+ _globals->_characterPtr = &_persons[index];
+ AddCharacterToParty();
+ _globals->_characterPtr = old_perso;
+}
+
+// Original name: reste_ici5
+void EdenGame::removeCharacterFromParty() {
+ debug("removing person %ld from party", _globals->_characterPtr - _persons);
+ _globals->_characterPtr->_flags &= ~PersonFlags::pfInParty;
+ _globals->_partyOutside |= _globals->_characterPtr->_partyMask;
+ _globals->_party &= ~_globals->_characterPtr->_partyMask;
+ _globals->_drawFlags |= DrawFlags::drDrawTopScreen;
+}
+
+// Original name: reste_ici
+void EdenGame::removeFromParty(int16 index) {
+ perso_t *old_perso = _globals->_characterPtr;
+ _globals->_characterPtr = &_persons[index];
+ removeCharacterFromParty();
+ _globals->_characterPtr = old_perso;
+}
+
+// Original name: eloipart
+void EdenGame::handleEloiDeparture() {
+ removeFromParty(PER_ELOI);
+ _globals->_gameFlags &= ~GameFlags::gfFlag4000;
+ _persons[PER_ELOI]._roomNum = 0;
+ _globals->_partyOutside &= ~_persons[PER_ELOI]._partyMask;
+ if (_globals->_roomNum == 2817)
+ setChrono(3000);
+ _globals->_eloiDepartureDay = _globals->_gameDays;
+ _globals->_eloiHaveNews = 0;
+ unlockInfo();
+}
+
+// Original name: eloirevientq
+bool EdenGame::checkEloiReturn() {
+ if (_globals->_phaseNum < 304)
+ return true;
+ if ((_globals->_phaseNum <= 353) || (_globals->_phaseNum == 370) || (_globals->_phaseNum == 384))
+ return false;
+ if (_globals->_areaNum != Areas::arShandovra)
+ return true;
+ if (_globals->_phaseNum < 480)
+ return false;
+ return true;
+}
+
+// Original name: eloirevient
+void EdenGame::handleEloiReturn() {
+ if (_globals->_areaPtr->_type == AreaType::atValley && !_persons[PER_ELOI]._roomNum)
+ _persons[PER_ELOI]._roomNum = (_globals->_roomNum & 0xFF00) + 1;
+}
+//// phase.c
+void EdenGame::incPhase() {
+ static phase_t phases[] = {
+ { 65, &EdenGame::dialautoon },
+ { 113, &EdenGame::phase113 },
+ { 129, &EdenGame::dialautoon },
+ { 130, &EdenGame::phase130 },
+ { 161, &EdenGame::phase161 },
+ { 211, &EdenGame::dialautoon },
+ { 226, &EdenGame::phase226 },
+ { 257, &EdenGame::phase257 },
+ { 353, &EdenGame::phase353 },
+ { 369, &EdenGame::phase369 },
+ { 371, &EdenGame::phase371 },
+ { 385, &EdenGame::phase385 },
+ { 386, &EdenGame::dialonfollow },
+ { 418, &EdenGame::phase418 },
+ { 433, &EdenGame::phase433 },
+ { 434, &EdenGame::phase434 },
+ { 449, &EdenGame::dialautoon },
+ { 497, &EdenGame::dialautoon },
+ { 513, &EdenGame::phase513 },
+ { 514, &EdenGame::phase514 },
+ { 529, &EdenGame::phase529 },
+ { 545, &EdenGame::phase545 },
+ { 561, &EdenGame::phase561 },
+ { -1, nullptr }
+ };
+
+ _globals->_phaseNum++;
+ debug("!!! next phase - %4X , room %4X", _globals->_phaseNum, _globals->_roomNum);
+ _globals->_phaseActionsCount = 0;
+ for (phase_t *phase = phases; phase->_id != -1; phase++) {
+ if (_globals->_phaseNum == phase->_id) {
+ (this->*phase->disp)();
+ break;
+ }
+ }
+}
+
+void EdenGame::phase113() {
+ removeFromParty(PER_DINA);
+ _persons[PER_DINA]._roomNum = 274;
+}
+
+void EdenGame::phase130() {
+ dialautoon();
+ removeFromParty(PER_MONK);
+}
+
+void EdenGame::phase161() {
+ Area *area = _globals->_areaPtr;
+ addToParty(PER_MAMMI);
+ _persons[PER_MAMMI]._flags |= PersonFlags::pf10;
+ area->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+}
+
+void EdenGame::phase226() {
+ newObject(16, 3);
+ newObject(16, 4);
+ newObject(16, 5);
+}
+
+void EdenGame::phase257() {
+ _gameIcons[127]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 58;
+ dialautooff();
+}
+
+void EdenGame::phase353() {
+ removeFromParty(PER_DINA);
+ _persons[PER_DINA]._roomNum = 0;
+ _tabletView[1] = 88;
+}
+
+void EdenGame::phase369() {
+ addToParty(PER_ELOI);
+ _globals->_narratorSequence = 2;
+ _gameRooms[334]._exits[0] = 134;
+ _gameRooms[335]._exits[0] = 134;
+}
+
+void EdenGame::phase371() {
+ handleEloiReturn();
+ _gameIcons[128]._cursorId &= ~0x8000;
+ _gameIcons[129]._cursorId &= ~0x8000;
+ _gameIcons[127]._cursorId |= 0x8000;
+ _globals->_characterBackgroundBankIdx = 59;
+ _gameRooms[334]._exits[0] = 0xFF;
+ _gameRooms[335]._exits[0] = 0xFF;
+ _gameIcons[123]._objectId = 9;
+ _gameIcons[124]._objectId = 26;
+ _gameIcons[125]._objectId = 42;
+ _gameIcons[126]._objectId = 56;
+}
+
+void EdenGame::phase385() {
+ dialautooff();
+ handleEloiReturn();
+ _globals->_nextInfoIdx = 0;
+ _globals->_lastInfoIdx = 0;
+ updateInfoList();
+ _globals->_lastInfo = 0;
+}
+
+void EdenGame::phase418() {
+ loseObject(Objects::obHorn);
+ dialautoon();
+ addToParty(PER_JABBER);
+}
+
+void EdenGame::phase433() {
+ dialautoon();
+ _persons[PER_MAMMI_4]._flags &= ~PersonFlags::pf80;
+ _persons[PER_JABBER]._flags &= ~PersonFlags::pf80;
+ setCharacterHere();
+ _globals->_chronoFlag = 0;
+ _globals->_chrono = 0;
+}
+
+void EdenGame::phase434() {
+ _globals->_roomNum = 275;
+ _gameRooms[16]._bank = 44;
+ _gameRooms[18]._bank = 44;
+ _gameIcons[132]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 61;
+ _gameRooms[118]._exits[2] = 0xFF;
+ abortDialogue();
+ _gameRooms[7]._bank = 322;
+ removeFromParty(PER_EVE);
+ removeFromParty(PER_MONK);
+ removeFromParty(PER_ELOI);
+ removeFromParty(PER_GUARDS);
+ removeFromParty(PER_JABBER);
+ _globals->_drawFlags |= DrawFlags::drDrawTopScreen;
+}
+
+void EdenGame::phase513() {
+ _globals->_lastDialogPtr = nullptr;
+ parlemoiNormalFlag = false;
+ dialautoon();
+}
+
+void EdenGame::phase514() {
+ _gameRooms[123]._exits[2] = 1;
+}
+
+void EdenGame::phase529() {
+ _gameIcons[133]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 63;
+}
+
+void EdenGame::phase545() {
+}
+
+void EdenGame::phase561() {
+ _globals->_narratorSequence = 10;
+}
+
+void EdenGame::bigphase1() {
+ static void (EdenGame::*bigphases[])() = {
+ &EdenGame::phase16,
+ &EdenGame::phase32,
+ &EdenGame::phase48,
+ &EdenGame::phase64,
+ &EdenGame::phase80,
+ &EdenGame::phase96,
+ &EdenGame::phase112,
+ &EdenGame::phase128,
+ &EdenGame::phase144,
+ &EdenGame::phase160,
+ &EdenGame::phase176,
+ &EdenGame::phase192,
+ &EdenGame::phase208,
+ &EdenGame::phase224,
+ &EdenGame::phase240,
+ &EdenGame::phase256,
+ &EdenGame::phase272,
+ &EdenGame::phase288,
+ &EdenGame::phase304,
+ &EdenGame::phase320,
+ &EdenGame::phase336,
+ &EdenGame::phase352,
+ &EdenGame::phase368,
+ &EdenGame::phase384,
+ &EdenGame::phase400,
+ &EdenGame::phase416,
+ &EdenGame::phase432,
+ &EdenGame::phase448,
+ &EdenGame::phase464,
+ &EdenGame::phase480,
+ &EdenGame::phase496,
+ &EdenGame::phase512,
+ &EdenGame::phase528,
+ &EdenGame::phase544,
+ &EdenGame::phase560
+ };
+
+ int16 phase = (_globals->_phaseNum & ~3) + 0x10; //TODO: check me
+ debug("!!! big phase - %4X", phase);
+ _globals->_phaseActionsCount = 0;
+ _globals->_phaseNum = phase;
+ if (phase > 560)
+ return;
+ phase >>= 4;
+ (this->*bigphases[phase - 1])();
+}
+
+void EdenGame::bigphase() {
+ if (!(_globals->_dialogPtr->_flags & DialogFlags::dfSpoken))
+ bigphase1();
+}
+
+void EdenGame::phase16() {
+ dialautoon();
+}
+
+void EdenGame::phase32() {
+ word_31E7A &= ~0x8000;
+}
+
+void EdenGame::phase48() {
+ _gameRooms[8]._exits[1] = 22;
+ dialautoon();
+}
+
+void EdenGame::phase64() {
+ addToParty(PER_DINA);
+ _persons[PER_ELOI]._roomNum = 259;
+}
+
+void EdenGame::phase80() {
+ _persons[PER_TAU]._roomNum = 0;
+}
+
+void EdenGame::phase96() {
+}
+
+void EdenGame::phase112() {
+ giveObject();
+}
+
+void EdenGame::phase128() {
+ addToParty(PER_DINA);
+ giveObject();
+}
+
+void EdenGame::phase144() {
+ addToParty(PER_ELOI);
+ _gameRooms[113]._video = 0;
+ _gameRooms[113]._bank = 317;
+}
+
+void EdenGame::phase160() {
+}
+
+void EdenGame::phase176() {
+ dialonfollow();
+}
+
+void EdenGame::phase192() {
+ Area *area = _globals->_areaPtr;
+ addToParty(PER_MAMMI_1);
+ _persons[PER_MAMMI_1]._flags |= PersonFlags::pf10;
+ dialautoon();
+ area->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+}
+
+void EdenGame::phase208() {
+ handleEloiReturn();
+}
+
+void EdenGame::phase224() {
+ _gameIcons[126]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 57;
+ dialautooff();
+}
+
+void EdenGame::phase240() {
+ Area *area = _globals->_areaPtr;
+ addToParty(PER_MAMMI_2);
+ _persons[PER_MAMMI_2]._flags |= PersonFlags::pf10;
+ area->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+}
+
+void EdenGame::phase256() {
+ dialautoon();
+}
+
+void EdenGame::phase272() {
+ dialautoon();
+ _globals->_eloiHaveNews = 0;
+}
+
+void EdenGame::phase288() {
+ setChoiceYes();
+ _persons[PER_MUNGO]._roomNum = 0;
+ removeFromParty(PER_MUNGO);
+ addToParty(PER_ELOI);
+ _globals->_narratorSequence = 8;
+}
+
+void EdenGame::phase304() {
+ Area *area = _globals->_areaPtr;
+ addToParty(PER_EVE);
+ addToParty(PER_MAMMI_5);
+ _persons[PER_MAMMI_5]._flags |= PersonFlags::pf10;
+ dialautoon();
+ area->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+}
+
+void EdenGame::phase320() {
+ dialonfollow();
+}
+
+void EdenGame::phase336() {
+ _gameRooms[288]._exits[0] = 135;
+ _gameRooms[289]._exits[0] = 135;
+ loseObject(_globals->_curObjectId);
+ dialautoon();
+}
+
+void EdenGame::phase352() {
+ _personRoomBankTable[30] = 26;
+ _persons[PER_EVE]._spriteBank = 9;
+ _persons[PER_EVE]._targetLoc = 8;
+ _followerList[13]._spriteNum = 2;
+ dialautoon();
+ _gameRooms[288]._exits[0] = 0xFF;
+ _gameRooms[289]._exits[0] = 0xFF;
+ _gameRooms[288]._flags &= ~RoomFlags::rf02;
+ _gameRooms[289]._flags &= ~RoomFlags::rf02;
+}
+
+void EdenGame::phase368() {
+ removeFromParty(PER_EVE);
+ dialautoon();
+ _persons[PER_ELOI]._roomNum = 1811;
+ _persons[PER_DINA]._roomNum = 1607;
+}
+
+void EdenGame::phase384() {
+ Area *area = _globals->_areaPtr;
+ addToParty(PER_EVE);
+ removeFromParty(PER_DINA);
+ dialautoon();
+ area->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+ handleEloiDeparture();
+}
+
+void EdenGame::phase400() {
+ dialonfollow();
+ _persons[PER_KING]._roomNum = 0;
+ _persons[PER_MONK]._roomNum = 259;
+ _globals->_eloiHaveNews = 0;
+ _objectLocations[20] = 259;
+}
+
+void EdenGame::phase416() {
+ addToParty(PER_MONK);
+ _gameIcons[130]._cursorId &= ~0x8000;
+ _globals->_characterBackgroundBankIdx = 60;
+ _gameRooms[0]._exits[0] = 138;
+}
+
+void EdenGame::phase432() {
+ _globals->_narratorSequence = 3;
+ _persons[PER_MAMMI_4]._flags |= PersonFlags::pf80;
+ _persons[PER_JABBER]._flags |= PersonFlags::pf80;
+ _persons[PER_ELOI]._roomNum = 257;
+ _gameRooms[0]._exits[0] = 0xFF;
+ _globals->_drawFlags |= DrawFlags::drDrawTopScreen;
+}
+
+void EdenGame::phase448() {
+ dialautoon();
+ handleEloiDeparture();
+}
+
+void EdenGame::phase464() {
+ _globals->_areaPtr->_flags |= AreaFlags::afFlag1;
+ _globals->_curAreaFlags |= AreaFlags::afFlag1;
+ _persons[PER_MAMMI_6]._flags |= PersonFlags::pf10;
+ addToParty(PER_SHAZIA);
+ _globals->_citadelAreaNum = _globals->_areaNum;
+ naitredino(8);
+}
+
+void EdenGame::phase480() {
+ giveObject();
+ newValley();
+ handleEloiReturn();
+ _tabletView[1] = 94;
+}
+
+void EdenGame::phase496() {
+ dialautoon();
+ _globals->_lastDialogPtr = nullptr;
+ parlemoiNormalFlag = false;
+}
+
+void EdenGame::phase512() {
+ removeFromParty(PER_MONK);
+ removeFromParty(PER_EVE);
+ removeFromParty(PER_SHAZIA);
+ removeFromParty(PER_GUARDS);
+}
+
+void EdenGame::phase528() {
+ _globals->_narratorSequence = 11;
+ addToParty(PER_MONK);
+ addToParty(PER_ELOI);
+ addToParty(PER_EVE);
+ addToParty(PER_SHAZIA);
+ addToParty(PER_GUARDS);
+}
+
+void EdenGame::phase544() {
+ handleEloiDeparture();
+ dialautoon();
+ removeFromParty(PER_SHAZIA);
+ removeFromParty(PER_GUARDS);
+}
+
+void EdenGame::phase560() {
+ _persons[PER_ELOI]._roomNum = 3073;
+ _gameRooms[127]._exits[1] = 0;
+}
+
+void EdenGame::saveGame(char *name) {
+ Common::OutSaveFile *fh = g_system->getSavefileManager()->openForSaving(name);
+ if (!fh)
+ return;
+
+ Common::Serializer s(nullptr, fh);
+
+ syncGame(s);
+
+ delete fh;
+}
+
+void EdenGame::syncGame(Common::Serializer s) {
+ syncGlobalPointers(s);
+ syncGlobalValues(s);
+
+ // _gameIcons
+ // CHECKME: only from #123 to #133?
+ for (int i = 123; i < 134; i++) {
+ s.syncAsSint16LE(_gameIcons[i].sx);
+ s.syncAsSint16LE(_gameIcons[i].sy);
+ s.syncAsSint16LE(_gameIcons[i].ex);
+ s.syncAsSint16LE(_gameIcons[i].ey);
+ s.syncAsUint16LE(_gameIcons[i]._cursorId);
+ s.syncAsUint16LE(_gameIcons[i]._actionId);
+ s.syncAsUint16LE(_gameIcons[i]._objectId);
+ }
+
+ syncCitadelRoomPointers(s);
+
+ // _areasTable
+ for (int i = 0; i < 12; i++) {
+ s.syncAsByte(_areasTable[i]._num);
+ s.syncAsByte(_areasTable[i]._type);
+ s.syncAsUint16LE(_areasTable[i]._flags);
+ s.syncAsUint16LE(_areasTable[i]._firstRoomIdx);
+ s.syncAsByte(_areasTable[i]._citadelLevel);
+ s.syncAsByte(_areasTable[i]._placeNum);
+ s.syncAsSint16LE(_areasTable[i]._visitCount);
+ }
+
+ // _gameRooms
+ for (int i = 0; i < 423; i++) {
+ s.syncAsByte(_gameRooms[i]._id);
+ for (int j = 0; j < 4; j++)
+ s.syncAsByte(_gameRooms[i]._exits[j]);
+ s.syncAsByte(_gameRooms[i]._flags);
+ s.syncAsUint16LE(_gameRooms[i]._bank);
+ s.syncAsUint16LE(_gameRooms[i]._party);
+ s.syncAsByte(_gameRooms[i]._level);
+ s.syncAsByte(_gameRooms[i]._video);
+ s.syncAsByte(_gameRooms[i]._location);
+ s.syncAsByte(_gameRooms[i]._backgroundBankNum);
+ }
+
+ // _Objects
+ for (int i = 0; i < 42; i++) {
+ s.syncAsByte(_objects[i]._id);
+ s.syncAsByte(_objects[i]._flags);
+ s.syncAsSint16LE(_objects[i]._locations);
+ s.syncAsUint16LE(_objects[i]._itemMask);
+ s.syncAsUint16LE(_objects[i]._powerMask);
+ s.syncAsSint16LE(_objects[i]._count);
+ }
+
+ for (int i = 0; i < 45; i++)
+ s.syncAsUint16LE(_objectLocations[i]);
+
+ // _followerList[13]
+ // CHECKME: Only #13?
+ s.syncAsByte(_followerList[13]._id);
+ s.syncAsByte(_followerList[13]._spriteNum);
+ s.syncAsSint16LE(_followerList[13].sx);
+ s.syncAsSint16LE(_followerList[13].sy);
+ s.syncAsSint16LE(_followerList[13].ex);
+ s.syncAsSint16LE(_followerList[13].ey);
+ s.syncAsSint16LE(_followerList[13]._spriteBank);
+ s.syncAsSint16LE(_followerList[13].ff_C);
+ s.syncAsSint16LE(_followerList[13].ff_E);
+
+ // _persons
+ for (int i = 0; i < 58; i++) {
+ s.syncAsUint16LE(_persons[i]._roomNum);
+ s.syncAsUint16LE(_persons[i]._actionId);
+ s.syncAsUint16LE(_persons[i]._partyMask);
+ s.syncAsByte(_persons[i]._id);
+ s.syncAsByte(_persons[i]._flags);
+ s.syncAsByte(_persons[i]._roomBankId);
+ s.syncAsByte(_persons[i]._spriteBank);
+ s.syncAsUint16LE(_persons[i]._items);
+ s.syncAsUint16LE(_persons[i]._powers);
+ s.syncAsByte(_persons[i]._targetLoc);
+ s.syncAsByte(_persons[i]._lastLoc);
+ s.syncAsByte(_persons[i]._speed);
+ s.syncAsByte(_persons[i]._steps);
+ }
+
+ syncTapePointers(s);
+
+ // _tapes
+ for (int i = 0; i < MAX_TAPES; i++) {
+ s.syncAsSint16LE(_tapes[i]._textNum);
+ s.syncAsSint16LE(_tapes[i]._party);
+ s.syncAsSint16LE(_tapes[i]._roomNum);
+ s.syncAsSint16LE(_tapes[i]._backgroundBankNum);
+ }
+
+ // _tabletView
+ // CHECKME: Only 6 out of 12?
+ for (int i = 0; i < 6; i++)
+ s.syncAsByte(_tabletView[i]);
+
+ // _gameDialogs
+ for (int i = 0; i < 10240; i++)
+ s.syncAsByte(_gameDialogs[i]);
+}
+
+void EdenGame::loadrestart() {
+ _quitFlag3 = true;
+/*
+ assert(0); //TODO: this won't work atm - all snapshots are BE
+ int32 offs = 0;
+ int32 size;
+ size = (char *)(&_globals->_saveEnd) - (char *)(_globals);
+ loadpartoffile(2495, _globals, offs, size);
+ offs += size;
+ vavaoffsetin();
+ size = (char *)(&_gameIcons[134]) - (char *)(&_gameIcons[123]);
+ loadpartoffile(2495, &_gameIcons[123], offs, size);
+ offs += size;
+ size = (char *)(&_areasTable[12]) - (char *)(&_areasTable[0]);
+ loadpartoffile(2495, &_areasTable[0], offs, size);
+ offs += size;
+ lieuoffsetin();
+ size = (char *)(&_gameRooms[423]) - (char *)(&_gameRooms[0]);
+ loadpartoffile(2495, &_gameRooms[0], offs, size);
+ offs += size;
+ size = (char *)(&_objects[42]) - (char *)(&_objects[0]);
+ loadpartoffile(2495, &_objects[0], offs, size);
+ offs += size;
+ size = (char *)(&_objectLocations[45]) - (char *)(&_objectLocations[0]);
+ loadpartoffile(2495, &_objectLocations[0], offs, size);
+ offs += size;
+ size = (char *)(&_followerList[14]) - (char *)(&_followerList[13]);
+ loadpartoffile(2495, &_followerList[13], offs, size);
+ offs += size;
+ size = (char *)(&_persons[PER_UNKN_3DE]) - (char *)(&_persons[PER_KING]);
+ loadpartoffile(2495, &_persons[PER_KING], offs, size);
+ offs += size;
+ size = (char *)(&_tapes[16]) - (char *)(&_tapes[0]);
+ loadpartoffile(2495, &_tapes[0], offs, size);
+ offs += size;
+ bandeoffsetin();
+ size = (char *)(&_tabletView[6]) - (char *)(&_tabletView[0]);
+ loadpartoffile(2495, &_tabletView[0], offs, size);
+ offs += size;
+ size = (char *)(&_gameDialogs[10240]) - (char *)(&_gameDialogs[0]); //TODO: const size 10240
+ loadpartoffile(2495, &_gameDialogs[0], offs, size);
+ _gameLoaded = true;
+ */
+}
+
+void EdenGame::loadgame(char *name) {
+ Common::InSaveFile *fh = g_system->getSavefileManager()->openForLoading(name);
+ if (!fh)
+ return;
+
+ Common::Serializer s(fh, nullptr);
+ syncGame(s);
+
+ delete fh;
+ _gameLoaded = true;
+}
+
+#define NULLPTR 0xFFFFFF
+#define IDXOUT(val, base, typ, idx) if (val) (idx) = ((byte*)val - (byte*)base) / sizeof(typ); else (idx) = NULLPTR;
+#define OFSIN(val, base, typ) if ((void*)(val) != NULLPTR) (val) = (typ*)((char*)(val) + (size_t)(base)); else (val) = 0;
+
+void EdenGame::syncGlobalPointers(Common::Serializer s) {
+ uint32 dialogIdx, nextDialogIdx, narratorDialogIdx, lastDialogIdx, tapeIdx, nextRoomIconIdx, roomIdx;
+ uint32 citaAreaFirstRoomIdx, areaIdx, lastAreaIdx, curAreaIdx, characterIdx, roomCharacterIdx;
+
+ if (s.isSaving()) {
+ IDXOUT(_globals->_dialogPtr, _gameDialogs, Dialog, dialogIdx);
+ IDXOUT(_globals->_nextDialogPtr, _gameDialogs, Dialog, nextDialogIdx);
+ IDXOUT(_globals->_narratorDialogPtr, _gameDialogs, Dialog, narratorDialogIdx);
+ IDXOUT(_globals->_lastDialogPtr, _gameDialogs, Dialog, lastDialogIdx);
+ IDXOUT(_globals->_tapePtr, _tapes, tape_t, tapeIdx);
+ IDXOUT(_globals->_nextRoomIcon, _gameIcons, Icon, nextRoomIconIdx);
+ IDXOUT(_globals->_roomPtr, _gameRooms, Room, roomIdx);
+ IDXOUT(_globals->_citaAreaFirstRoom, _gameRooms, Room, citaAreaFirstRoomIdx);
+ IDXOUT(_globals->_areaPtr, _areasTable, Area, areaIdx);
+ IDXOUT(_globals->_lastAreaPtr, _areasTable, Area, lastAreaIdx);
+ IDXOUT(_globals->_curAreaPtr, _areasTable, Area, curAreaIdx);
+ IDXOUT(_globals->_characterPtr, _persons, perso_t, characterIdx);
+ IDXOUT(_globals->_roomCharacterPtr, _persons, perso_t, roomCharacterIdx);
+ }
+
+ s.syncAsUint32LE(dialogIdx);
+ s.syncAsUint32LE(nextDialogIdx);
+ s.syncAsUint32LE(narratorDialogIdx);
+ s.syncAsUint32LE(lastDialogIdx);
+ s.syncAsUint32LE(tapeIdx);
+ s.syncAsUint32LE(nextRoomIconIdx);
+ s.syncAsUint32LE(roomIdx);
+ s.syncAsUint32LE(citaAreaFirstRoomIdx);
+ s.syncAsUint32LE(areaIdx);
+ s.syncAsUint32LE(lastAreaIdx);
+ s.syncAsUint32LE(curAreaIdx);
+ s.syncAsUint32LE(characterIdx);
+ s.syncAsUint32LE(roomCharacterIdx);
+
+ if (s.isLoading()) {
+ _globals->_dialogPtr = (dialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, dialogIdx);
+ _globals->_nextDialogPtr = (nextDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, nextDialogIdx);
+ _globals->_narratorDialogPtr = (narratorDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, narratorDialogIdx);
+ _globals->_lastDialogPtr = (lastDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, lastDialogIdx);
+ _globals->_tapePtr = (tapeIdx == NULLPTR) ? nullptr : &_tapes[tapeIdx];
+ _globals->_nextRoomIcon = (nextRoomIconIdx == NULLPTR) ? nullptr : &_gameIcons[nextRoomIconIdx];
+ _globals->_roomPtr = (roomIdx == NULLPTR) ? nullptr : &_gameRooms[roomIdx];
+ _globals->_citaAreaFirstRoom = (citaAreaFirstRoomIdx == NULLPTR) ? nullptr : &_gameRooms[citaAreaFirstRoomIdx];
+ _globals->_areaPtr = (areaIdx == NULLPTR) ? nullptr : &_areasTable[areaIdx];
+ _globals->_lastAreaPtr = (lastAreaIdx == NULLPTR) ? nullptr : &_areasTable[lastAreaIdx];
+ _globals->_curAreaPtr = (curAreaIdx == NULLPTR) ? nullptr : &_areasTable[curAreaIdx];
+ _globals->_characterPtr = (characterIdx == NULLPTR) ? nullptr : &_persons[characterIdx];
+ _globals->_roomCharacterPtr = (roomCharacterIdx == NULLPTR) ? nullptr : &_persons[roomCharacterIdx];
+ }
+}
+
+void EdenGame::syncGlobalValues(Common::Serializer s) {
+ s.syncAsByte(_globals->_areaNum);
+ s.syncAsByte(_globals->_areaVisitCount);
+ s.syncAsByte(_globals->_menuItemIdLo);
+ s.syncAsByte(_globals->_menuItemIdHi);
+ s.syncAsUint16LE(_globals->_randomNumber);
+ s.syncAsUint16LE(_globals->_gameTime);
+ s.syncAsUint16LE(_globals->_gameDays);
+ s.syncAsUint16LE(_globals->_chrono);
+ s.syncAsUint16LE(_globals->_eloiDepartureDay);
+ s.syncAsUint16LE(_globals->_roomNum);
+ s.syncAsUint16LE(_globals->_newRoomNum);
+ s.syncAsUint16LE(_globals->_phaseNum);
+ s.syncAsUint16LE(_globals->_metPersonsMask1);
+ s.syncAsUint16LE(_globals->_party);
+ s.syncAsUint16LE(_globals->_partyOutside);
+ s.syncAsUint16LE(_globals->_metPersonsMask2);
+ s.syncAsUint16LE(_globals->_var1C);
+ s.syncAsUint16LE(_globals->_phaseActionsCount);
+ s.syncAsUint16LE(_globals->_curAreaFlags);
+ s.syncAsUint16LE(_globals->_curItemsMask);
+ s.syncAsUint16LE(_globals->_curPowersMask);
+ s.syncAsUint16LE(_globals->_curPersoItems);
+ s.syncAsUint16LE(_globals->_curCharacterPowers);
+ s.syncAsUint16LE(_globals->_wonItemsMask);
+ s.syncAsUint16LE(_globals->_wonPowersMask);
+ s.syncAsUint16LE(_globals->_stepsToFindAppleFast);
+ s.syncAsUint16LE(_globals->_stepsToFindAppleNormal);
+ s.syncAsUint16LE(_globals->_roomPersoItems);
+ s.syncAsUint16LE(_globals->_roomCharacterPowers);
+ s.syncAsUint16LE(_globals->_gameFlags);
+ s.syncAsUint16LE(_globals->_curVideoNum);
+ s.syncAsUint16LE(_globals->_morkusSpyVideoNum1);
+ s.syncAsUint16LE(_globals->_morkusSpyVideoNum2);
+ s.syncAsUint16LE(_globals->_morkusSpyVideoNum3);
+ s.syncAsUint16LE(_globals->_morkusSpyVideoNum4);
+ s.syncAsByte(_globals->_newMusicType);
+ s.syncAsByte(_globals->_var43);
+ s.syncAsByte(_globals->_videoSubtitleIndex);
+ s.syncAsByte(_globals->_partyInstruments);
+ s.syncAsByte(_globals->_monkGotRing);
+ s.syncAsByte(_globals->_chronoFlag);
+ s.syncAsByte(_globals->_curRoomFlags);
+ s.syncAsByte(_globals->_endGameFlag);
+ s.syncAsByte(_globals->_lastInfo);
+
+ byte autoDialog;
+ if (s.isSaving())
+ autoDialog = _globals->_autoDialog ? 1 : 0;
+ s.syncAsByte(autoDialog);
+ if (s.isLoading())
+ _globals->_autoDialog = (autoDialog == 1);
+
+ s.syncAsByte(_globals->_worldTyranSighted);
+ s.syncAsByte(_globals->_var4D);
+ s.syncAsByte(_globals->_var4E);
+ s.syncAsByte(_globals->_worldGaveGold);
+ s.syncAsByte(_globals->_worldHasTriceraptors);
+ s.syncAsByte(_globals->_worldHasVelociraptors);
+ s.syncAsByte(_globals->_worldHasTyran);
+ s.syncAsByte(_globals->_var53);
+ s.syncAsByte(_globals->_var54);
+ s.syncAsByte(_globals->_var55);
+ s.syncAsByte(_globals->_gameHours);
+ s.syncAsByte(_globals->_textToken1);
+ s.syncAsByte(_globals->_textToken2);
+ s.syncAsByte(_globals->_eloiHaveNews);
+ s.syncAsByte(_globals->_dialogFlags);
+ s.syncAsByte(_globals->_curAreaType);
+ s.syncAsByte(_globals->_curCitadelLevel);
+ s.syncAsByte(_globals->_newLocation);
+ s.syncAsByte(_globals->_prevLocation);
+ s.syncAsByte(_globals->_curPersoFlags);
+ s.syncAsByte(_globals->_var60);
+ s.syncAsByte(_globals->_eventType);
+ s.syncAsByte(_globals->_var62);
+ s.syncAsByte(_globals->_curObjectId);
+ s.syncAsByte(_globals->_curObjectFlags);
+ s.syncAsByte(_globals->_var65);
+ s.syncAsByte(_globals->_roomCharacterType);
+ s.syncAsByte(_globals->_roomCharacterFlags);
+ s.syncAsByte(_globals->_narratorSequence);
+ s.syncAsByte(_globals->_var69);
+ s.syncAsByte(_globals->_var6A);
+ s.syncAsByte(_globals->_frescoNumber);
+ s.syncAsByte(_globals->_var6C);
+ s.syncAsByte(_globals->_var6D);
+ s.syncAsByte(_globals->_labyrinthDirections);
+ s.syncAsByte(_globals->_labyrinthRoom);
+
+/*
+ CHECKME: *_sentenceBufferPtr
+*/
+
+ s.syncAsByte(_globals->_lastInfoIdx);
+ s.syncAsByte(_globals->_nextInfoIdx);
+
+/*
+ CHECKME
+ * _persoSpritePtr
+ * _persoSpritePtr2
+ * _curCharacterAnimPtr
+ * _varC2
+*/
+
+ s.syncAsSint16LE(_globals->_iconsIndex);
+ s.syncAsSint16LE(_globals->_curObjectCursor);
+ s.syncAsSint16LE(_globals->_varCA);
+ s.syncAsSint16LE(_globals->_varCC);
+ s.syncAsSint16LE(_globals->_characterImageBank);
+ s.syncAsUint16LE(_globals->_roomImgBank);
+ s.syncAsUint16LE(_globals->_characterBackgroundBankIdx);
+ s.syncAsUint16LE(_globals->_varD4);
+ s.syncAsUint16LE(_globals->_frescoeWidth);
+ s.syncAsUint16LE(_globals->_frescoeImgBank);
+ s.syncAsUint16LE(_globals->_varDA);
+ s.syncAsUint16LE(_globals->_varDC);
+ s.syncAsUint16LE(_globals->_roomBaseX);
+ s.syncAsUint16LE(_globals->_varE0);
+ s.syncAsUint16LE(_globals->_dialogType);
+ s.syncAsUint16LE(_globals->_varE4);
+ s.syncAsUint16LE(_globals->_currMusicNum);
+ s.syncAsSint16LE(_globals->_textNum);
+ s.syncAsUint16LE(_globals->_travelTime);
+ s.syncAsUint16LE(_globals->_varEC);
+ s.syncAsByte(_globals->_displayFlags);
+ s.syncAsByte(_globals->_oldDisplayFlags);
+ s.syncAsByte(_globals->_drawFlags);
+ s.syncAsByte(_globals->_varF1);
+ s.syncAsByte(_globals->_varF2);
+ s.syncAsByte(_globals->_menuFlags);
+ s.syncAsByte(_globals->_varF4);
+ s.syncAsByte(_globals->_varF5);
+ s.syncAsByte(_globals->_varF6);
+ s.syncAsByte(_globals->_varF7);
+ s.syncAsByte(_globals->_varF8);
+ s.syncAsByte(_globals->_varF9);
+ s.syncAsByte(_globals->_varFA);
+ s.syncAsByte(_globals->_animationFlags);
+ s.syncAsByte(_globals->_giveObj1);
+ s.syncAsByte(_globals->_giveObj2);
+ s.syncAsByte(_globals->_giveObj3);
+ s.syncAsByte(_globals->_var100);
+ s.syncAsByte(_globals->_roomVidNum);
+ s.syncAsByte(_globals->_mirrorEffect);
+ s.syncAsByte(_globals->_var103);
+ s.syncAsByte(_globals->_roomBackgroundBankNum);
+ s.syncAsByte(_globals->_valleyVidNum);
+ s.syncAsByte(_globals->_updatePaletteFlag);
+ s.syncAsByte(_globals->_inventoryScrollPos);
+ s.syncAsByte(_globals->_objCount);
+ s.syncAsByte(_globals->_textBankIndex);
+ s.syncAsByte(_globals->_prefLanguage);
+ for (int i = 0; i < 2; i++) {
+ s.syncAsByte(_globals->_prefMusicVol[i]);
+ s.syncAsByte(_globals->_prefVoiceVol[i]);
+ s.syncAsByte(_globals->_prefSoundVolume[i]);
+ }
+ s.syncAsByte(_globals->_citadelAreaNum);
+ s.syncAsByte(_globals->_var113);
+ s.syncAsByte(_globals->_lastPlaceNum);
+ s.syncAsByte(_globals->_saveEnd);
+}
+
+void EdenGame::syncCitadelRoomPointers(Common::Serializer s) {
+ uint32 citadelRoomIdx;
+ for (int i = 0; i < 12; i++) {
+ if (s.isSaving())
+ IDXOUT(_areasTable[i]._citadelRoomPtr, _gameRooms, Room, citadelRoomIdx);
+ s.syncAsUint32LE(citadelRoomIdx);
+ if (s.isLoading())
+ _areasTable[i]._citadelRoomPtr = (citadelRoomIdx == NULLPTR) ? nullptr : &_gameRooms[citadelRoomIdx];
+ }
+}
+
+void EdenGame::syncTapePointers(Common::Serializer s) {
+ int persoIdx, dialogIdx;
+
+ for (int i = 0; i < 16; i++) {
+ if (s.isSaving()) {
+ IDXOUT(_tapes[i]._perso, _persons, perso_t, persoIdx);
+ IDXOUT(_tapes[i]._dialog, _gameDialogs, Dialog, dialogIdx);
+ }
+
+ s.syncAsUint32LE(persoIdx);
+ s.syncAsUint32LE(dialogIdx);
+
+ if (s.isLoading()) {
+ _tapes[i]._perso = (persoIdx == NULLPTR) ? nullptr : &_persons[persoIdx];
+ _tapes[i]._dialog = (dialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, dialogIdx);
+ }
+ }
+}
+
+char EdenGame::testCondition(int16 index) {
+ bool endFl = false;
+ uint16 stack[32];
+ uint16 *sp = stack;
+ assert(index > 0);
+ _codePtr = (byte *)getElem(_gameConditions, (index - 1));
+ uint16 value;
+ do {
+ value = fetchValue();
+ for (;;) {
+ byte op = *_codePtr++;
+ if (op == 0xFF) {
+ endFl = true;
+ break;
+ }
+ if ((op & 0x80) == 0) {
+ uint16 value2 = fetchValue();
+ value = operation(op, value, value2);
+ } else {
+ assert(sp < stack + 32);
+ *sp++ = value;
+ *sp++ = op;
+ break;
+ }
+ }
+ } while (!endFl);
+
+ if (sp != stack) {
+ *sp++ = value;
+ uint16 *sp2 = stack;
+ value = *sp2++;
+ do {
+ byte op = *sp2++;
+ uint16 value2 = *sp2++;
+ value = operation(op, value, value2);
+ } while (sp2 != sp);
+ }
+// if (value)
+ debug("cond %d(-1) returns %s", index, value ? "TRUE" : "false");
+// if (index == 402) debug("(glob_61.b == %X) & (glob_12.w == %X) & (glob_4C.b == %X) & (glob_4E.b == %X)", p_global->eventType, p_global->phaseNum, p_global->worldTyrannSighted, p_global->ff_4E);
+ return value != 0;
+}
+
+// Original name: opera_add
+uint16 EdenGame::operAdd(uint16 v1, uint16 v2) {
+ return v1 + v2;
+}
+
+// Original name: opera_sub
+uint16 EdenGame::operSub(uint16 v1, uint16 v2) {
+ return v1 - v2;
+}
+
+// Original name: opera_and
+uint16 EdenGame::operLogicalAnd(uint16 v1, uint16 v2) {
+ return v1 & v2;
+}
+
+// Original name: opera_or
+uint16 EdenGame::operLogicalOr(uint16 v1, uint16 v2) {
+ return v1 | v2;
+}
+
+// Original name: opera_egal
+uint16 EdenGame::operIsEqual(uint16 v1, uint16 v2) {
+ return v1 == v2 ? -1 : 0;
+}
+
+// Original name: opera_petit
+uint16 EdenGame::operIsSmaller(uint16 v1, uint16 v2) {
+ return v1 < v2 ? -1 : 0; //TODO: all comparisons are unsigned!
+}
+
+// Original name: opera_grand
+uint16 EdenGame::operIsGreater(uint16 v1, uint16 v2) {
+ return v1 > v2 ? -1 : 0;
+}
+
+// Original name: opera_diff
+uint16 EdenGame::operIsDifferent(uint16 v1, uint16 v2) {
+ return v1 != v2 ? -1 : 0;
+}
+
+// Original name: opera_petega
+uint16 EdenGame::operIsSmallerOrEqual(uint16 v1, uint16 v2) {
+ return v1 <= v2 ? -1 : 0;
+}
+
+// Original name: opera_graega
+uint16 EdenGame::operIsGreaterOrEqual(uint16 v1, uint16 v2) {
+ return v1 >= v2 ? -1 : 0;
+}
+
+// Original name: opera_faux
+uint16 EdenGame::operFalse(uint16 v1, uint16 v2) {
+ return 0;
+}
+
+uint16 EdenGame::operation(byte op, uint16 v1, uint16 v2) {
+ static uint16(EdenGame::*operations[16])(uint16, uint16) = {
+ &EdenGame::operIsEqual,
+ &EdenGame::operIsSmaller,
+ &EdenGame::operIsGreater,
+ &EdenGame::operIsDifferent,
+ &EdenGame::operIsSmallerOrEqual,
+ &EdenGame::operIsGreaterOrEqual,
+ &EdenGame::operAdd,
+ &EdenGame::operSub,
+ &EdenGame::operLogicalAnd,
+ &EdenGame::operLogicalOr,
+ &EdenGame::operFalse,
+ &EdenGame::operFalse,
+ &EdenGame::operFalse,
+ &EdenGame::operFalse,
+ &EdenGame::operFalse,
+ &EdenGame::operFalse
+ };
+ return (this->*operations[(op & 0x1F) >> 1])(v1, v2);
+}
+
+#define VAR(ofs, var) case ofs: return _globals->var;
+
+uint8 EdenGame::getByteVar(uint16 offset) {
+ switch (offset) {
+ VAR(0, _areaNum);
+ VAR(1, _areaVisitCount);
+ VAR(2, _menuItemIdLo);
+ VAR(3, _menuItemIdHi); //TODO: pad?
+ VAR(0x42, _newMusicType);
+ VAR(0x43, _var43);
+ VAR(0x44, _videoSubtitleIndex);
+ VAR(0x45, _partyInstruments); // &1 - Bell for Monk, &2 - Drum for Thugg
+ VAR(0x46, _monkGotRing);
+ VAR(0x47, _chronoFlag);
+ VAR(0x48, _curRoomFlags);
+ VAR(0x49, _endGameFlag);
+ VAR(0x4A, _lastInfo);
+ VAR(0x4B, _autoDialog);
+ VAR(0x4C, _worldTyranSighted);
+ VAR(0x4D, _var4D);
+ VAR(0x4E, _var4E);
+ VAR(0x4F, _worldGaveGold);
+ VAR(0x50, _worldHasTriceraptors);
+ VAR(0x51, _worldHasVelociraptors);
+ VAR(0x52, _worldHasTyran);
+ VAR(0x53, _var53);
+ VAR(0x54, _var54); //CHEKME: Used?
+ VAR(0x55, _var55); //TODO: pad?
+ VAR(0x56, _gameHours);
+ VAR(0x57, _textToken1);
+ VAR(0x58, _textToken2); //TODO: pad?
+ VAR(0x59, _eloiHaveNews);
+ VAR(0x5A, _dialogFlags);
+ VAR(0x5B, _curAreaType);
+ VAR(0x5C, _curCitadelLevel);
+ VAR(0x5D, _newLocation);
+ VAR(0x5E, _prevLocation);
+ VAR(0x5F, _curPersoFlags);
+ VAR(0x60, _var60);
+ VAR(0x61, _eventType);
+ VAR(0x62, _var62); //TODO: pad?
+ VAR(0x63, _curObjectId);
+ VAR(0x64, _curObjectFlags);
+ VAR(0x65, _var65); //TODO: pad?
+ VAR(0x66, _roomCharacterType);
+ VAR(0x67, _roomCharacterFlags);
+ VAR(0x68, _narratorSequence);
+ VAR(0x69, _var69);
+ VAR(0x6A, _var6A);
+ VAR(0x6B, _frescoNumber);
+ VAR(0x6C, _var6C); //TODO: pad?
+ VAR(0x6D, _var6D); //TODO: pad?
+ VAR(0x6E, _labyrinthDirections);
+ VAR(0x6F, _labyrinthRoom);
+ default:
+ error("Undefined byte variable access (0x%X)", offset);
+ }
+ return 0;
+}
+
+uint16 EdenGame::getWordVar(uint16 offset) {
+ switch (offset) {
+ VAR(4, _randomNumber); //TODO: this is randomized in pc ver and used by some conds. always zero on mac
+ VAR(6, _gameTime);
+ VAR(8, _gameDays);
+ VAR(0xA, _chrono);
+ VAR(0xC, _eloiDepartureDay);
+ VAR(0xE, _roomNum); // current room number
+ VAR(0x10, _newRoomNum); // target room number selected on world map
+ VAR(0x12, _phaseNum);
+ VAR(0x14, _metPersonsMask1);
+ VAR(0x16, _party);
+ VAR(0x18, _partyOutside);
+ VAR(0x1A, _metPersonsMask2);
+ VAR(0x1C, _var1C); //TODO: write-only?
+ VAR(0x1E, _phaseActionsCount);
+ VAR(0x20, _curAreaFlags);
+ VAR(0x22, _curItemsMask);
+ VAR(0x24, _curPowersMask);
+ VAR(0x26, _curPersoItems);
+ VAR(0x28, _curCharacterPowers);
+ VAR(0x2A, _wonItemsMask);
+ VAR(0x2C, _wonPowersMask);
+ VAR(0x2E, _stepsToFindAppleFast);
+ VAR(0x30, _stepsToFindAppleNormal);
+ VAR(0x32, _roomPersoItems); //TODO: write-only?
+ VAR(0x34, _roomCharacterPowers); //TODO: write-only?
+ VAR(0x36, _gameFlags);
+ VAR(0x38, _curVideoNum);
+ VAR(0x3A, _morkusSpyVideoNum1); //TODO: pad?
+ VAR(0x3C, _morkusSpyVideoNum2); //TODO: pad?
+ VAR(0x3E, _morkusSpyVideoNum3); //TODO: pad?
+ VAR(0x40, _morkusSpyVideoNum4); //TODO: pad?
+ default:
+ error("Undefined word variable access (0x%X)", offset);
+ }
+ return 0;
+}
+
+#undef VAR
+
+// Original name: cher_valeur
+uint16 EdenGame::fetchValue() {
+ uint16 val;
+ byte typ = *_codePtr++;
+ if (typ < 0x80) {
+ byte ofs = *_codePtr++;
+ val = (typ == 1) ? getByteVar(ofs) : getWordVar(ofs);
+ } else if (typ == 0x80)
+ val = *_codePtr++;
+ else {
+ val = READ_LE_UINT16(_codePtr);
+ _codePtr += 2;
+ }
+ return val;
+}
+
+// Original name: ret
+void EdenGame::actionNop() {
+}
+
+//// cube.c
+// Original name: make_tabcos
+void EdenGame::initSinCosTable() {
+ for (int i = 0; i < 361; i++) {
+ _cosTable[i] = (int)(cos(3.1416 * i / 180.0) * 255.0);
+ _sinTable[i] = (int)(sin(3.1416 * i / 180.0) * 255.0);
+ }
+}
+
+void EdenGame::makeMatriceFix() {
+ int16 rotAngleTheta = _rotationAngleX;
+ int16 rotAnglePhi = _rotationAngleY;
+ int16 rotAnglePsi = _rotationAngleZ;
+
+ _passMat31 = (_cosTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8;
+ _passMat32 = (_sinTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8;
+ _passMat33 = -_sinTable[rotAngleTheta];
+ _passMat21 = ((-_sinTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8)
+ + ((_sinTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
+ _passMat22 = ((_cosTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8)
+ + ((_sinTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
+ _passMat23 = (_cosTable[rotAngleTheta] * _sinTable[rotAnglePsi]) >> 8;
+ _passMat11 = ((_sinTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8)
+ + ((_cosTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
+ _passMat12 = ((-_cosTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8)
+ + ((_cosTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
+ _passMat13 = (_cosTable[rotAngleTheta] * _cosTable[rotAnglePsi]) >> 8;
+}
+
+void EdenGame::projectionFix(Cube *cubep, int n) {
+ for (int i = 0; i < n; i++) {
+ int x = cubep->_vertices[i].x;
+ int y = cubep->_vertices[i].y;
+ int z = cubep->_vertices[i].z;
+
+ int transformX = _passMat31 * x + _passMat21 * y + _passMat11 * z + (int)(_translationX * 256.0f);
+ int transformY = _passMat32 * x + _passMat22 * y + _passMat12 * z + (int)(_translationY * 256.0f);
+ int transformZ = _passMat33 * x + _passMat23 * y + _passMat13 * z + (int)(_translationZ * 256.0f);
+
+ transformZ >>= 8;
+ if (transformZ == -256)
+ transformZ++;
+ cubep->_projection[i].x = transformX / (transformZ + 256) + _cursorPosX + 14 + _scrollPos;
+ cubep->_projection[i].y = transformY / (transformZ + 256) + _cursorPosY + 14;
+ cubep->_projection[i].z = transformZ;
+ }
+}
+
+// Original name init_cube
+void EdenGame::initCubeMac() {
+ loadMap(2493, _cubeTexture);
+ NEWcharge_objet_mob(&_cube, 2494, _cubeTexture);
+ initSinCosTable();
+}
+
+void EdenGame::engineMac() {
+ Eden_dep_and_rot();
+ makeMatriceFix();
+ projectionFix(&_cube, _cubeFaces);
+ displayObject(&_cube);
+}
+
+// Original name: affiche_objet
+void EdenGame::displayObject(Cube *cubep) {
+ for (int i = 0; i < cubep->_num; i++)
+ displayPolygoneMapping(cubep, cubep->_faces[i]);
+}
+
+// Original name: NEWcharge_map
+void EdenGame::loadMap(int file_id, byte *buffer) {
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ loadpartoffile(file_id, buffer, 32, 256 * 3);
+
+ for (int i = 0; i < 256; i++) {
+ color3_t color;
+ color.r = buffer[i * 3] << 8;
+ color.g = buffer[i * 3 + 1] << 8;
+ color.b = buffer[i * 3 + 2] << 8;
+ CLPalette_SetRGBColor(_globalPalette, i, &color);
+ }
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+
+ loadpartoffile(file_id, buffer, 32 + 256 * 3, 0x4000);
+ } else {
+#if 0
+// Fake Mac cursor on PC
+ Common::File f;
+ if (f.open("curs.raw")) {
+ f.seek(32);
+ f.read(buffer, 256 * 3);
+
+ for (i = 0; i < 256; i++) {
+ color3_t color;
+ color.r = buffer[i * 3] << 8;
+ color.g = buffer[i * 3 + 1] << 8;
+ color.b = buffer[i * 3 + 2] << 8;
+ CLPalette_SetRGBColor(global_palette, i, &color);
+ }
+ CLPalette_Send2Screen(global_palette, 0, 256);
+
+ f.read(buffer, 0x4000);
+
+ f.close();
+ }
+ else
+ error("can not load cursor texture");
+#endif
+ }
+}
+
+void EdenGame::NEWcharge_objet_mob(Cube *cubep, int fileNum, byte *texturePtr) {
+ char *tmp1 = (char *)malloc(454);
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ loadpartoffile(fileNum, tmp1, 0, 454);
+ else {
+#if 0
+// Fake Mac cursor on PC
+ Common::File f;
+ if (f.open("curseden.mob")) {
+ f.read(tmp1, 454);
+ f.close();
+ }
+ else
+ ::error("can not load cursor model");
+#endif
+ }
+
+ char *next = tmp1;
+ char error;
+ _cubeFaces = nextVal(&next, &error);
+ Point3D *vertices = (Point3D *)malloc(_cubeFaces * sizeof(*vertices));
+ Point3D *projection = (Point3D *)malloc(_cubeFaces * sizeof(*projection));
+ for (int i = 0; i < _cubeFaces; i++) {
+ vertices[i].x = nextVal(&next, &error);
+ vertices[i].y = nextVal(&next, &error);
+ vertices[i].z = nextVal(&next, &error);
+ }
+ int count2 = nextVal(&next, &error);
+ CubeFace **tmp4 = (CubeFace **)malloc(count2 * sizeof(*tmp4));
+ for (int i = 0; i < count2; i++) {
+ tmp4[i] = (CubeFace *)malloc(sizeof(CubeFace));
+ tmp4[i]->tri = 3;
+ char textured = nextVal(&next, &error);
+ tmp4[i]->ff_5 = nextVal(&next, &error);
+ tmp4[i]->_indices = (uint16 *)malloc(3 * sizeof(*tmp4[i]->_indices));
+ tmp4[i]->_uv = (int16 *)malloc(3 * 2 * sizeof(*tmp4[i]->_uv));
+ for (int j = 0; j < 3; j++) {
+ tmp4[i]->_indices[j] = nextVal(&next, &error);
+ if (textured) {
+ tmp4[i]->_uv[j * 2] = nextVal(&next, &error);
+ tmp4[i]->_uv[j * 2 + 1] = nextVal(&next, &error);
+ }
+ }
+ if (textured) {
+ tmp4[i]->ff_4 = 3;
+ tmp4[i]->_texturePtr = texturePtr;
+ } else
+ tmp4[i]->ff_4 = 0;
+ }
+ free(tmp1);
+ cubep->_num = count2;
+ cubep->_faces = tmp4;
+ cubep->_projection = projection;
+ cubep->_vertices = vertices;
+}
+
+int EdenGame::nextVal(char **ptr, char *error) {
+ char c = 0;
+ char *p = *ptr;
+ int val = strtol(p, 0, 10);
+ while ((*p >= '0' && *p <= '9' && *p != 0) || *p == '-')
+ p++;
+ while ((*p == 13 || *p == 10 || *p == ',' || *p == ' ') && *p)
+ c = *p++;
+ *error = c == 10;
+ *ptr = p;
+ return val;
+}
+
+void EdenGame::selectMap(int16 num) {
+ _cursCurPCMap = num;
+ int16 k = 0;
+ int mode = _mapMode[num];
+ int16 x = (num & 7) * 32;
+ int16 y = (num & 0x18) * 4;
+ for (int i = 0; i < 6 * 2; i++) {
+ for (int j = 0; j < 3; j++) {
+ _cube._faces[i]->_uv[j * 2 ] = x + _cubeTextureCoords[mode][k++];
+ _cube._faces[i]->_uv[j * 2 + 1] = y + _cubeTextureCoords[mode][k++];
+ }
+ }
+}
+
+void EdenGame::Eden_dep_and_rot() {
+ int16 curs = _currCursor;
+ if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20))
+ curs = 10;
+ selectMap(curs);
+ _cursorNewTick = g_system->getMillis();
+ if (_cursorNewTick - _cursorOldTick < 1)
+ return;
+
+ _cursorOldTick = _cursorNewTick;
+ switch (_currCursor) {
+ case 0:
+ _rotationAngleZ = (_rotationAngleZ + 2) % 360;
+ _rotationAngleX = (_rotationAngleX + 2) % 360;
+ restoreZDEP();
+ break;
+ case 1:
+ _rotationAngleZ = 0;
+ _rotationAngleX -= 2;
+ if (_rotationAngleX < 0)
+ _rotationAngleX += 360;
+ restoreZDEP();
+ break;
+ case 2:
+ _rotationAngleZ = (_rotationAngleZ + 2) % 360;
+ _rotationAngleX = 0;
+ restoreZDEP();
+ break;
+ case 3:
+ _rotationAngleZ -= 2;
+ if (_rotationAngleZ < 0)
+ _rotationAngleZ += 360;
+ _rotationAngleX = 0;
+ restoreZDEP();
+ break;
+ case 4:
+ _rotationAngleZ = 0;
+ _rotationAngleX = (_rotationAngleX + 2) % 360;
+ restoreZDEP();
+ break;
+ case 5:
+ _rotationAngleZ = 0;
+ _rotationAngleX = 0;
+ _translationZ += _zDirection * Z_STEP;
+ if ((_translationZ < -3600 + Z_RESET) || _translationZ > Z_RESET)
+ _zDirection = -_zDirection;
+ break;
+ case 6:
+ _rotationAngleZ = 0;
+ _rotationAngleX = 0;
+ _translationZ = Z_RESET;
+ break;
+ case 7:
+ _rotationAngleZ -= 2;
+ if (_rotationAngleZ < 0)
+ _rotationAngleZ += 360;
+ _rotationAngleX = 0;
+ restoreZDEP();
+ break;
+ case 8:
+ _rotationAngleZ = 0;
+ _rotationAngleX = 0;
+ _translationZ = Z_RESET;
+ break;
+ case 9:
+ _rotationAngleZ = 0;
+ _rotationAngleX = 0;
+ _translationZ = Z_RESET;
+ break;
+ }
+}
+
+void EdenGame::restoreZDEP() {
+ _zDirection = Z_UP;
+ if (_translationZ < Z_RESET)
+ _translationZ += _zDirection * Z_STEP;
+ if (_translationZ > Z_RESET)
+ _translationZ -= _zDirection * Z_STEP;
+}
+
+// Original name: affiche_polygone_mapping
+void EdenGame::displayPolygoneMapping(Cube *cubep, CubeFace *face) {
+ uint16 *indices = face->_indices;
+ int idx = indices[0];
+ int16 projX0 = cubep->_projection[idx].x;
+ int16 projY0 = cubep->_projection[idx].y;
+
+ idx = indices[1];
+ int16 projX1 = cubep->_projection[idx].x;
+ int16 projY1 = cubep->_projection[idx].y;
+
+ idx = indices[2];
+ int16 projX2 = cubep->_projection[idx].x;
+ int16 projY2 = cubep->_projection[idx].y;
+
+ if ((projY1 - projY0) * (projX2 - projX0) - (projY2 - projY0) * (projX1 - projX0) > 0)
+ return;
+
+ int16 *uv = face->_uv;
+ int16 ymin = 200; // min y
+ int16 ymax = 0; // max y
+ idx = indices[0];
+ int16 r20 = cubep->_projection[idx].x;
+ int16 r30 = cubep->_projection[idx].y;
+ int16 r19 = *uv++;
+ int16 r18 = *uv++;
+ indices++;
+ for (int i = 0; i < face->tri - 1; i++, indices++) {
+ idx = indices[0];
+ int16 r26 = cubep->_projection[idx].x;
+ int16 r31 = cubep->_projection[idx].y;
+ uint16 r25 = *uv++; //TODO: unsigned
+ int16 r24 = *uv++; //TODO: unsigned
+ ymin = MIN(r30, ymin);
+ ymax = MAX(r30, ymax);
+ ymin = MIN(r31, ymin);
+ ymax = MAX(r31, ymax);
+ drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines);
+ r20 = r26;
+ r30 = r31;
+ r19 = r25;
+ r18 = r24;
+ }
+ idx = face->_indices[0];
+ int16 r26 = cubep->_projection[idx].x;
+ int16 r31 = cubep->_projection[idx].y;
+ uv = face->_uv;
+ uint16 r25 = *uv++;
+ int16 r24 = *uv;
+ ymin = MIN(r30, ymin);
+ ymax = MAX(r30, ymax);
+ ymin = MIN(r31, ymin);
+ ymax = MAX(r31, ymax);
+ drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines);
+ displayMappingLine(ymin, ymax, _mainView->_bufferPtr, face->_texturePtr);
+}
+
+// Original name: trace_ligne_mapping
+void EdenGame::drawMappingLine(int16 r3, int16 r4, int16 r5, int16 r6, int16 r7, int16 r8, int16 r9, int16 r10, int16 *linesp) {
+ int16 r26 = r6 - r4;
+ if (r26 <= 0) {
+ if (r26 == 0) {
+ linesp += r4 * 8;
+ if (r5 - r3 > 0) {
+ linesp[0] = r3;
+ linesp[1] = r5;
+ linesp[4] = r7;
+ linesp[5] = r9;
+ linesp[6] = r8;
+ linesp[7] = r10;
+ } else {
+ linesp[0] = r5;
+ linesp[1] = r3;
+ linesp[4] = r9;
+ linesp[5] = r7;
+ linesp[6] = r10;
+ linesp[7] = r8;
+ }
+ return;
+ }
+ int16 t = r3;
+ r3 = r5;
+ r5 = t;
+ t = r7;
+ r7 = r9;
+ r9 = t;
+ t = r8;
+ r8 = r10;
+ r10 = t;
+ linesp += r6 * 8;
+ r26 = -r26;
+ } else
+ linesp += r4 * 8 + 1; //TODO wha???
+
+ int r30 = r3 << 16;
+ int r29 = r7 << 16;
+ int r28 = r8 << 16;
+
+ int r25 = ((r5 - r3) << 16) / r26;
+ int r24 = ((r9 - r7) << 16) / r26;
+ int r23 = ((r10 - r8) << 16) / r26;
+
+ for (int i = 0; i < r26; i++) {
+ linesp[0] = r30 >> 16;
+ linesp[4] = r29 >> 16;
+ linesp[6] = r28 >> 16;
+
+ r30 += r25;
+ r29 += r24;
+ r28 += r23;
+ linesp += 8;
+ }
+}
+
+// Original name: affiche_ligne_mapping
+void EdenGame::displayMappingLine(int16 r3, int16 r4, byte *target, byte *texture) {
+ int16 height = r4 - r3;
+ byte *trg_line = _mainView->_bufferPtr + r3 * 640; //TODO: target??
+ int16 *line = &_lines[r3 * 8];
+ // debug("curs: beg draw %d - %d", r3, r4);
+ for (int r22 = height; r22; r22--, line += 8, trg_line += 640) {
+ int16 r29 = line[0];
+ int16 r28 = line[1];
+ int16 len = r28 - r29;
+ if (len < 0)
+ break;
+ if (len == 0)
+ continue;
+
+ // debug("curs: lin draw %d", r4 - height);
+ uint16 r31 = line[4] << 8;
+ uint16 r30 = line[6] << 8;
+
+ int16 r21 = line[5] - line[4];
+ int16 r20 = line[7] - line[6];
+
+ int16 r26 = (r21 << 8) / len;
+ int16 r25 = (r20 << 8) / len;
+ byte *trg = trg_line + r29;
+#if 1
+ while (r29++ < r28) {
+ *trg++ = texture[(r30 & 0xFF00) | (r31 >> 8)];
+ r31 += r26;
+ r30 += r25;
+ }
+#endif
+ }
+}
+
+// PC cursor
+CubeCursor _cursorsPC[9] = {
+ { { 0, 0, 0, 0, 0, 0 }, 3, 2 },
+ { { 1, 1, 0, 1, 1, 0 }, 2, -2 },
+ { { 2, 2, 2, 2, 2, 2 }, 1, 2 },
+ { { 3, 3, 3, 3, 3, 3 }, 1, -2 },
+ { { 4, 4, 4, 4, 4, 4 }, 2, 2 },
+ { { 5, 5, 5, 5, 5, 5 }, 4, 0 },
+ { { 6, 6, 6, 6, 6, 6 }, 1, 2 },
+ { { 7, 7, 7, 7, 7, 7 }, 1, -2 },
+// { { 0, 8, 0, 0, 8, 8 }, 2, 2 },
+ { { 0, 8, 0, 0, 8, 8 }, 2, 2 }
+};
+
+XYZ _cubePC[6][3] = {
+ { { -15, -15, -15 }, { -15, 15, -15 }, { 15, 15, -15 } },
+ { { -15, -15, 15 }, { -15, 15, 15 }, { -15, 15, -15 } },
+ { { -15, -15, 15 }, { -15, -15, -15 }, { 15, -15, -15 } },
+ { { 15, -15, 15 }, { 15, 15, 15 }, { -15, 15, 15 } },
+ { { 15, -15, -15 }, { 15, 15, -15 }, { 15, 15, 15 } },
+ { { 15, 15, 15 }, { 15, 15, -15 }, { -15, 15, -15 } }
+};
+
+signed short cosineTable[] = {
+ // = cos(n) << 7; n += 10;
+ 128, 126, 120, 111, 98, 82, 64, 44, 22, 0, -22, -44, -64, -82, -98, -111, -120, -126,
+ -128, -126, -120, -111, -98, -82, -64, -44, -22, 0, 22, 44, 64, 82, 98, 111, 120, 126,
+ 128, 126, 120, 111, 98, 82, 64, 44, 22, 0
+};
+
+void EdenGame::makeTables() {
+ for (int i = -15; i < 15; i++) {
+ int v = (i * 11) / 15 + 11;
+ tab1[i + 15] = v;
+ tab2[i + 15] = v * 22;
+ }
+
+ for (int i = 0; i < 36; i++) {
+ for (int j = -35; j < 36; j++)
+ tab3[i][j + 35] = (cosineTable[i] * j) >> 7;
+ }
+}
+
+void EdenGame::getSinCosTables(unsigned short angle, signed char **cos_table, signed char **sin_table) {
+ angle /= 2;
+ *cos_table = tab3[angle] + 35;
+
+ angle += 9;
+ if (angle >= 36)
+ angle -= 36;
+
+ *sin_table = tab3[angle] + 35;
+}
+
+
+void EdenGame::rotatePoint(XYZ *point, XYZ *rpoint) {
+ // see http://www.cprogramming.com/tutorial/3d/rotation.html
+ XYZ xrot;
+
+ xrot.x = point->x;
+ xrot.y = _cosX[point->y] + _sinX[point->z];
+ xrot.z = _sinX[-point->y] + _cosX[point->z];
+
+ rpoint->x = _cosY[xrot.x] + _sinY[-xrot.z];
+ rpoint->y = xrot.y;
+ rpoint->z = _sinY[xrot.x] + _cosY[xrot.z];
+
+ rpoint->z += _zoomZ;
+}
+
+void EdenGame::mapPoint(XYZ *point, short *x, short *y) {
+ *y = ((12800 / point->z) * point->y) >> 7;
+ *x = ((12800 / point->z) * point->x) >> 7;
+}
+
+short EdenGame::calcFaceArea(XYZ *face) {
+ XYZ rpoint;
+ short x[3], y[3];
+
+ for (int i = 0; i < 3; i++) {
+ rotatePoint(&face[i], &rpoint);
+ mapPoint(&rpoint, &x[i], &y[i]);
+ }
+
+ short area = (y[1] - y[0]) * (x[2] - x[0]) - (y[2] - y[0]) * (x[1] - x[0]);
+
+ return area;
+}
+
+void EdenGame::paintPixel(XYZ *point, unsigned char pixel) {
+ short x, y;
+ mapPoint(point, &x, &y);
+ _cursorCenter[y * 40 + x] = pixel;
+}
+
+void EdenGame::paintFace0(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->x = x;
+ point->y = y;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[0][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFace1(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->y = y;
+ point->z = -x;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[1][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFace2(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->x = x;
+ point->z = -y;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[2][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFace3(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->x = -x;
+ point->y = -y;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[3][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFace4(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->y = y;
+ point->z = x;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[4][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFace5(XYZ *point) {
+ XYZ rpoint;
+ for (int y = -15; y < 15; y++) {
+ for (int x = -15; x < 15; x++) {
+ point->x = x;
+ point->z = y;
+ rotatePoint(point, &rpoint);
+ paintPixel(&rpoint, _face[5][tab1[x + 15] + tab2[y + 15]]);
+ }
+ }
+}
+
+void EdenGame::paintFaces() {
+ XYZ point;
+ if (!(_faceSkip & 1)) {
+ point.z = -15;
+ paintFace0(&point);
+ }
+ if (!(_faceSkip & 2)) {
+ point.x = -15;
+ paintFace1(&point);
+ }
+ if (!(_faceSkip & 4)) {
+ point.y = -15;
+ paintFace2(&point);
+ }
+ if (!(_faceSkip & 8)) {
+ point.z = 15;
+ paintFace3(&point);
+ }
+ if (!(_faceSkip & 16)) {
+ point.x = 15;
+ paintFace4(&point);
+ }
+ if (!(_faceSkip & 32)) {
+ point.y = 15;
+ paintFace5(&point);
+ }
+}
+
+void EdenGame::renderCube() {
+ for (uint16 i = 0; i < sizeof(_cursor); i++)
+ _cursor[i] = 0;
+ _cursorCenter = &_cursor[40 * 20 + 20];
+
+ getSinCosTables(_angleX, &_cosX, &_sinX);
+ getSinCosTables(_angleY, &_cosY, &_sinY);
+ getSinCosTables(_angleZ, &_cosZ, &_sinZ);
+
+ for (int i = 0; i < 6; i++) {
+ int area = calcFaceArea(_cubePC[i]);
+ if (area <= 0) {
+ _face[i] = _newface[i]; // set new texture for invisible area,
+ _faceSkip |= 1 << i; // but don't draw it just yet
+ } else
+ _faceSkip &= ~(1 << i);
+ }
+
+ paintFaces();
+
+ const int xshift = -5; // TODO: temporary fix to decrease left margin
+ unsigned char *cur = _cursor;
+ unsigned char *scr = _mainView->_bufferPtr + _cursorPosX + _scrollPos + xshift + _cursorPosY * _mainView->_pitch;
+
+ for (int y = 0; y < 40; y++) {
+ for (int x = 0; x < 40; x++) {
+ if (x + _cursorPosX + _scrollPos + xshift < _mainView->_pitch && y + _cursorPosY < _mainView->_height)
+ if (*cur)
+ *scr = *cur;
+ scr++;
+ cur++;
+ }
+ scr += _mainView->_pitch - 40;
+ }
+}
+
+
+void EdenGame::incAngleX(int step) {
+ _angleX += step;
+ if (_angleX == 70 + 2)
+ _angleX = 0;
+ else if (_angleX == 0 - 2)
+ _angleX = 70;
+}
+
+void EdenGame::decAngleX() {
+ if (_angleX != 0)
+ _angleX -= (_angleX > 4) ? 4 : 2;
+}
+
+void EdenGame::incAngleY(int step) {
+ _angleY += step;
+ if (_angleY == 70 + 2)
+ _angleY = 0;
+ else if (_angleY == 0 - 2)
+ _angleY = 70;
+}
+
+void EdenGame::decAngleY() {
+ if (_angleY != 0)
+ _angleY -= (_angleY > 4) ? 4 : 2;
+}
+
+void EdenGame::incZoom() {
+ if (_zoomZ == 170)
+ _zoomZStep = 40;
+ else if (_zoomZ == 570)
+ _zoomZStep = -40;
+ _zoomZ += _zoomZStep;
+}
+
+void EdenGame::decZoom() {
+ if (_zoomZ == 170)
+ return;
+
+ if (_zoomZ < 170)
+ _zoomZ = 170;
+ else
+ _zoomZ -= 40;
+}
+
+void EdenGame::initCubePC() {
+ _zoomZ = 170;
+ _zoomZStep = 40;
+ _angleX = _angleY = _angleZ = 0;
+ _pcCursor = &_cursorsPC[0];
+ _cursCurPCMap = -1;
+ makeTables();
+}
+
+void EdenGame::selectPCMap(int16 num) {
+ if (num != _cursCurPCMap) {
+ _pcCursor = &_cursorsPC[num];
+ unsigned char *bank = _mainBankBuf + READ_LE_UINT16(_mainBankBuf);
+ for (int i = 0; i < 6; i++) {
+ _newface[i] = 4 + (unsigned char*)getElem(bank, _pcCursor->_sides[i]);
+ if (_cursCurPCMap == -1)
+ _face[i] = _newface[i];
+ }
+ _cursCurPCMap = num;
+ }
+}
+
+void EdenGame::enginePC() {
+ int16 curs = _currCursor;
+ if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20))
+ curs = 9;
+ selectPCMap(curs);
+ _cursorNewTick = g_system->getMillis();
+ if (_cursorNewTick - _cursorOldTick < 1)
+ return;
+ _cursorOldTick = _cursorNewTick;
+ int step = _pcCursor->_speed;
+ switch (_pcCursor->_kind) {
+ case 0:
+ break;
+ case 1: // rot up-down
+ decAngleY();
+ decZoom();
+ incAngleX(step);
+ break;
+ case 2: // rot left-right
+ decAngleX();
+ decZoom();
+ incAngleY(step);
+ break;
+ case 3: // rotate random
+ decZoom();
+ incAngleX(step);
+ incAngleY(step);
+ break;
+ case 4: // zoom in-out
+ _face[0] = _newface[0];
+ decAngleY();
+ decAngleX();
+ incZoom();
+ break;
+ }
+ renderCube();
+}
+
+void EdenGame::LostEdenMac_InitPrefs() {
+ _globals->_prefLanguage = 1;
+ _globals->_prefMusicVol[0] = 192;
+ _globals->_prefMusicVol[1] = 192;
+ _globals->_prefVoiceVol[0] = 255;
+ _globals->_prefVoiceVol[1] = 255;
+ _globals->_prefSoundVolume[0] = 32;
+ _globals->_prefSoundVolume[1] = 32;
+}
+
+} // namespace Cryo
diff --git a/engines/cryo/eden.h b/engines/cryo/eden.h
new file mode 100644
index 0000000000..1fd5415163
--- /dev/null
+++ b/engines/cryo/eden.h
@@ -0,0 +1,774 @@
+/* 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.
+ *
+ */
+
+#ifndef CRYO_EDEN_H
+#define CRYO_EDEN_H
+
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+
+#include "cryo/sound.h"
+#include "cryo/defs.h"
+
+enum Direction {
+ kCryoNorth = 0,
+ kCryoEast = 1,
+ kCryoSouth = 2,
+ kCryoWest = 3
+};
+
+namespace Cryo {
+
+class CryoEngine;
+
+class EdenGame {
+private:
+ CryoEngine *_vm;
+
+public:
+ EdenGame(CryoEngine *vm);
+
+ void run();
+ object_t *getObjectPtr(int16 id);
+ void showObjects();
+
+private:
+ void removeConsole();
+ void scroll();
+ void resetScroll();
+ void scrollFrescoes();
+ void displayFrescoes();
+ void gametofresques();
+ void doFrescoes();
+ void actionEndFrescoes();
+ void scrollMirror();
+ void scrollPanel();
+ void displayFollower(Follower *follower, int16 x, int16 y);
+ void characterInMirror();
+ void gameToMirror(byte arg1);
+ void flipMode();
+ void quitMirror();
+ void clictimbre();
+ void actionClickValleyPlan();
+ void gotoPlace(Goto *go);
+ void deplaval(uint16 roomNum);
+ void move(Direction dir);
+ void move2(Direction dir);
+ void actionDinoBlow();
+ void actionPlateMonk();
+ void actionGraaFrescoe();
+ void actionLascFrescoe();
+ void actionPushStone();
+ void actionMummyHead();
+ void actionSkelettonHead();
+ void actionSkelettonMoorkong();
+ void actionChoose();
+ void handleDinaDialog();
+ void handleKingDialog();
+ void actionKingDialog1();
+ void actionKingDialog2();
+ void actionKingDialog3();
+ void actionGetKnife();
+ void actionGetPrism();
+ void actionGetMushroom();
+ void actionGetBadMushroom();
+ void actionGetGold();
+ void actionGetFullNest();
+ void actionGetEmptyNest();
+ void actionGetHorn();
+ void actionGetSunStone();
+ void actionGetEgg();
+ void actionGetTablet();
+ void actionLookLake();
+ void actionGotoHall();
+ void actionLabyrinthTurnAround();
+ void actionGotoFullNest();
+ void actionGotoVal();
+ void actionVisit();
+ void actionFinal();
+ void actionMoveNorth();
+ void actionMoveEast();
+ void actionMoveSouth();
+ void actionMoveWest();
+ void display();
+ void afficher128();
+ void saveFriezes();
+ void saveTopFrieze(int16 x);
+ void saveBottomFrieze();
+ void restoreFriezes();
+ void restoreTopFrieze();
+ void restoreBottomFrieze();
+ void useMainBank();
+ void useCharacterBank();
+ void useBank(int16 bank);
+ void sundcurs(int16 x, int16 y);
+ void rundcurs();
+ void drawSprite(int16 index, int16 x, int16 y, bool withBlack = false, bool onSubtitle = false);
+ void getglow(int16 x, int16 y, int16 w, int16 h);
+ void unglow();
+ void glow(int16 index);
+ void readPalette(byte *ptr);
+ void hideBars();
+ void showBars();
+ void saveMouthBackground();
+ void restoreMouthBackground();
+ void drawBlackBars();
+ void drawTopScreen();
+ void displayValleyMap();
+ void displayMapMark(int16 index, int16 location);
+ void displayAdamMapMark(int16 location);
+ void restoreAdamMapMark();
+ void saveAdamMapMark(int16 x, int16 y);
+ bool istrice(int16 roomNum);
+ bool istyran(int16 roomNum);
+ void istyranval(Area *area);
+ char getDirection(perso_t *perso);
+ bool canMoveThere(char loc, perso_t *perso);
+ void scramble1(uint8 elem[4]);
+ void scramble2(uint8 elem[4]);
+ void scrambleDirections();
+ bool naitredino(char persoType);
+ void newCitadel(char area, int16 level, Room *room);
+ void evolveCitadel(int16 level);
+ void destroyCitadelRoom(int16 roomNum);
+ void narratorBuildCitadel();
+ void citadelFalls(char level);
+ void buildCitadel();
+ void moveDino(perso_t *perso);
+ void moveAllDino();
+ void newValley();
+ char whereIsCita();
+ bool isCita(int16 loc);
+ void placeVava(Area *area);
+ void vivredino();
+ void vivreval(int16 areaNum);
+ void handleDay();
+ void addTime(int16 t);
+ void animCharacter();
+ void getanimrnd();
+ void addanim();
+ void removeMouthSprite();
+ void AnimEndCharacter();
+ void setCharacterSprite(byte *spr);
+ void displayImage();
+ void displayCharacter1();
+ void displayCharacter();
+ void ef_perso();
+ void loadCharacter(perso_t *perso);
+ void loadCurrCharacter();
+ void fin_perso();
+ void no_perso();
+ void closeCharacterScreen();
+ void displayBackgroundFollower();
+ void displayNoFollower(int16 bank);
+ void displayCharacterBackground1();
+ void displayCharacterBackground();
+ void setCharacterIcon();
+ void showCharacter();
+ void displayCharacterPanel();
+ void getDataSync();
+ int16 readFrameNumber();
+ void waitEndSpeak();
+ void my_bulle();
+ void my_pr_bulle();
+ void drawSubtitleChar(byte c, byte color, int16 width);
+ void displaySubtitles();
+ void saveUnderSubtitles(int16 y);
+ void restoreUnderSubtitles();
+ void displayHNMSubtitle();
+ void patchSentence();
+ void vavapers();
+ void citadelle();
+ void selectZone();
+ void showEvents1();
+ void showEvents();
+ void parle_mfin();
+ void parlemoi_normal();
+ void parle_moi();
+ void initCharacterPointers(perso_t *perso);
+ void perso1(perso_t *perso);
+ void perso_normal(perso_t *perso);
+ void handleCharacterDialog(int16 pers);
+ void actionKing();
+ void actionDina();
+ void actionThoo();
+ void actionMonk();
+ void actionTormentor();
+ void actionMessenger();
+ void actionMango();
+ void actionEve();
+ void actionAzia();
+ void actionMammi();
+ void actionGuards();
+ void actionBamboo();
+ void actionKabuka();
+ void actionFisher();
+ void actionDino();
+ void actionTyran();
+ void actionMorkus();
+ void comment();
+ void actionAdam();
+ void setChoiceYes();
+ void setChoiceNo();
+ bool isAnswerYes();
+ void specialMushroom(perso_t *perso);
+ void specialEmptyNest(perso_t *perso);
+ void specialNestWithEggs(perso_t *perso);
+ void specialApple(perso_t *perso);
+ void specialGold(perso_t *perso);
+ void specialPrism(perso_t *perso);
+ void specialTalisman(perso_t *perso);
+ void specialMask(perso_t *perso);
+ void specialBag(perso_t *perso);
+ void specialTrumpet(perso_t *perso);
+ void specialWeapons(perso_t *perso);
+ void specialInstrument(perso_t *perso);
+ void specialEgg(perso_t *perso);
+ void tyranDies(perso_t *perso);
+ void specialObjects(perso_t *perso, char objid);
+ void dialautoon();
+ void dialautooff();
+ void follow();
+ void dialonfollow();
+ void abortDialogue();
+ void subHandleNarrator();
+ void handleNarrator();
+ void checkPhraseFile();
+ byte *getPhrase(int16 id);
+ void actionGotoMap();
+ void record();
+ bool dial_scan(Dialog *dial);
+ bool dialoscansvmas(Dialog *dial);
+ bool dialogEvent(perso_t *perso);
+ void characterStayHere();
+ void endDeath(int16 vid);
+ void chronoEvent();
+ void setChrono(int16 t);
+ void preloadDialogs(int16 vid);
+ void displayEffect1();
+ void displayEffect2();
+ void displayEffect3();
+ void displayEffect4();
+ void clearScreen();
+ void colimacon(int16 pattern[16]);
+ void fadeToBlack(int delay);
+ void fadeToBlackLowPalette(int delay);
+ void fadeFromBlackLowPalette(int delay);
+ void blackRect32();
+ void setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey);
+ void setDestRect(int16 sx, int16 sy, int16 ex, int16 ey);
+ void wait(int howlong);
+ void effetpix();
+ void verifh(byte *ptr);
+ void openbigfile();
+ void closebigfile();
+ void loadRawFile(uint16 num, byte *buffer);
+ void loadIconFile(uint16 num, Icon *buffer);
+ void loadRoomFile(uint16 num, Room *buffer);
+ void loadHnm(uint16 num);
+ int loadSound(uint16 num);
+ void convertMacToPC();
+ void loadpermfiles();
+ bool ReadDataSyncVOC(unsigned int num);
+ bool ReadDataSync(uint16 num);
+ void loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len);
+ void expandHSQ(byte *input, byte *output);
+ void addInfo(byte info);
+ void unlockInfo();
+ void nextInfo();
+ void removeInfo(byte info);
+ void updateInfoList();
+ void initGlobals();
+ void initRects();
+ void closeRoom();
+ void displaySingleRoom(Room *room);
+ void displayRoom();
+ void displayPlace();
+ void loadPlace(int16 num);
+ void specialoutside();
+ void specialout();
+ void specialin();
+ void animpiece();
+ void getdino(Room *room);
+ Room *getRoom(int16 loc);
+ void initPlace(int16 roomNum);
+ void maj2();
+ void updateRoom1(int16 roomNum);
+ void updateRoom(uint16 roomNum);
+ void allocateBuffers();
+ void freebuf();
+ void openWindow();
+ void EmergencyExit();
+ void edmain();
+ void intro();
+ void enterGame();
+ void signon(const char *s);
+ void FRDevents();
+ Icon *scan_icon_list(int16 x, int16 y, int16 index);
+ void updateCursor();
+ void mouse();
+ void showMovie(char arg1);
+ void playHNM(int16 num);
+ void handleHNMSubtitles();
+ void musique();
+ void startmusique(byte num);
+ void musicspy();
+ int loadmusicfile(int16 num);
+ void persovox();
+ void endCharacterSpeech();
+ void fademusicup();
+ void fademusica0(int16 delay);
+ void countObjects();
+ void winObject(int16 id);
+ void loseObject(int16 id);
+ void lostObject();
+ bool isObjectHere(int16 id);
+ void objectmain(int16 id);
+ void getObject(int16 id);
+ void putObject();
+ void newObject(int16 id, int16 arg2);
+ void giveobjectal(int16 id);
+ void giveObject();
+ void actionTakeObject();
+ void newMushroom();
+ void newEmptyNest();
+ void newNestWithEggs();
+ void newGold();
+ void gotoPanel();
+ void noclicpanel();
+ void generique();
+ void cancel2();
+ void testvoice();
+ void load();
+ void initafterload();
+ void save();
+ void desktopcolors();
+ void panelrestart();
+ void reallyquit();
+ void confirmer(char mode, char yesId);
+ void confirmYes();
+ void confirmNo();
+ void restart();
+ void edenQuit();
+ void choseSubtitleOption();
+ void changeVolume();
+ void changervol();
+ void newvol(byte *volptr, int16 delta);
+ void playtape();
+ void rewindtape();
+ void depcurstape();
+ void affcurstape();
+ void forwardtape();
+ void stoptape();
+ void cliccurstape();
+ void paneltobuf();
+ void cursbuftopanel();
+ void langbuftopanel();
+ void displayPanel();
+ void displayLanguage();
+ void displayVolCursor(int16 x, int16 vol1, int16 vol2);
+ void displayCursors();
+ void selectCursor(int itemId);
+ void displayTopPanel();
+ void displayResult();
+ void restrictCursorArea(int16 xmin, int16 xmax, int16 ymin, int16 ymax);
+ void edenShudown();
+ void habitants(perso_t *perso);
+ void suiveurs(perso_t *perso);
+ void evenements(perso_t *perso);
+ void followme(perso_t *perso);
+ void rangermammi(perso_t *perso, Room *room);
+ void perso_ici(int16 action);
+ void setCharacterHere();
+ void faire_suivre(int16 roomNum);
+ void AddCharacterToParty();
+ void addToParty(int16 index);
+ void removeCharacterFromParty();
+ void removeFromParty(int16 index);
+ void handleEloiDeparture();
+ bool checkEloiReturn();
+ void handleEloiReturn();
+ void incPhase();
+ void phase113();
+ void phase130();
+ void phase161();
+ void phase226();
+ void phase257();
+ void phase353();
+ void phase369();
+ void phase371();
+ void phase385();
+ void phase418();
+ void phase433();
+ void phase434();
+ void phase513();
+ void phase514();
+ void phase529();
+ void phase545();
+ void phase561();
+ void bigphase1();
+ void bigphase();
+ void phase16();
+ void phase32();
+ void phase48();
+ void phase64();
+ void phase80();
+ void phase96();
+ void phase112();
+ void phase128();
+ void phase144();
+ void phase160();
+ void phase176();
+ void phase192();
+ void phase208();
+ void phase224();
+ void phase240();
+ void phase256();
+ void phase272();
+ void phase288();
+ void phase304();
+ void phase320();
+ void phase336();
+ void phase352();
+ void phase368();
+ void phase384();
+ void phase400();
+ void phase416();
+ void phase432();
+ void phase448();
+ void phase464();
+ void phase480();
+ void phase496();
+ void phase512();
+ void phase528();
+ void phase544();
+ void phase560();
+ void saveGame(char *name);
+ void loadrestart();
+ void loadgame(char *name);
+ void syncGame(Common::Serializer s);
+ void syncGlobalPointers(Common::Serializer s);
+ void syncGlobalValues(Common::Serializer s);
+ void syncCitadelRoomPointers(Common::Serializer s);
+ void syncTapePointers(Common::Serializer s);
+ char testCondition(int16 index);
+ uint16 operAdd(uint16 v1, uint16 v2);
+ uint16 operSub(uint16 v1, uint16 v2);
+ uint16 operLogicalAnd(uint16 v1, uint16 v2);
+ uint16 operLogicalOr(uint16 v1, uint16 v2);
+ uint16 operIsEqual(uint16 v1, uint16 v2);
+ uint16 operIsSmaller(uint16 v1, uint16 v2);
+ uint16 operIsGreater(uint16 v1, uint16 v2);
+ uint16 operIsDifferent(uint16 v1, uint16 v2);
+ uint16 operIsSmallerOrEqual(uint16 v1, uint16 v2);
+ uint16 operIsGreaterOrEqual(uint16 v1, uint16 v2);
+ uint16 operFalse(uint16 v1, uint16 v2);
+ uint16 operation(byte op, uint16 v1, uint16 v2);
+ uint16 fetchValue();
+ uint8 getByteVar(uint16 offset);
+ uint16 getWordVar(uint16 offset);
+ void actionNop();
+ void initSinCosTable();
+ void makeMatriceFix();
+ void projectionFix(Cube *cube, int n);
+ void initCubeMac();
+ void engineMac();
+ void displayObject(Cube *cube);
+ void loadMap(int file_id, byte *buffer);
+ void NEWcharge_objet_mob(Cube *cube, int fileNum, byte *texturePtr);
+ static int nextVal(char **ptr, char *error);
+ void selectMap(int16 num);
+ void Eden_dep_and_rot();
+ void restoreZDEP();
+ void displayPolygoneMapping(Cube *cube, CubeFace *face);
+ void drawMappingLine(int16 r3, int16 r4, int16 r5, int16 r6, int16 r7, int16 r8, int16 r9, int16 r10, int16 *lines);
+ void displayMappingLine(int16 r3, int16 r4, byte *target, byte *texture);
+ void LostEdenMac_InitPrefs();
+
+ void initCubePC();
+ void enginePC();
+ void selectPCMap(int16 num);
+
+ void makeTables();
+ void getSinCosTables(unsigned short angle, signed char **cos_table, signed char **sin_table);
+ void rotatePoint(XYZ *point, XYZ *rpoint);
+ void mapPoint(XYZ *point, short *x, short *y);
+ short calcFaceArea(XYZ *face);
+ void paintPixel(XYZ *point, unsigned char pixel);
+ void paintFace0(XYZ *point);
+ void paintFace1(XYZ *point);
+ void paintFace2(XYZ *point);
+ void paintFace3(XYZ *point);
+ void paintFace4(XYZ *point);
+ void paintFace5(XYZ *point);
+ void paintFaces();
+ void renderCube();
+
+ void incAngleX(int step);
+ void decAngleX();
+ void incAngleY(int step);
+ void decAngleY();
+ void incZoom();
+ void decZoom();
+
+ CubeCursor *_pcCursor;
+
+ int16 tab1[30];
+ int16 tab2[30];
+ int8 tab3[36][71];
+ int16 _angleX, _angleY, _angleZ, _zoomZ, _zoomZStep;
+
+ int8 *_cosX, *_sinX;
+ int8 *_cosY, *_sinY;
+ int8 *_cosZ, *_sinZ;
+
+ uint8 *_face[6], *_newface[6];
+ int16 _faceSkip;
+
+ uint8 _cursor[40 * 40];
+ uint8 *_cursorCenter;
+
+ byte _ownObjects[128];
+
+private:
+ int16 _scrollPos;
+ int16 _oldScrollPos;
+ bool _frescoTalk;
+ byte _oldPix[8];
+ Common::Point _adamMapMarkPos;
+ byte _cursKeepBuf[2500];
+ Common::Point _cursKeepPos;
+ bool _torchCursor;
+ int16 _curBankNum;
+ int16 _glowX;
+ int16 _glowY;
+ int16 _glowW;
+ int16 _glowH;
+ bool _paletteUpdateRequired;
+ bool _cursorSaved;
+ bool _showBlackBars;
+ bool _backgroundSaved;
+ byte *_bankData;
+ color_t _globalPalette[256]; //TODO palette_t
+ perso_t *_tyranPtr;
+ int _lastAnimFrameNumb;
+ int _curAnimFrameNumb;
+ int _lastAnimTicks;
+ Common::Rect *_curCharacterRect;
+ int16 _numAnimFrames;
+ int16 _maxPersoDesc;
+ int16 _numImgDesc;
+ bool _restartAnimation;
+ bool _animationActive;
+ byte _animationDelay;
+ byte _animationIndex;
+ byte _lastAnimationIndex;
+
+ byte *dword_30724;
+ byte *dword_30728; //TODO: rename - something amim-related
+ byte *_mouthAnimations;
+ byte *_animationTable;
+ byte _imageDesc[512];
+ byte *_characterBankData;
+ bool _savedUnderSubtitles;
+ int16 _numTextLines;
+ byte _sentenceBuffer[400];
+ byte phraseIconsBuffer[10];
+ byte _sentenceCoordsBuffer[22];
+ byte *_textOutPtr;
+ byte *textout;
+ object_t *_curSpecialObject;
+ bool _lastDialogChoice;
+ bool parlemoiNormalFlag;
+
+ bool _closeCharacterDialog;
+ int dword_30B04;
+
+ char _lastPhrasesFile;
+ byte _dialogSkipFlags;
+
+ color3_t newColor;
+ color_t oldPalette[256]; // TODO palette_t ?
+ color_t newPalette[256];
+ Common::Rect rect_dst, rect_src;
+ byte *_voiceSamplesBuffer; //TODO: sound sample buffer
+ Common::File _bigfile;
+ byte _infoList[16];
+ bool _needToFade;
+ byte *_mainBankBuf;
+ byte *_musicBuf;
+ byte *_gameLipsync;
+ byte *_gamePhrases;
+ byte *_gameDialogs; //TODO: rename to dialogs?
+ byte *_gameConditions;
+ byte *_placeRawBuf; //TODO: fixme
+ byte *_bankDataBuf;
+ Icon *_gameIcons;
+ Room *_gameRooms;
+ PakHeaderNode *_bigfileHeader;
+ byte *_glowBuffer;
+ byte *_mainViewBuf;
+ byte *_view2Buf;
+ byte *_gameFont; //TODO: rename to font?
+ byte *_subtitlesViewBuf;
+ byte *_underSubtitlesViewBuf; // CHECKME: Useless?
+ global_t *_globals;
+ uint16 _mouseCenterX;
+ uint16 _mouseCenterY;
+ bool _bufferAllocationErrorFl;
+ bool _quitFlag2;
+ bool _quitFlag3;
+ bool _gameStarted;
+ bool _soundAllocated;
+
+ CSoundChannel *_musicChannel;
+ CSoundChannel *_voiceChannel;
+ CSoundChannel *_hnmSoundChannel;
+ Sound *_voiceSound;
+
+ View *_view2;
+ View *_underSubtitlesView;
+ View *_subtitlesView;
+ View *_underBarsView;
+ View *_mainView;
+ View *_hnmView;
+ Common::Rect _underSubtitlesBackupRect;
+ Common::Rect _underSubtitlesScreenRect;
+ Common::Rect _underBottomBarBackupRect;
+ Common::Rect _underBottomBarScreenRect;
+ Common::Rect _underTopBarBackupRect;
+ Common::Rect _underTopBarScreenRect;
+ int _demoCurrentTicks;
+ int _demoStartTicks;
+ int _currentTime;
+ int16 _cirsorPanX;
+ int16 _inventoryScrollDelay;
+ int16 _cursorPosX;
+ int16 _cursorPosY;
+ int16 _currCursor;
+ Icon *_currSpot;
+ Icon *_curSpot2;
+ bool _mouseHeld;
+ bool _normalCursor;
+ byte *_hnmViewBuf;
+ bool _showVideoSubtitle;
+ bool _videoCanceledFlag; //TODO: hnm_canceled
+ bool _specialTextMode;
+ int _hnmFrameNum;
+ int _voiceSamplesSize; //TODO: perso vox sample data len
+ int16 _musicRightVol;
+ int16 _musicLeftVol;
+
+ bool _animateTalking;
+ bool _personTalking;
+ byte _musicFadeFlag;
+
+ char _musicSequencePos;
+ bool _musicPlayingFlag;
+
+ byte *_musicSamplesPtr;
+ byte *_musicPatternsPtr; //TODO: sndblock_t ?
+ byte *_musSequencePtr;
+ bool _musicEnabledFlag;
+ uint16 *_currentObjectLocation;
+ bool byte_31D64;
+
+ bool _noPalette;
+ bool _gameLoaded;
+#define MAX_TAPES 16
+ tape_t _tapes[MAX_TAPES];
+ byte _confirmMode;
+ byte *_curSliderValuePtr;
+ byte _lastMenuItemIdLo;
+ int16 _lastTapeRoomNum;
+ int16 _curSliderX;
+ int16 _curSliderY;
+ int16 _destinationRoom;
+ int16 word_31E7A; // CHECKME: Unused?
+
+ int16 word_378CC; // TODO: set by CLComputer_Init to 0
+ int16 word_378CE; // CHECKME: Unused
+
+ int _invIconsCount;
+ int _invIconsBase;
+ int _roomIconsBase;
+
+ //// cube.c
+ int16 _cosTable[361];
+ int16 _sinTable[361];
+ int _passMat31, _passMat21, _passMat11;
+ int _passMat32, _passMat22, _passMat12;
+ int _passMat33, _passMat23, _passMat13;
+ int16 _rotationAngleY; // CHECKME: USeless?
+ int16 _rotationAngleX, _rotationAngleZ;
+ float _translationY, _translationX; // CHECKME: Useless?
+ Cube _cube;
+ int16 _cursCurPCMap;
+ int16 _lines[200 * 8];
+ byte _cubeTexture[0x4000];
+ int _cubeFaces;
+ uint32 _cursorOldTick, _cursorNewTick;
+ byte *_codePtr;
+
+ uint8 tab_2CB1E[8][4];
+
+ const unsigned int kMaxMusicSize; // largest .mus file size
+
+ // Loaded from cryo.dat
+ Follower _followerList[15];
+ byte _labyrinthPath[70];
+ char _dinoSpeedForCitadelLevel[16];
+ char _tabletView[12];
+ char _personRoomBankTable[84]; // special character backgrounds for specific rooms
+
+ // Loaded from cryo.dat - Area transition descriptors
+ Goto _gotos[130];
+ object_t _objects[42];
+ uint16 _objectLocations[45];
+ perso_t _persons[58];
+ Citadel _citadelList[7];
+
+ // Loaded from cryo.dat
+ Common::Rect _characterRects[19];
+ byte _characterArray[20][5];
+ Area _areasTable[12];
+ int16 tab_2CEF0[64];
+ int16 tab_2CF70[64];
+ byte _actionCursors[299];
+ byte _mapMode[12];
+ byte _cubeTextureCoords[3][6 * 2 * 3 * 2];
+
+ int32 _translationZ;
+ int8 _zDirection; // 1 (up) or -1 (down)
+
+ // Torch/glow related
+ int16 _torchTick;
+ int16 _glowIndex;
+ int16 _torchCurIndex;
+
+ int _cursCenter;
+};
+
+}
+
+#endif
diff --git a/engines/cryo/graphics.cpp b/engines/cryo/graphics.cpp
new file mode 100644
index 0000000000..51cb818f3e
--- /dev/null
+++ b/engines/cryo/graphics.cpp
@@ -0,0 +1,1208 @@
+/* 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.
+ *
+ */
+
+#include "cryo/defs.h"
+#include "cryo/cryo.h"
+#include "cryo/platdefs.h"
+#include "cryo/cryolib.h"
+#include "cryo/eden.h"
+#include "cryo/sound.h"
+
+namespace Cryo {
+
+// Original name: noclipax
+void EdenGame::drawSprite(int16 index, int16 x, int16 y, bool withBlack, bool onSubtitle) {
+ uint16 width = (!onSubtitle) ? 640 : _subtitlesXWidth;
+ byte *pix = _bankData;
+ byte *buf = (!onSubtitle) ? _mainViewBuf : _subtitlesViewBuf;
+ byte *scr = buf + x + y * width;
+ if (_curBankNum != 117 && (!_noPalette || withBlack || onSubtitle)) {
+ if (READ_LE_UINT16(pix) > 2)
+ readPalette(pix + 2);
+ }
+ pix += READ_LE_UINT16(pix);
+ pix += READ_LE_UINT16(pix + index * 2);
+ // int16 height:9
+ // int16 pad:6;
+ // int16 flag:1;
+ byte h0 = *pix++;
+ byte h1 = *pix++;
+ int16 w = ((h1 & 1) << 8) | h0;
+ int16 h = *pix++;
+ byte mode = *pix++;
+ if (mode != 0xFF && mode != 0xFE)
+ return;
+ if (y + h > 200 && !onSubtitle)
+ h -= (y + h - 200);
+ if (h1 & 0x80) {
+ // compressed
+ for (; h-- > 0;) {
+ for (int16 ww = w; ww > 0;) {
+ byte c = *pix++;
+ if (c >= 0x80) {
+ if (c == 0x80) {
+ byte fill = *pix++;
+ if (fill == 0 && !withBlack) {
+ scr += 128 + 1;
+ ww -= 128 + 1;
+ }
+ else {
+ byte runVal;
+ *scr++ = fill; //TODO: wha?
+ *scr++ = fill;
+ ww -= 128 + 1;
+ for (runVal = 127; runVal--;)
+ *scr++ = fill;
+ }
+ }
+ else {
+ byte fill = *pix++;
+ byte runVal = 255 - c + 2;
+ ww -= runVal;
+ if (fill == 0 && !withBlack)
+ scr += runVal;
+ else
+ for (; runVal--;)
+ *scr++ = fill;
+ }
+ }
+ else {
+ byte runVal = c + 1;
+ ww -= runVal;
+ for (; runVal--;) {
+ byte p = *pix++;
+ if (p == 0 && !withBlack)
+ scr++;
+ else
+ *scr++ = p;
+ }
+ }
+ }
+ scr += width - w;
+ }
+ }
+ else {
+ // uncompressed
+ for (; h--;) {
+ for (int16 ww = w; ww--;) {
+ byte p = *pix++;
+ if (p == 0 && !withBlack)
+ scr++;
+ else
+ *scr++ = p;
+ }
+ scr += width - w;
+ }
+ }
+}
+
+void EdenGame::sundcurs(int16 x, int16 y) {
+ byte *keep = _cursKeepBuf;
+ x = CLIP<int16>(x - 4, 0, 640 - 48);
+ y = CLIP<int16>(y - 4, 0, 200 - 48);
+ _cursKeepPos = Common::Point(x, y);
+ byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640;
+ for (int16 h = 48; h--;) {
+ for (int16 w = 48; w--;)
+ *keep++ = *scr++;
+ scr += 640 - 48;
+ }
+ _cursorSaved = true;
+}
+
+void EdenGame::rundcurs() {
+ byte *keep = _cursKeepBuf;
+ byte *scr = _mainViewBuf + _cursKeepPos.x + _cursKeepPos.y * 640;
+ if (!_cursorSaved || (_cursKeepPos == Common::Point(-1, -1))) //TODO ...
+ return;
+
+ for (int16 h = 48; h--;) {
+ for (int16 w = 48; w--;)
+ *scr++ = *keep++;
+ scr += 640 - 48;
+ }
+}
+
+void EdenGame::getglow(int16 x, int16 y, int16 w, int16 h) {
+ byte *scr = _mainViewBuf + x + y * 640;
+ byte *gl = _glowBuffer;
+ _glowX = x;
+ _glowY = y;
+ _glowW = w;
+ _glowH = h;
+ for (; h--;) {
+ for (int16 ww = w; ww--;)
+ *gl++ = *scr++;
+ scr += 640 - w;
+ }
+}
+
+void EdenGame::unglow() {
+ byte *gl = _glowBuffer;
+ byte *scr = _mainViewBuf + _glowX + _glowY * 640;
+ if (_glowX < 0 || _glowY < 0) //TODO: move it up
+ return;
+ for (; _glowH--;) {
+ for (int16 ww = _glowW; ww--;)
+ *scr++ = *gl++;
+ scr += 640 - _glowW;
+ }
+}
+
+void EdenGame::glow(int16 index) {
+ // byte pixbase;
+ byte *pix = _bankData;
+
+ index += 9;
+ pix += READ_LE_UINT16(pix);
+ pix += READ_LE_UINT16(pix + index * 2);
+ // int16 height:9
+ // int16 pad:6;
+ // int16 flag:1;
+ byte h0 = *pix++;
+ byte h1 = *pix++;
+ int16 w = ((h1 & 1) << 8) | h0;
+ int16 h = *pix++;
+ byte mode = *pix++;
+ if (mode != 0xFF && mode != 0xFE)
+ return;
+
+ int16 x = _cursorPosX + _scrollPos - 38;
+ int16 y = _cursorPosY - 28;
+ int16 ex = _globals->_frescoeWidth + 320;
+
+ if (x + w <= 0 || x >= ex || y + h <= 0 || y >= 176)
+ return;
+
+ int16 dx;
+ if (x < 0) {
+ dx = -x;
+ x = 0;
+ }
+ else if (x + w > ex)
+ dx = x + w - ex;
+ else
+ dx = 0;
+
+ int16 dy = 0;
+ if (y < 16) {
+ dy = 16 - y;
+ y = 16;
+ }
+ else if (y + h > 175)
+ dy = y + h - 175;
+
+ int16 pstride = dx;
+ int16 sstride = 640 - (w - dx);
+ if (y == 16)
+ pix += w * dy;
+ if (x == 0)
+ pix += dx;
+
+ byte *scr = _mainViewBuf + x + y * 640;
+
+ w -= dx;
+ h -= dy;
+
+ getglow(x, y, w, h);
+
+ for (; h--;) {
+ for (int16 ww = w; ww--;) {
+ byte p = *pix++;
+ if (p == 0)
+ scr++;
+ else
+ *scr++ += p << 4;
+ }
+ pix += pstride;
+ scr += sstride;
+ }
+}
+
+// Original name : blackbars
+void EdenGame::drawBlackBars() {
+ byte *scr = _mainViewBuf;
+ for (int16 y = 0; y < 16; y++) {
+ for (int16 x = 0; x < 640; x++)
+ *scr++ = 0;
+ }
+
+ scr += 640 * (200 - 16 - 24);
+ for (int16 y = 0; y < 24; y++) {
+ for (int16 x = 0; x < 640; x++)
+ *scr++ = 0;
+ }
+}
+
+// Original name: bars_out
+void EdenGame::hideBars() {
+ if (_showBlackBars)
+ return;
+
+ display();
+ _underTopBarScreenRect.left = _scrollPos;
+ _underTopBarScreenRect.right = _scrollPos + 320 - 1;
+ CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+ _underBottomBarScreenRect.left = _underTopBarScreenRect.left;
+ _underBottomBarScreenRect.right = _underTopBarScreenRect.right;
+ CLBlitter_CopyViewRect(_mainView, _underBarsView, &_underBottomBarScreenRect, &_underBottomBarBackupRect);
+ int16 r19 = 14; // TODO - init in decl?
+ int16 r20 = 176;
+ int16 r25 = 14;
+ int16 r24 = 21;
+ _underTopBarScreenRect.left = 0;
+ _underTopBarScreenRect.right = 320 - 1;
+ _underTopBarBackupRect.left = _scrollPos;
+ _underTopBarBackupRect.right = _scrollPos + 320 - 1;
+ unsigned int *scr40, *scr41, *scr42;
+ while (r24 > 0) {
+ if (r25 > 0) {
+ _underTopBarScreenRect.top = 16 - r25;
+ _underTopBarScreenRect.bottom = 16 - 1;
+ _underTopBarBackupRect.top = 0;
+ _underTopBarBackupRect.bottom = r25 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+ scr40 = ((unsigned int *)_mainViewBuf) + r19 * 640 / 4;
+ scr41 = scr40 + 640 / 4;
+ for (int i = 0; i < 320; i += 4) {
+ *scr40++ = 0;
+ *scr41++ = 0;
+ }
+ }
+ _underTopBarScreenRect.top = 16;
+ _underTopBarScreenRect.bottom = r24 + 16 - 1;
+ _underTopBarBackupRect.top = 200 - r24;
+ _underTopBarBackupRect.bottom = 200 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+ scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4;
+ scr41 = scr40 + 640 / 4;
+ scr42 = scr41 + 640 / 4;
+ for (int i = 0; i < 320; i += 4) {
+ *scr40++ = 0;
+ *scr41++ = 0;
+ *scr42++ = 0;
+ }
+ r19 -= 2;
+ r20 += 3;
+ r25 -= 2;
+ r24 -= 3;
+ display();
+ }
+ scr40 = (unsigned int *)_mainViewBuf;
+ scr41 = scr40 + 640 / 4;
+ for (int i = 0; i < 320; i += 4) {
+ *scr40++ = 0;
+ *scr41++ = 0;
+ }
+ scr40 = ((unsigned int *)_mainViewBuf) + r20 * 640 / 4;
+ scr41 = scr40 + 640 / 4;
+ scr42 = scr41 + 640 / 4;
+ for (int i = 0; i < 320; i += 4) {
+ *scr40++ = 0;
+ *scr41++ = 0;
+ *scr42++ = 0;
+ }
+ display();
+ initRects();
+ _showBlackBars = true;
+}
+
+// Original name: bars_in
+void EdenGame::showBars() {
+ if (!_showBlackBars)
+ return;
+
+ drawBlackBars();
+ int16 r29 = 2;
+ int16 r28 = 2;
+ _underTopBarScreenRect.left = 0;
+ _underTopBarScreenRect.right = 320 - 1;
+ _underTopBarBackupRect.left = _scrollPos;
+ _underTopBarBackupRect.right = _scrollPos + 320 - 1;
+ while (r28 < 24) {
+ if (r29 <= 16) {
+ _underTopBarScreenRect.top = 16 - r29;
+ _underTopBarScreenRect.bottom = 16 - 1;
+ _underTopBarBackupRect.top = 0;
+ _underTopBarBackupRect.bottom = r29 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+ }
+ _underTopBarScreenRect.top = 16;
+ _underTopBarScreenRect.bottom = 16 + r28;
+ _underTopBarBackupRect.top = 200 - 1 - r28;
+ _underTopBarBackupRect.bottom = 200 - 1;
+ CLBlitter_CopyViewRect(_underBarsView, _mainView, &_underTopBarScreenRect, &_underTopBarBackupRect);
+ r29 += 2;
+ r28 += 3;
+ display();
+ }
+ initRects();
+ _showBlackBars = false;
+}
+
+// Original name: af_image
+void EdenGame::displayImage() {
+ byte *img = _imageDesc + 200;
+
+ int16 count = READ_LE_UINT16(img);
+ if (!count)
+ return;
+
+ byte *img_start = img;
+ byte *curimg = _imageDesc;
+
+ img += 2;
+ count *= 3;
+ while (count--)
+ *curimg++ = *img++;
+ img = img_start;
+ count = READ_LE_UINT16(img);
+ img += 2;
+ /////// draw it
+ while (count--) {
+ uint16 index = *img++;
+ uint16 x = *img++ + _gameIcons[0].sx;
+ uint16 y = *img++ + _gameIcons[0].sy;
+ byte *pix = _bankData;
+ byte *scr = _mainViewBuf + x + y * 640;
+ index--;
+ if (READ_LE_UINT16(pix) > 2)
+ readPalette(pix + 2);
+ pix += READ_LE_UINT16(pix);
+ pix += READ_LE_UINT16(pix + index * 2);
+ // int16 height:9
+ // int16 pad:6;
+ // int16 flag:1;
+ byte h0 = *pix++;
+ byte h1 = *pix++;
+ int16 w = ((h1 & 1) << 8) | h0;
+ int16 h = *pix++;
+ byte mode = *pix++;
+ if (mode != 0xFF && mode != 0xFE)
+ continue; //TODO: enclosing block?
+ if (h1 & 0x80) {
+ // compressed
+ for (; h-- > 0;) {
+ for (int16 ww = w; ww > 0;) {
+ byte c = *pix++;
+ if (c >= 0x80) {
+ if (c == 0x80) {
+ byte fill = *pix++;
+ if (fill == 0) {
+ scr += 128 + 1;
+ ww -= 128 + 1;
+ }
+ else {
+ byte runVal;
+ *scr++ = fill; //TODO: wha?
+ *scr++ = fill;
+ ww -= 128 + 1;
+ for (runVal = 127; runVal--;)
+ *scr++ = fill;
+ }
+ }
+ else {
+ byte fill = *pix++;
+ byte runVal = 255 - c + 2;
+ ww -= runVal;
+ if (fill == 0)
+ scr += runVal;
+ else {
+ for (; runVal--;)
+ *scr++ = fill;
+ }
+ }
+ }
+ else {
+ byte runVal = c + 1;
+ ww -= runVal;
+ for (; runVal--;) {
+ byte p = *pix++;
+ if (p == 0)
+ scr++;
+ else
+ *scr++ = p;
+ }
+ }
+ }
+ scr += 640 - w;
+ }
+ }
+ else {
+ // uncompressed
+ for (; h--;) {
+ for (int16 ww = w; ww--;) {
+ byte p = *pix++;
+ if (p == 0)
+ scr++;
+ else
+ *scr++ = p;
+ }
+ scr += 640 - w;
+ }
+ }
+ }
+}
+
+// Original name: af_subtitle
+void EdenGame::displaySubtitles() {
+ byte *src = _subtitlesViewBuf;
+ byte *dst = _mainViewBuf;
+ int16 y;
+ if (_globals->_displayFlags & DisplayFlags::dfFlag2) {
+ y = 174;
+ if ((_globals->_drawFlags & DrawFlags::drDrawMenu) && _numTextLines == 1)
+ y = 167;
+ dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _subtitlesXScrMargin;
+ }
+ else {
+ y = 174;
+ dst += 640 * (y - _numTextLines * FONT_HEIGHT) + _scrollPos + _subtitlesXScrMargin;
+ }
+ if (_animationActive && !_personTalking)
+ return;
+ saveUnderSubtitles(y);
+ for (int16 h = 0; h < _numTextLines * FONT_HEIGHT + 1; h++) {
+ for (int16 w = 0; w < _subtitlesXWidth; w++) {
+ byte c = *src++;
+ if (c)
+ *dst = c;
+ dst++;
+ }
+ dst += 640 - _subtitlesXWidth;
+ }
+}
+
+// Original name afsalle1
+void EdenGame::displaySingleRoom(Room *room) {
+ byte *ptr = (byte *)getElem(_placeRawBuf, room->_id - 1);
+ ptr++;
+ for (;;) {
+ byte b0 = *ptr++;
+ byte b1 = *ptr++;
+ int16 index = (b1 << 8) | b0;
+ if (index == -1)
+ break;
+ if (index > 0) {
+ int16 x = *ptr++ | (((b1 & 0x2) >> 1) << 8); //TODO: check me
+ int16 y = *ptr++;
+ ptr++;
+ index &= 0x1FF;
+ if (!(_globals->_displayFlags & 0x80)) {
+ if (index == 1 || _globals->_varF7)
+ drawSprite(index - 1, x, y, true);
+ }
+ _globals->_varF7 = 0;
+ continue;
+ }
+ if (b1 & 0x40) {
+ if (b1 & 0x20) {
+ bool addIcon = false;
+ Icon *icon = _globals->_nextRoomIcon;
+ if (b0 < 4) {
+ if (_globals->_roomPtr->_exits[b0])
+ addIcon = true;
+ }
+ else if (b0 > 229) {
+ if (_globals->_partyOutside & (1 << (b0 - 230)))
+ addIcon = true;
+ }
+ else if (b0 >= 100) {
+ debug("add object %d", b0 - 100);
+ if (isObjectHere(b0 - 100)) {
+ addIcon = true;
+ _globals->_varF7 = 1;
+ }
+ }
+ else
+ addIcon = true;
+ if (addIcon) {
+ icon->_actionId = b0;
+ icon->_objectId = b0;
+ icon->_cursorId = _actionCursors[b0];
+ int16 x = READ_LE_UINT16(ptr);
+ ptr += 2;
+ int16 y = READ_LE_UINT16(ptr);
+ ptr += 2;
+ int16 ex = READ_LE_UINT16(ptr);
+ ptr += 2;
+ int16 ey = READ_LE_UINT16(ptr);
+ ptr += 2;
+ x += _globals->_roomBaseX;
+ ex += _globals->_roomBaseX;
+ debug("add hotspot at %3d:%3d - %3d:%3d, action = %d", x, y, ex, ey, b0);
+
+ if (_vm->_showHotspots) {
+ for (int iii = x; iii < ex; iii++)
+ _mainViewBuf[y * 640 + iii] = _mainViewBuf[ey * 640 + iii] = (iii % 2) ? 0 : 255;
+ for (int iii = y; iii < ey; iii++)
+ _mainViewBuf[iii * 640 + x] = _mainViewBuf[iii * 640 + ex] = (iii % 2) ? 0 : 255;
+ }
+
+ icon->sx = x;
+ icon->sy = y;
+ icon->ex = ex;
+ icon->ey = ey;
+ _globals->_nextRoomIcon = ++icon;
+ icon->sx = -1;
+ }
+ else
+ ptr += 8;
+ }
+ else
+ ptr += 8;
+ }
+ else
+ ptr += 8;
+ }
+}
+
+// Original name: afsalle
+void EdenGame::displayRoom() {
+ Room *room = _globals->_roomPtr;
+ _globals->_displayFlags = DisplayFlags::dfFlag1;
+ _globals->_roomBaseX = 0;
+ _globals->_roomBackgroundBankNum = room->_backgroundBankNum;
+ if (room->_flags & RoomFlags::rf08) {
+ _globals->_displayFlags |= DisplayFlags::dfFlag80;
+ if (room->_flags & RoomFlags::rfPanable) {
+ // Scrollable room on 2 screens
+ _globals->_displayFlags |= DisplayFlags::dfPanable;
+ _globals->_varF4 = 0;
+ rundcurs();
+ saveFriezes();
+ useBank(room->_bank - 1);
+ drawSprite(0, 0, 16, true);
+ useBank(room->_bank);
+ drawSprite(0, 320, 16, true);
+ displaySingleRoom(room);
+ _globals->_roomBaseX = 320;
+ displaySingleRoom(room + 1);
+ }
+ else
+ displaySingleRoom(room);
+ }
+ else {
+ //TODO: roomImgBank is garbage here!
+ debug("displayRoom: room 0x%X using bank %d", _globals->_roomNum, _globals->_roomImgBank);
+ useBank(_globals->_roomImgBank);
+ displaySingleRoom(room);
+ assert(_vm->_screenView->_pitch == 320);
+ }
+}
+
+void EdenGame::openWindow() {
+ _underBarsView = new View(320, 40);
+ _underBarsView->_normal._width = 320;
+
+ _view2 = new View(32, 32);
+ _view2Buf = _view2->_bufferPtr;
+
+ _subtitlesView = new View(_subtitlesXWidth, 60);
+ _subtitlesViewBuf = _subtitlesView->_bufferPtr;
+
+ _underSubtitlesView = new View(_subtitlesXWidth, 60);
+ _underSubtitlesViewBuf = _underSubtitlesView->_bufferPtr;
+
+ _mainView = new View(640, 200);
+ _mainView->_normal._width = 320;
+ CLBlitter_FillView(_mainView, 0xFFFFFFFF);
+ _mainView->setSrcZoomValues(0, 0);
+ _mainView->setDisplayZoomValues(640, 400);
+ _mainView->centerIn(_vm->_screenView);
+ _mainViewBuf = _mainView->_bufferPtr;
+
+ _mouseCenterX = _mainView->_normal._dstLeft + _mainView->_normal._width / 2;
+ _mouseCenterY = _mainView->_normal._dstTop + _mainView->_normal._height / 2;
+ _vm->setMousePosition(_mouseCenterX, _mouseCenterY);
+ _vm->hideMouse();
+
+ _cursorPosX = 320 / 2;
+ _cursorPosY = 200 / 2;
+}
+
+// Original name: effet1
+void EdenGame::displayEffect1() {
+ blackRect32();
+ setSrcRect(0, 0, 16 - 1, 4 - 1);
+ int y = _mainView->_normal._dstTop;
+ for (int16 i = 16; i <= 96; i += 4) {
+ for (int x = _mainView->_normal._dstLeft; x < _mainView->_normal._dstLeft + 320; x += 16) {
+ setDestRect(x, y + i, x + 16 - 1, y + i + 4 - 1);
+ CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst);
+ setDestRect(x, y + 192 - i, x + 16 - 1, y + 192 - i + 4 - 1);
+ CLBlitter_CopyViewRect(_view2, _vm->_screenView, &rect_src, &rect_dst);
+ }
+ CLBlitter_UpdateScreen();
+ wait(1);
+ }
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+ _mainView->_normal._height = 2;
+ _mainView->_zoom._height = 4;
+ int16 ny = _mainView->_normal._dstTop;
+ int16 dy = _mainView->_zoom._dstTop;
+ for (int16 i = 0; i < 100; i += 2) {
+ _mainView->_normal._srcTop = 99 - i;
+ _mainView->_zoom._srcTop = 99 - i;
+ _mainView->_normal._dstTop = 99 - i + ny;
+ _mainView->_zoom._dstTop = (99 - i) * 2 + dy;
+ CLBlitter_CopyView2Screen(_mainView);
+ _mainView->_normal._srcTop = 100 + i;
+ _mainView->_zoom._srcTop = 100 + i;
+ _mainView->_normal._dstTop = 100 + i + ny;
+ _mainView->_zoom._dstTop = (100 + i) * 2 + dy;
+ CLBlitter_CopyView2Screen(_mainView);
+ CLBlitter_UpdateScreen();
+ wait(1);
+ }
+ _mainView->_normal._height = 200;
+ _mainView->_zoom._height = 400;
+ _mainView->_normal._srcTop = 0;
+ _mainView->_zoom._srcTop = 0;
+ _mainView->_normal._dstTop = ny;
+ _mainView->_zoom._dstTop = dy;
+ _globals->_varF1 = 0;
+}
+
+// Original name: effet2
+void EdenGame::displayEffect2() {
+ static int16 pattern1[] = { 0, 1, 2, 3, 7, 11, 15, 14, 13, 12, 8, 4, 5, 6, 10, 9 };
+ static int16 pattern2[] = { 0, 15, 1, 14, 2, 13, 3, 12, 7, 8, 11, 4, 5, 10, 6, 9 };
+ static int16 pattern3[] = { 0, 2, 5, 7, 8, 10, 13, 15, 1, 3, 4, 6, 9, 11, 12, 14 };
+ static int16 pattern4[] = { 0, 3, 15, 12, 1, 7, 14, 8, 2, 11, 13, 4, 5, 6, 10, 9 };
+
+ static int eff2pat = 0;
+ if (_globals->_var103 == 69) {
+ displayEffect4();
+ return;
+ }
+ switch (++eff2pat) {
+ case 1:
+ colimacon(pattern1);
+ break;
+ case 2:
+ colimacon(pattern2);
+ break;
+ case 3:
+ colimacon(pattern3);
+ break;
+ case 4:
+ colimacon(pattern4);
+ eff2pat = 0;
+ break;
+ }
+}
+
+// Original name: effet3
+void EdenGame::displayEffect3() {
+ CLPalette_GetLastPalette(oldPalette);
+ for (uint16 i = 0; i < 6; i++) {
+ for (uint16 c = 0; c < 256; c++) {
+ newColor.r = oldPalette[c].r >> i;
+ newColor.g = oldPalette[c].g >> i;
+ newColor.b = oldPalette[c].b >> i;
+ CLPalette_SetRGBColor(newPalette, c, &newColor);
+ }
+ CLPalette_Send2Screen(newPalette, 0, 256);
+ wait(1);
+ }
+ CLBlitter_CopyView2Screen(_mainView);
+ for (uint16 i = 0; i < 6; i++) {
+ for (uint16 c = 0; c < 256; c++) {
+ newColor.r = _globalPalette[c].r >> (5 - i);
+ newColor.g = _globalPalette[c].g >> (5 - i);
+ newColor.b = _globalPalette[c].b >> (5 - i);
+ CLPalette_SetRGBColor(newPalette, c, &newColor);
+ }
+ CLPalette_Send2Screen(newPalette, 0, 256);
+ wait(1);
+ }
+}
+
+// Original name: effet4
+void EdenGame::displayEffect4() {
+ byte *scr, *pix, *r24, *r25, *r30, c;
+ int16 r17, r23, r16, r18, r19, r22, r27, r31;
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+
+ int16 ww = _vm->_screenView->_pitch;
+ int16 x = _mainView->_normal._dstLeft;
+ int16 y = _mainView->_normal._dstTop;
+ for (int16 i = 32; i > 0; i -= 2) {
+ scr = _vm->_screenView->_bufferPtr;
+ scr += (y + 16) * ww + x;
+ pix = _mainView->_bufferPtr + 16 * 640;
+ r17 = 320 / i;
+ r23 = 320 - 320 / i * i; //TODO: 320 % i ?
+ r16 = 160 / i;
+ r18 = 160 - 160 / i * i; //TODO: 160 % i ?
+ for (r19 = r16; r19 > 0; r19--) {
+ r24 = scr;
+ r25 = pix;
+ for (r22 = r17; r22 > 0; r22--) {
+ c = *r25;
+ r25 += i;
+ r30 = r24;
+ for (r27 = i; r27 > 0; r27--) {
+ for (r31 = i; r31 > 0; r31--)
+ *r30++ = c;
+ r30 += ww - i;
+ }
+ r24 += i;
+ }
+ if (r23) {
+ c = *r25;
+ r30 = r24;
+ for (r27 = i; r27 > 0; r27--) {
+ for (r31 = r23; r31 > 0; r31--)
+ *r30++ = c;
+ r30 += ww - r23;
+ }
+ }
+ scr += i * ww;
+ pix += i * 640;
+ }
+ if (r18) {
+ r24 = scr;
+ r25 = pix;
+ for (r22 = r17; r22 > 0; r22--) {
+ c = *r25;
+ r25 += i;
+ r30 = r24;
+ for (r27 = r18; r27 > 0; r27--) {
+ for (r31 = i; r31 > 0; r31--)
+ *r30++ = c;
+ r30 += ww - i;
+ }
+ r24 += i;
+ }
+ if (r23) {
+ c = *r25;
+ r30 = r24;
+ for (r27 = r18; r27 > 0; r27--) {
+ for (r31 = r23; r31 > 0; r31--)
+ *r30++ = c;
+ r30 += ww - r23;
+ }
+ }
+ }
+ CLBlitter_UpdateScreen();
+ wait(3);
+ }
+ CLBlitter_CopyView2Screen(_mainView);
+}
+
+void EdenGame::clearScreen() {
+ int16 ww = _vm->_screenView->_pitch;
+ int16 x = _mainView->_normal._dstLeft;
+ int16 y = _mainView->_normal._dstTop;
+ byte *scr = _vm->_screenView->_bufferPtr;
+ scr += (y + 16) * ww + x;
+ for (int16 yy = 0; yy < 160; yy++) {
+ for (int16 xx = 0; xx < 320; xx++)
+ *scr++ = 0;
+ scr += ww - 320;
+ }
+ CLBlitter_UpdateScreen();
+}
+
+void EdenGame::colimacon(int16 pattern[16]) {
+ int16 p, r27, r25;
+
+ int16 ww = _vm->_screenView->_pitch;
+ int16 x = _mainView->_normal._dstLeft;
+ int16 y = _mainView->_normal._dstTop;
+ byte *scr = _vm->_screenView->_bufferPtr;
+ scr += (y + 16) * ww + x;
+ for (int16 i = 0; i < 16; i++) {
+ p = pattern[i];
+ r27 = p % 4 + p / 4 * ww;
+ for (int16 j = 0; j < 320 * 160 / 16; j++)
+ scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] = 0;
+ CLBlitter_UpdateScreen();
+ wait(1);
+ }
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+ byte *pix = _mainView->_bufferPtr;
+ x = _mainView->_normal._dstLeft;
+ y = _mainView->_normal._dstTop;
+ pix += 640 * 16;
+ scr = _vm->_screenView->_bufferPtr;
+ scr += (y + 16) * ww + x;
+ for (int16 i = 0; i < 16; i++) {
+ p = pattern[i];
+ r25 = p % 4 + p / 4 * 640;
+ r27 = p % 4 + p / 4 * ww;
+ for (int16 j = 0; j < 320 * 160 / 16; j++)
+ scr[j / (320 / 4) * ww * 4 + j % (320 / 4) * 4 + r27] =
+ pix[j / (320 / 4) * 640 * 4 + j % (320 / 4) * 4 + r25];
+ CLBlitter_UpdateScreen();
+ wait(1);
+ }
+}
+
+void EdenGame::fadeToBlack(int delay) {
+ CLPalette_GetLastPalette(oldPalette);
+ for (int16 i = 0; i < 6; i++) {
+ for (int16 j = 0; j < 256; j++) {
+ newColor.r = oldPalette[j].r >> i;
+ newColor.g = oldPalette[j].g >> i;
+ newColor.b = oldPalette[j].b >> i;
+ CLPalette_SetRGBColor(newPalette, j, &newColor);
+ }
+ CLPalette_Send2Screen(newPalette, 0, 256);
+ wait(delay);
+ }
+}
+
+// Original name: fadetoblack128
+void EdenGame::fadeToBlackLowPalette(int delay) {
+ CLPalette_GetLastPalette(oldPalette);
+ for (int16 i = 0; i < 6; i++) {
+ for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128?
+ newColor.r = oldPalette[j].r >> i;
+ newColor.g = oldPalette[j].g >> i;
+ newColor.b = oldPalette[j].b >> i;
+ CLPalette_SetRGBColor(newPalette, j, &newColor);
+ }
+ CLPalette_Send2Screen(newPalette, 0, 128);
+ wait(delay);
+ }
+}
+
+// Original name: fadefromblack128
+void EdenGame::fadeFromBlackLowPalette(int delay) {
+ for (int16 i = 0; i < 6; i++) {
+ for (int16 j = 0; j < 129; j++) { //CHECKME: Should be 128?
+ newColor.r = _globalPalette[j].r >> (5 - i);
+ newColor.g = _globalPalette[j].g >> (5 - i);
+ newColor.b = _globalPalette[j].b >> (5 - i);
+ CLPalette_SetRGBColor(newPalette, j, &newColor);
+ }
+ CLPalette_Send2Screen(newPalette, 0, 128);
+ wait(delay);
+ }
+}
+
+// Original name: rectanglenoir32
+void EdenGame::blackRect32() {
+ // blacken 32x32 rectangle
+ int *pix = (int *)_view2Buf;
+ for (int16 i = 0; i < 32; i++) {
+ pix[0] = 0;
+ pix[1] = 0;
+ pix[2] = 0;
+ pix[3] = 0;
+ pix[4] = 0;
+ pix[5] = 0;
+ pix[6] = 0;
+ pix[7] = 0;
+ pix += 32 / 4;
+ }
+}
+
+void EdenGame::setSrcRect(int16 sx, int16 sy, int16 ex, int16 ey) {
+ rect_src = Common::Rect(sx, sy, ex, ey);
+}
+
+void EdenGame::setDestRect(int16 sx, int16 sy, int16 ex, int16 ey) {
+ rect_dst = Common::Rect(sx, sy, ex, ey);
+}
+
+void EdenGame::effetpix() {
+ uint16 r25, r18, r31, r30; //TODO: change to xx/yy
+
+ uint16 ww = _vm->_screenView->_pitch;
+ r25 = ww * 80;
+ r18 = 640 * 80;
+ byte *pix = _mainView->_bufferPtr + 16 * 640;
+ int x = _mainView->_normal._dstLeft;
+ int y = _mainView->_normal._dstTop;
+ byte *scr = _vm->_screenView->_bufferPtr;
+ scr += (y + 16) * ww + x;
+ int16 r20 = 0x4400; //TODO
+ int16 r27 = 1;
+ int16 r26 = 0;
+ do {
+ char r8 = r27 & 1;
+ r27 >>= 1;
+ if (r8)
+ r27 ^= r20;
+ if (r27 < 320 * 80) {
+ r31 = r27 / 320;
+ r30 = r27 % 320;
+ scr[r31 * ww + r30] = 0;
+ scr[r31 * ww + r25 + r30] = 0;
+ if (++r26 == 960) {
+ CLBlitter_UpdateScreen();
+ wait(1);
+ r26 = 0;
+ }
+ }
+ } while (r27 != 1);
+ CLPalette_Send2Screen(_globalPalette, 0, 256);
+ r20 = 0x4400;
+ r27 = 1;
+ r26 = 0;
+ do {
+ char r8 = r27 & 1;
+ r27 >>= 1;
+ if (r8)
+ r27 ^= r20;
+ if (r27 < 320 * 80) {
+ r31 = r27 / 320;
+ r30 = r27 % 320;
+ byte p0 = pix[r31 * 640 + r30];
+ byte p1 = pix[r31 * 640 + r18 + r30];
+ scr[r31 * ww + r30] = p0;
+ scr[r31 * ww + r25 + r30] = p1;
+ if (++r26 == 960) {
+ CLBlitter_UpdateScreen();
+ wait(1);
+ r26 = 0;
+ }
+ }
+ } while (r27 != 1);
+ assert(_vm->_screenView->_pitch == 320);
+}
+
+////// film.c
+// Original name: showfilm
+void EdenGame::showMovie(char arg1) {
+ _vm->_video->readHeader();
+ if (_globals->_curVideoNum == 92) {
+ // _hnmContext->_header._unusedFlag2 = 0; CHECKME: Useless?
+ _hnmSoundChannel->setVolumeLeft(0);
+ _hnmSoundChannel->setVolumeRight(0);
+ }
+
+ if (_vm->_video->getVersion() != 4)
+ return;
+
+ bool playing = true;
+ _vm->_video->allocMemory();
+ _hnmView = new View(_vm->_video->_header._width, _vm->_video->_header._height);
+ _hnmView->setSrcZoomValues(0, 0);
+ _hnmView->setDisplayZoomValues(_vm->_video->_header._width * 2, _vm->_video->_header._height * 2);
+ _hnmView->centerIn(_vm->_screenView);
+ _hnmViewBuf = _hnmView->_bufferPtr;
+ if (arg1) {
+ _hnmView->_normal._height = 160;
+ _hnmView->_zoom._height = 320; //TODO: width??
+ _hnmView->_normal._dstTop = _mainView->_normal._dstTop + 16;
+ _hnmView->_zoom._dstTop = _mainView->_zoom._dstTop + 32;
+ }
+ _vm->_video->setFinalBuffer(_hnmView->_bufferPtr);
+ do {
+ _hnmFrameNum = _vm->_video->getFrameNum();
+ _vm->_video->waitLoop();
+ playing = _vm->_video->nextElement();
+ if (_specialTextMode)
+ handleHNMSubtitles();
+ else
+ musicspy();
+ CLBlitter_CopyView2Screen(_hnmView);
+ assert(_vm->_screenView->_pitch == 320);
+ _vm->pollEvents();
+
+ if (arg1) {
+ if (_vm->isMouseButtonDown()) {
+ if (!_mouseHeld) {
+ _mouseHeld = true;
+ _videoCanceledFlag = true;
+ }
+ }
+ else
+ _mouseHeld = false;
+ }
+ } while (playing && !_videoCanceledFlag);
+ delete _hnmView;
+ _vm->_video->deallocMemory();
+}
+
+void EdenGame::playHNM(int16 num) {
+ perso_t *perso = nullptr;
+ int16 oldDialogType = -1;
+ _globals->_curVideoNum = num;
+ if (num != 2001 && num != 2012 && num != 98 && num != 171) {
+ byte oldMusicType = _globals->_newMusicType;
+ _globals->_newMusicType = MusicType::mtEvent;
+ musique();
+ musicspy();
+ _globals->_newMusicType = oldMusicType;
+ }
+ _globals->_videoSubtitleIndex = 1;
+ if (_specialTextMode) {
+ perso = _globals->_characterPtr;
+ oldDialogType = _globals->_dialogType;
+ preloadDialogs(num);
+ fademusica0(1);
+ _musicChannel->stop();
+ }
+ _showVideoSubtitle = false;
+ _videoCanceledFlag = false;
+ loadHnm(num);
+ _vm->_video->reset();
+ if (_needToFade) {
+ fadeToBlack(4);
+ clearScreen();
+ _needToFade = false;
+ }
+ if (num == 2012 || num == 98 || num == 171)
+ showMovie(0);
+ else
+ showMovie(1);
+ _cursKeepPos = Common::Point(-1, -1);
+ if (_specialTextMode) {
+ _musicFadeFlag = 3;
+ musicspy();
+ _globals->_characterPtr = perso;
+ _globals->_dialogType = oldDialogType;
+ _specialTextMode = false;
+ }
+ if (_videoCanceledFlag)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+ if (_globals->_curVideoNum == 167)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+ if (_globals->_curVideoNum == 104)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+ if (_globals->_curVideoNum == 102)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+ if (_globals->_curVideoNum == 77)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+ if (_globals->_curVideoNum == 149)
+ _globals->_varF1 = RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01;
+}
+
+// Original name bullehnm
+void EdenGame::handleHNMSubtitles() {
+#define SUB_LINE(start, end) \
+ (start), (end) | 0x8000
+
+ static uint16 kFramesVid170[] = {
+ SUB_LINE(68, 120),
+ SUB_LINE(123, 196),
+ SUB_LINE(199, 274),
+ SUB_LINE(276, 370),
+ SUB_LINE(799, 885),
+ SUB_LINE(888, 940),
+ SUB_LINE(947, 1000),
+ SUB_LINE(1319, 1378),
+ SUB_LINE(1380, 1440),
+ SUB_LINE(1854, 1898),
+ SUB_LINE(1900, 1960),
+ SUB_LINE(2116, 2184),
+ SUB_LINE(2186, 2252),
+ SUB_LINE(2254, 2320),
+ SUB_LINE(3038, 3094),
+ SUB_LINE(3096, 3160),
+ 0xFFFF
+ };
+
+ static uint16 kFramesVid83[] = {
+ SUB_LINE(99, 155),
+ SUB_LINE(157, 256),
+ 0xFFFF
+ };
+
+ static uint16 kFramesVid88[] = {
+ SUB_LINE(106, 173),
+ SUB_LINE(175, 244),
+ SUB_LINE(246, 350),
+ SUB_LINE(352, 467),
+ 0xFFFF
+ };
+
+ static uint16 kFramesVid89[] = {
+ SUB_LINE(126, 176),
+ SUB_LINE(178, 267),
+ SUB_LINE(269, 342),
+ SUB_LINE(344, 398),
+ SUB_LINE(400, 458),
+ SUB_LINE(460, 558),
+ 0xFFFF
+ };
+
+ static uint16 kFramesVid94[] = {
+ SUB_LINE(101, 213),
+ SUB_LINE(215, 353),
+ SUB_LINE(355, 455),
+ SUB_LINE(457, 518),
+ SUB_LINE(520, 660),
+ SUB_LINE(662, 768),
+ 0xFFFF
+ };
+
+#undef SUB_LINE
+
+ uint16 *frames;
+ perso_t *perso;
+ switch (_globals->_curVideoNum) {
+ case 170:
+ frames = kFramesVid170;
+ perso = &_persons[PER_UNKN_156];
+ break;
+ case 83:
+ frames = kFramesVid83;
+ perso = &_persons[PER_MORKUS];
+ break;
+ case 88:
+ frames = kFramesVid88;
+ perso = &_persons[PER_MORKUS];
+ break;
+ case 89:
+ frames = kFramesVid89;
+ perso = &_persons[PER_MORKUS];
+ break;
+ case 94:
+ frames = kFramesVid94;
+ perso = &_persons[PER_MORKUS];
+ break;
+ default:
+ return;
+ }
+ uint16 *frames_start = frames;
+ uint16 frame;
+ while ((frame = *frames++) != 0xFFFF) {
+ if ((frame & ~0x8000) == _hnmFrameNum)
+ break;
+ }
+ if (frame == 0xFFFF) {
+ if (_showVideoSubtitle)
+ displayHNMSubtitle();
+ return;
+ }
+ if (frame & 0x8000)
+ _showVideoSubtitle = false;
+ else {
+ _globals->_videoSubtitleIndex = (frames - frames_start) / 2 + 1;
+ _globals->_characterPtr = perso;
+ _globals->_dialogType = DialogType::dtInspect;
+ int16 num = (perso->_id << 3) | _globals->_dialogType;
+ dialoscansvmas((Dialog *)getElem(_gameDialogs, num));
+ _showVideoSubtitle = true;
+ }
+ if (_showVideoSubtitle)
+ displayHNMSubtitle();
+}
+
+} // namespace Cryo
diff --git a/engines/cryo/module.mk b/engines/cryo/module.mk
new file mode 100644
index 0000000000..1fcb0ae6fd
--- /dev/null
+++ b/engines/cryo/module.mk
@@ -0,0 +1,20 @@
+MODULE := engines/cryo
+
+MODULE_OBJS = \
+ cryo.o \
+ cryolib.o \
+ debugger.o \
+ detection.o \
+ eden.o \
+ graphics.o \
+ resource.o \
+ sound.o \
+ video.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_CRYO), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/cryo/platdefs.h b/engines/cryo/platdefs.h
new file mode 100644
index 0000000000..69f8e625ea
--- /dev/null
+++ b/engines/cryo/platdefs.h
@@ -0,0 +1,43 @@
+/* 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.
+ *
+ */
+
+#ifndef CRYO_PLATDEFS_H
+#define CRYO_PLATDEFS_H
+
+namespace Cryo {
+
+#if 1
+const int _subtitlesXMargin = 16; //PC
+const int _subtitlesXScrMargin = 16;
+const int _spaceWidth = 6;
+#define FAKE_DOS_VERSION
+#else
+const int _subtitlesXMargin = 16; //MAC
+const int _subtitlesXScrMargin = 16; //MAC
+const int _spaceWidth = 4;
+#endif
+const int _subtitlesXWidth = (320 - _subtitlesXMargin * 2);
+const int _subtitlesXCenter = _subtitlesXWidth / 2;
+
+} // End of namespace Cryo
+
+#endif
diff --git a/engines/cryo/resource.cpp b/engines/cryo/resource.cpp
new file mode 100644
index 0000000000..7698de0906
--- /dev/null
+++ b/engines/cryo/resource.cpp
@@ -0,0 +1,555 @@
+/* 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.
+ *
+ */
+
+#include "cryo/defs.h"
+#include "cryo/cryo.h"
+#include "cryo/platdefs.h"
+#include "cryo/cryolib.h"
+#include "cryo/eden.h"
+#include "cryo/sound.h"
+
+namespace Cryo {
+
+#define CRYO_DAT_VER 1 // 32-bit integer
+
+// Original name: prechargephrases
+void EdenGame::preloadDialogs(int16 vid) {
+ perso_t *perso = &_persons[PER_MORKUS];
+ if (vid == 170)
+ perso = &_persons[PER_UNKN_156];
+ _globals->_characterPtr = perso;
+ _globals->_dialogType = DialogType::dtInspect;
+ int num = (perso->_id << 3) | _globals->_dialogType;
+ Dialog *dial = (Dialog *)getElem(_gameDialogs, num);
+ dialoscansvmas(dial);
+}
+
+////// datfile.c
+void EdenGame::verifh(byte *ptr) {
+ byte sum = 0;
+ byte *head = ptr;
+
+ for (int8 i = 0; i < 6; i++)
+ sum += *head++;
+
+ if (sum != 0xAB)
+ return;
+
+ debug("* Begin unpacking resource");
+ head -= 6;
+ uint16 h0 = READ_LE_UINT16(head);
+ // 3 = 2 bytes for the uint16 and 1 byte for an unused char
+ head += 3;
+ uint16 h3 = READ_LE_UINT16(head);
+ head += 2;
+ byte *data = h0 + head + 26;
+ h3 -= 6;
+ head += h3;
+ for (; h3; h3--)
+ *data-- = *head--;
+ head = data + 1;
+ data = ptr;
+ expandHSQ(head, data);
+}
+
+void EdenGame::openbigfile() {
+ _bigfile.open("EDEN.DAT");
+
+ char buf[16];
+ int count = _bigfile.readUint16LE();
+ _bigfileHeader = new PakHeaderNode(count);
+ for (int j = 0; j < count; j++) {
+ for (int k = 0; k < 16; k++)
+ buf[k] = _bigfile.readByte();
+ _bigfileHeader->_files[j]._name = Common::String(buf);
+ _bigfileHeader->_files[j]._size = _bigfile.readUint32LE();
+ _bigfileHeader->_files[j]._offs = _bigfile.readUint32LE();
+ _bigfileHeader->_files[j]._flag = _bigfile.readByte();
+ }
+
+ _vm->_video->resetInternals();
+ _vm->_video->setFile(&_bigfile);
+}
+
+void EdenGame::closebigfile() {
+ _bigfile.close();
+}
+
+int EdenGame::loadmusicfile(int16 num) {
+ PakHeaderItem *file = &_bigfileHeader->_files[num + 435];
+ int32 size = file->_size;
+ int32 offs = file->_offs;
+ _bigfile.seek(offs, SEEK_SET);
+ uint32 numread = size;
+ if (numread > kMaxMusicSize)
+ error("Music file %s is too big", file->_name.c_str());
+ _bigfile.read(_musicBuf, numread);
+ return size;
+}
+
+void EdenGame::loadRawFile(uint16 num, byte *buffer) {
+ if (_vm->getPlatform() == Common::kPlatformDOS) {
+ if ((_vm->isDemo() && num > 2204) || num > 2472)
+ error("Trying to read invalid game resource");
+ }
+
+ assert(num < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[num];
+ int32 size = file->_size;
+ int32 offs = file->_offs;
+
+ _bigfile.seek(offs, SEEK_SET);
+ _bigfile.read(buffer, size);
+}
+
+void EdenGame::loadIconFile(uint16 num, Icon *buffer) {
+ if (_vm->getPlatform() == Common::kPlatformDOS) {
+ if ((_vm->isDemo() && num > 2204) || num > 2472)
+ error("Trying to read invalid game resource");
+ }
+
+ assert(num < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[num];
+ int32 size = file->_size;
+ int32 offs = file->_offs;
+ debug("* Loading icon - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size);
+ _bigfile.seek(offs, SEEK_SET);
+
+ int count = size / 18; // sizeof(Icon)
+ for (int i = 0; i < count; i++) {
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ buffer[i].sx = _bigfile.readSint16BE();
+ buffer[i].sy = _bigfile.readSint16BE();
+ buffer[i].ex = _bigfile.readSint16BE();
+ buffer[i].ey = _bigfile.readSint16BE();
+ buffer[i]._cursorId = _bigfile.readUint16BE();;
+ buffer[i]._actionId = _bigfile.readUint32BE();;
+ buffer[i]._objectId = _bigfile.readUint32BE();;
+ }
+ else {
+ buffer[i].sx = _bigfile.readSint16LE();
+ buffer[i].sy = _bigfile.readSint16LE();
+ buffer[i].ex = _bigfile.readSint16LE();
+ buffer[i].ey = _bigfile.readSint16LE();
+ buffer[i]._cursorId = _bigfile.readUint16LE();;
+ buffer[i]._actionId = _bigfile.readUint32LE();;
+ buffer[i]._objectId = _bigfile.readUint32LE();;
+ }
+ }
+}
+
+void EdenGame::loadRoomFile(uint16 num, Room *buffer) {
+ if (_vm->getPlatform() == Common::kPlatformDOS) {
+ if ((_vm->isDemo() && num > 2204) || num > 2472)
+ error("Trying to read invalid game resource");
+ }
+
+ assert(num < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[num];
+ int32 size = file->_size;
+ int32 offs = file->_offs;
+ debug("* Loading room - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size);
+ _bigfile.seek(offs, SEEK_SET);
+
+ int count = size / 14; // sizeof(Room)
+ for (int i = 0; i < count; i++) {
+ buffer[i]._id = _bigfile.readByte();
+ for (int j = 0; j < 4; j++)
+ buffer[i]._exits[j] = _bigfile.readByte();
+ buffer[i]._flags = _bigfile.readByte();
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ buffer[i]._bank = _bigfile.readUint16BE();
+ buffer[i]._party = _bigfile.readUint16BE();
+ }
+ else {
+ buffer[i]._bank = _bigfile.readUint16LE();
+ buffer[i]._party = _bigfile.readUint16LE();
+ }
+ buffer[i]._level = _bigfile.readByte();
+ buffer[i]._video = _bigfile.readByte();
+ buffer[i]._location = _bigfile.readByte();
+ buffer[i]._backgroundBankNum = _bigfile.readByte();
+ }
+}
+
+// Original name: shnmfl
+void EdenGame::loadHnm(uint16 num) {
+ unsigned int resNum = num - 1 + 485;
+ assert(resNum < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[resNum];
+ int size = file->_size;
+ int offs = file->_offs;
+ debug("* Loading movie %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size);
+ _vm->_video->_file->seek(offs, SEEK_SET);
+}
+
+// Original name: ssndfl
+int EdenGame::loadSound(uint16 num) {
+ unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661);
+ assert(resNum < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[resNum];
+ int32 size = file->_size;
+ int32 offs = file->_offs;
+ debug("* Loading sound %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size);
+ if (_soundAllocated) {
+ free(_voiceSamplesBuffer);
+ _voiceSamplesBuffer = nullptr;
+ _soundAllocated = false; //TODO: bug??? no alloc
+ }
+ else {
+ _voiceSamplesBuffer = (byte *)malloc(size);
+ _soundAllocated = true;
+ }
+
+ _bigfile.seek(offs, SEEK_SET);
+ //For PC loaded data is a VOC file, on Mac version this is a raw samples
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _bigfile.read(_voiceSamplesBuffer, size);
+ else {
+ // VOC files also include extra information for lipsync
+ // 1. Standard VOC header
+ _bigfile.read(_voiceSamplesBuffer, 0x1A);
+
+ // 2. Lipsync?
+ unsigned char chunkType = _bigfile.readByte();
+
+ uint32 val = 0;
+ _bigfile.read(&val, 3);
+ unsigned int chunkLen = LE32(val);
+
+ if (chunkType == 5) {
+ _bigfile.read(_gameLipsync + 7260, chunkLen);
+ chunkType = _bigfile.readByte();
+ _bigfile.read(&val, 3);
+ chunkLen = LE32(val);
+ }
+
+ // 3. Normal sound data
+ if (chunkType == 1) {
+ _bigfile.readUint16LE();
+ size = chunkLen - 2;
+ _bigfile.read(_voiceSamplesBuffer, size);
+ }
+ }
+
+ return size;
+}
+
+void EdenGame::convertMacToPC() {
+ // Convert all mac (big-endian) resources to native format
+ // Array of longs
+ int *p = (int *)_gameLipsync;
+ for (int i = 0; i < 7240 / 4; i++)
+ p[i] = BE32(p[i]);
+}
+
+void EdenGame::loadpermfiles() {
+ Common::File f;
+ const int kNumIcons = 136;
+ const int kNumRooms = 424;
+ const int kNumFollowers = 15;
+ const int kNumLabyrinthPath = 70;
+ const int kNumDinoSpeedForCitaLevel = 16;
+ const int kNumTabletView = 12;
+ const int kNumPersoRoomBankTable = 84;
+ const int kNumGotos = 130;
+ const int kNumObjects = 42;
+ const int kNumObjectLocations = 45;
+ const int kNumPersons = 58;
+ const int kNumCitadel = 7;
+ const int kNumCharacterRects = 19;
+ const int kNumCharacters = 20;
+ const int kNumAreas = 12;
+ // tab_2CEF0
+ // tab_2CF70
+ const int kNumActionCursors = 299;
+
+ const int expectedDataSize =
+ kNumIcons * 18 + // sizeof(Icon)
+ kNumRooms * 14 + // sizeof(Room)
+ kNumFollowers * 16 + // sizeof(Follower)
+ kNumLabyrinthPath +
+ kNumDinoSpeedForCitaLevel +
+ kNumTabletView +
+ kNumPersoRoomBankTable +
+ kNumGotos * 5 + // sizeof(Goto)
+ kNumObjects * 12 + // sizeof(object_t)
+ kNumObjectLocations * 2 +
+ kNumPersons * 18 + // sizeof(perso_t)
+ kNumCitadel * 34 + // sizeof(Citadel)
+ kNumCharacterRects * 8 +
+ kNumCharacters * 5 +
+ kNumAreas * 10 + // (sizeof(Area) - 4)
+ 64 * 2 +
+ 64 * 2 +
+ kNumActionCursors +
+ 12 +
+ 3 * 6 * 2 * 3 * 2;
+
+ if (f.open("cryo.dat")) {
+ const int dataSize = f.size() - 8 - 4; // CRYODATA + version
+ char headerId[9];
+
+ f.read(headerId, 8);
+ headerId[8] = '\0';
+ if (strcmp(headerId, "CRYODATA"))
+ error("Invalid cryo.dat aux data file");
+
+ if (f.readUint32LE() != CRYO_DAT_VER)
+ error("Incorrect data version for cryo.dat");
+
+ if (dataSize != expectedDataSize)
+ error("Mismatching data in cryo.dat aux data file (got %d, expected %d)", dataSize, expectedDataSize);
+ }
+ else
+ error("Can not load cryo.dat");
+
+ switch (_vm->getPlatform()) {
+ case Common::kPlatformDOS:
+ // Since PC version stores hotspots and rooms info in the executable, load them from premade resource file
+ for (int i = 0; i < kNumIcons; i++) {
+ _gameIcons[i].sx = f.readSint16LE();
+ _gameIcons[i].sy = f.readSint16LE();
+ _gameIcons[i].ex = f.readSint16LE();
+ _gameIcons[i].ey = f.readSint16LE();
+ _gameIcons[i]._cursorId = f.readUint16LE();
+ _gameIcons[i]._actionId = f.readUint32LE();
+ _gameIcons[i]._objectId = f.readUint32LE();
+ }
+
+ for (int i = 0; i < kNumRooms; i++) {
+ _gameRooms[i]._id = f.readByte();
+ for (int j = 0; j < 4; j++)
+ _gameRooms[i]._exits[j] = f.readByte();
+ _gameRooms[i]._flags = f.readByte();
+ _gameRooms[i]._bank = f.readUint16LE();
+ _gameRooms[i]._party = f.readUint16LE();
+ _gameRooms[i]._level = f.readByte();
+ _gameRooms[i]._video = f.readByte();
+ _gameRooms[i]._location = f.readByte();
+ _gameRooms[i]._backgroundBankNum = f.readByte();
+ }
+ break;
+ case Common::kPlatformMacintosh:
+ loadIconFile(2498, _gameIcons);
+ loadRoomFile(2497, _gameRooms);
+ loadRawFile(2486, _gameLipsync);
+ convertMacToPC();
+
+ // Skip the icons and rooms of the DOS version
+ f.skip(kNumIcons * 14 + kNumRooms * 11);
+ break;
+ default:
+ error("Unsupported platform");
+ }
+
+ // Read the common static data
+
+ for (int i = 0; i < kNumFollowers; i++) {
+ _followerList[i]._id = f.readSByte();
+ _followerList[i]._spriteNum = f.readSByte();
+ _followerList[i].sx = f.readSint16LE();
+ _followerList[i].sy = f.readSint16LE();
+ _followerList[i].ex = f.readSint16LE();
+ _followerList[i].ey = f.readSint16LE();
+ _followerList[i]._spriteBank = f.readSint16LE();
+ _followerList[i].ff_C = f.readSint16LE();
+ _followerList[i].ff_E = f.readSint16LE();
+ }
+
+ f.read(_labyrinthPath, kNumLabyrinthPath);
+ f.read(_dinoSpeedForCitadelLevel, kNumDinoSpeedForCitaLevel);
+ f.read(_tabletView, kNumTabletView);
+ f.read(_personRoomBankTable, kNumPersoRoomBankTable);
+ f.read(_gotos, kNumGotos * 5); // sizeof(Goto)
+
+ for (int i = 0; i < kNumObjects; i++) {
+ _objects[i]._id = f.readByte();
+ _objects[i]._flags = f.readByte();
+ _objects[i]._locations = f.readUint32LE();
+ _objects[i]._itemMask = f.readUint16LE();
+ _objects[i]._powerMask = f.readUint16LE();
+ _objects[i]._count = f.readSint16LE();
+ }
+
+ for (int i = 0; i < kNumObjectLocations; i++) {
+ _objectLocations[i] = f.readUint16LE();
+ }
+
+ for (int i = 0; i < kNumPersons; i++) {
+ _persons[i]._roomNum = f.readUint16LE();
+ _persons[i]._actionId = f.readUint16LE();
+ _persons[i]._partyMask = f.readUint16LE();
+ _persons[i]._id = f.readByte();
+ _persons[i]._flags = f.readByte();
+ _persons[i]._roomBankId = f.readByte();
+ _persons[i]._spriteBank = f.readByte();
+ _persons[i]._items = f.readUint16LE();
+ _persons[i]._powers = f.readUint16LE();
+ _persons[i]._targetLoc = f.readByte();
+ _persons[i]._lastLoc = f.readByte();
+ _persons[i]._speed = f.readByte();
+ _persons[i]._steps = f.readByte();
+ }
+
+ for (int i = 0; i < kNumCitadel; i++) {
+ _citadelList[i]._id = f.readSint16LE();
+ for (int j = 0; j < 8; j++)
+ _citadelList[i]._bank[j] = f.readSint16LE();
+ for (int j = 0; j < 8; j++)
+ _citadelList[i]._video[j] = f.readSint16LE();
+ }
+
+ for (int i = 0; i < kNumCharacterRects; i++) {
+ _characterRects[i].left = f.readSint16LE();
+ _characterRects[i].top = f.readSint16LE();
+ _characterRects[i].right = f.readSint16LE();
+ _characterRects[i].bottom = f.readSint16LE();
+ }
+
+ f.read(_characterArray, kNumCharacters * 5);
+
+ for (int i = 0; i < kNumAreas; i++) {
+ _areasTable[i]._num = f.readByte();
+ _areasTable[i]._type = f.readByte();
+ _areasTable[i]._flags = f.readUint16LE();
+ _areasTable[i]._firstRoomIdx = f.readUint16LE();
+ _areasTable[i]._citadelLevel = f.readByte();
+ _areasTable[i]._placeNum = f.readByte();
+ _areasTable[i]._citadelRoomPtr = nullptr;
+ _areasTable[i]._visitCount = f.readSint16LE();
+ }
+
+ for (int i = 0; i < 64; i++) {
+ tab_2CEF0[i] = f.readSint16LE();
+ }
+
+ for (int i = 0; i < 64; i++) {
+ tab_2CF70[i] = f.readSint16LE();
+ }
+
+ f.read(_actionCursors, kNumActionCursors);
+ f.read(_mapMode, 12);
+ f.read(_cubeTextureCoords, 3 * 6 * 2 * 3 * 2);
+
+ f.close();
+
+ loadRawFile(0, _mainBankBuf);
+ loadRawFile(402, _gameFont);
+ loadRawFile(404, _gameDialogs);
+ loadRawFile(403, _gameConditions);
+}
+
+bool EdenGame::ReadDataSyncVOC(unsigned int num) {
+ unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661);
+ unsigned char vocHeader[0x1A];
+ int filePos = 0;
+ loadpartoffile(resNum, vocHeader, filePos, sizeof(vocHeader));
+ filePos += sizeof(vocHeader);
+ unsigned char chunkType = 0;
+ loadpartoffile(resNum, &chunkType, sizeof(vocHeader), 1);
+ filePos++;
+ if (chunkType == 5) {
+ uint32 chunkLen = 0;
+ loadpartoffile(resNum, &chunkLen, filePos, 3);
+ filePos += 3;
+ chunkLen = LE32(chunkLen);
+ loadpartoffile(resNum, _gameLipsync + 7260, filePos, chunkLen);
+ return true;
+ }
+ return false;
+}
+
+bool EdenGame::ReadDataSync(uint16 num) {
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ long pos = READ_LE_UINT32(_gameLipsync + num * 4);
+ if (pos != -1) {
+ long len = 1024;
+ loadpartoffile(1936, _gameLipsync + 7260, pos, len);
+ return true;
+ }
+ }
+ else
+ return ReadDataSyncVOC(num + 1); //TODO: remove -1 in caller
+ return false;
+}
+
+void EdenGame::loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len) {
+ assert(num < _bigfileHeader->_count);
+ PakHeaderItem *file = &_bigfileHeader->_files[num];
+ int32 offs = READ_LE_UINT32(&file->_offs);
+ debug("* Loading partial resource %d (%s) at 0x%X(+0x%X), %d bytes", num, file->_name.c_str(), offs, pos, len);
+ _bigfile.seek(offs + pos, SEEK_SET);
+ _bigfile.read(buffer, len);
+}
+
+void EdenGame::expandHSQ(byte *input, byte *output) {
+ byte *src = input;
+ byte *dst = output;
+ byte *ptr;
+ uint16 bit; // bit
+ uint16 queue = 0; // queue
+ uint16 len = 0;
+ int16 ofs;
+#define GetBit \
+bit = queue & 1; \
+queue >>= 1; \
+if (!queue) { \
+ queue = (src[1] << 8) | src[0]; src += 2; \
+ bit = queue & 1; \
+ queue = (queue >> 1) | 0x8000; \
+ }
+
+ for (;;) {
+ GetBit;
+ if (bit)
+ *dst++ = *src++;
+ else {
+ len = 0;
+ GetBit;
+ if (!bit) {
+ GetBit;
+ len = (len << 1) | bit;
+ GetBit;
+ len = (len << 1) | bit;
+ ofs = 0xFF00 | *src++; //TODO: -256
+ }
+ else {
+ ofs = (src[1] << 8) | src[0];
+ src += 2;
+ len = ofs & 7;
+ ofs = (ofs >> 3) | 0xE000;
+ if (!len) {
+ len = *src++;
+ if (!len)
+ break;
+ }
+ }
+ ptr = dst + ofs;
+ len += 2;
+ while (len--)
+ *dst++ = *ptr++;
+ }
+ }
+}
+
+} // namespace Cryo
diff --git a/engines/cryo/sound.cpp b/engines/cryo/sound.cpp
new file mode 100644
index 0000000000..68f067588f
--- /dev/null
+++ b/engines/cryo/sound.cpp
@@ -0,0 +1,113 @@
+/* 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.
+ *
+ */
+
+#include "cryo/sound.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+namespace Cryo {
+
+CSoundChannel::CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits) : _mixer(mixer), _sampleRate(sampleRate), _stereo(stereo) {
+ _bufferFlags = is16bits ? (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS) : Audio::FLAG_UNSIGNED;
+ if (stereo)
+ _bufferFlags |= Audio::FLAG_STEREO;
+ _audioStream = nullptr;
+ _volumeLeft = _volumeRight = Audio::Mixer::kMaxChannelVolume;
+}
+
+CSoundChannel::~CSoundChannel() {
+ stop();
+ if (_audioStream)
+ delete _audioStream;
+}
+
+void CSoundChannel::queueBuffer(byte *buffer, unsigned int size, bool playNow, bool playQueue, bool buffering) {
+ if (playNow)
+ stop();
+
+ if (!buffer || !size)
+ return;
+
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(_sampleRate, _stereo);
+
+ if (buffering) {
+ byte *localBuffer = (byte*)malloc(size);
+ memcpy(localBuffer, buffer, size);
+ _audioStream->queueBuffer(localBuffer, size, DisposeAfterUse::YES, _bufferFlags);
+ } else
+ _audioStream->queueBuffer(buffer, size, DisposeAfterUse::NO, _bufferFlags);
+ if (playNow || playQueue)
+ play();
+}
+
+void CSoundChannel::play() {
+ if (!_audioStream)
+ return;
+ if (!_mixer->isSoundHandleActive(_soundHandle)) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ applyVolumeChange();
+ }
+}
+
+void CSoundChannel::stop() {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+
+ if (_audioStream) {
+ _audioStream->finish();
+ delete _audioStream;
+ _audioStream = nullptr;
+ }
+}
+
+unsigned int CSoundChannel::numQueued() {
+ return _audioStream ? _audioStream->numQueuedStreams() : 0;
+}
+
+unsigned int CSoundChannel::getVolume() {
+ return (_volumeRight + _volumeLeft) / 2;
+}
+
+void CSoundChannel::setVolume(unsigned int volumeLeft, unsigned int volumeRight) {
+ _volumeLeft = volumeLeft;
+ _volumeRight = volumeRight;
+ applyVolumeChange();
+}
+
+void CSoundChannel::setVolumeLeft(unsigned int volume) {
+ setVolume(volume, _volumeRight);
+}
+
+void CSoundChannel::setVolumeRight(unsigned int volume) {
+ setVolume(_volumeLeft, volume);
+}
+
+void CSoundChannel::applyVolumeChange() {
+ unsigned int volume = (_volumeRight + _volumeLeft) / 2;
+ int balance = (signed int)(_volumeRight - _volumeLeft) / 2;
+ _mixer->setChannelVolume(_soundHandle, volume);
+ _mixer->setChannelBalance(_soundHandle, balance);
+}
+
+}
diff --git a/engines/cryo/sound.h b/engines/cryo/sound.h
new file mode 100644
index 0000000000..72232cc4f1
--- /dev/null
+++ b/engines/cryo/sound.h
@@ -0,0 +1,70 @@
+/* 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.
+ *
+ */
+
+#pragma once
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+#include "cryo/cryolib.h"
+
+namespace Cryo {
+
+class CryoEngine;
+
+class CSoundChannel {
+private:
+ Audio::Mixer *_mixer;
+ Audio::QueuingAudioStream *_audioStream;
+ Audio::SoundHandle _soundHandle;
+ unsigned int _sampleRate;
+ bool _stereo;
+ unsigned int _bufferFlags;
+
+ void applyVolumeChange();
+
+public:
+ CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits = false);
+ ~CSoundChannel();
+
+ // Queue a new buffer, cancel any previously queued buffers if playNow is set
+ void queueBuffer(byte *buffer, unsigned int size, bool playNow = false, bool playQueue = true, bool buffering = true);
+
+ // Play any queued buffers
+ void play();
+
+ // Stop playing and purge play queue
+ void stop();
+
+ // How many buffers in queue (including currently playing one)
+ unsigned int numQueued();
+
+ // Volume control
+ int _volumeLeft, _volumeRight;
+ unsigned int getVolume();
+ void setVolume(unsigned int volumeLeft, unsigned int volumeRight);
+ void setVolumeLeft(unsigned int volume);
+ void setVolumeRight(unsigned int volume);
+};
+
+}
diff --git a/engines/cryo/video.cpp b/engines/cryo/video.cpp
new file mode 100644
index 0000000000..fe242425e5
--- /dev/null
+++ b/engines/cryo/video.cpp
@@ -0,0 +1,617 @@
+/* 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.
+ *
+ */
+
+#include "cryo/cryo.h"
+#include "cryo/video.h"
+
+namespace Cryo {
+HnmPlayer::HnmPlayer(CryoEngine *vm) : _vm(vm) {
+ _soundStarted = false;
+ _pendingSounds = 0;
+ _timeDrift = 0.0;
+ _nextFrameTime = 0.0;
+ _expectedFrameTime = 0.0;
+ _rate = 0.0;
+ _useSoundSync = false;
+ _useSound = true;
+ _soundChannel = nullptr;
+ _prevRight = _prevLeft = 0;
+ _useAdpcm = false;
+ _customChunkHandler = nullptr;
+ _preserveColor0 = false;
+ _safePalette = false;
+
+ for (int i = 0; i < 256; i++)
+ decompTable[i] = 0;
+}
+
+// Original name: CLHNM_New
+void HnmPlayer::resetInternals() {
+ _frameNum = 0;
+ _file = nullptr;
+ _tmpBuffer[0] = nullptr;
+ _tmpBuffer[1] = nullptr;
+ _finalBuffer = nullptr;
+ _readBuffer = nullptr;
+ for (int i = 0; i < 256; i++) {
+ _palette[i].a = 0;
+ _palette[i].r = 0;
+ _palette[i].g = 0;
+ _palette[i].b = 0;
+ }
+}
+
+// Original name: CLHNM_SetFile
+void HnmPlayer::setFile(Common::File *file) {
+ _file = file;
+}
+
+// Original name: CLHNM_SetupTimer
+void HnmPlayer::setupTimer(float rate) {
+ _rate = 100.0 / rate;
+}
+
+// Original name: CLHNM_ResetInternalTimer
+void HnmPlayer::resetInternalTimer() {
+ _timeDrift = 0.0;
+ _nextFrameTime = _expectedFrameTime = _vm->_timerTicks;
+}
+
+// Original name: CLHNM_Reset
+void HnmPlayer::reset() {
+ _frameNum = 0;
+ _soundStarted = false;
+ _pendingSounds = 0;
+ resetInternalTimer();
+}
+
+// Original name: CLHNM_Init
+void HnmPlayer::init() {
+ _customChunkHandler = nullptr;
+ _preserveColor0 = false;
+ _useSound = true;
+}
+
+// Original name: CLHNM_SetForceZero2Black
+void HnmPlayer::setForceZero2Black(bool forceblack) {
+ _preserveColor0 = forceblack;
+}
+
+// Original name: CLHNM_WaitLoop
+void HnmPlayer::waitLoop() {
+ _expectedFrameTime += _rate;
+ _nextFrameTime = _expectedFrameTime - _timeDrift;
+ if (_useSoundSync && _vm->_timerTicks > 1000.0 + _nextFrameTime)
+ _useSound = false;
+ while (_vm->_timerTicks < _nextFrameTime) ; // waste time
+ _timeDrift = _vm->_timerTicks - _nextFrameTime;
+}
+
+// Original name: CLHNM_WantsSound
+void HnmPlayer::wantsSound(bool sound) {
+ _useSound = sound;
+}
+
+// Original name: CLHNM_SetupSound
+void HnmPlayer::setupSound(unsigned int rate, bool stereo, bool is16bits) {
+ _soundChannel = new CSoundChannel(_vm->_mixer, rate, stereo, is16bits);
+}
+
+// Original name: CLHNM_CloseSound
+void HnmPlayer::closeSound() {
+ if (_soundChannel) {
+ _soundChannel->stop();
+ delete(_soundChannel);
+ _soundChannel = nullptr;
+ }
+}
+
+// Original name: CLHNM_LoadDecompTable
+void HnmPlayer::loadDecompTable(int16 *buffer) {
+ for (int16 i = 0; i < 256; i++) {
+ int16 e = *buffer++;
+ decompTable[i] = LE16(e);
+ }
+}
+
+// Original name: CLHNM_DecompADPCM
+void HnmPlayer::decompADPCM(byte *buffer, int16 *output, int size) {
+ int16 l = _prevLeft;
+ int16 r = _prevRight;
+ size &= ~1;
+ while (size--) {
+ *output++ = l += decompTable[*buffer++];
+ *output++ = r += decompTable[*buffer++];
+ if (l > 512 || r > 512)
+ error("decompADPCM - Unexpected values");
+ }
+ _prevLeft = l;
+ _prevRight = r;
+}
+
+// Original name: CLHNM_ReadHeader
+void HnmPlayer::readHeader() {
+ _header._signature = _file->readUint32BE();
+ _file->skip(4);
+ _header._width = _file->readUint16LE();
+ _header._height = _file->readUint16LE();
+ _file->skip(4);
+ _header._numbFrame = _file->readSint32LE();
+ _file->skip(8);
+ _header._bufferSize = _file->readSint32LE();
+ _file->skip(32);
+
+ _header._bufferSize += 4096; //TODO: checkme
+}
+
+// Original name: CLHNM_GetVersion
+int16 HnmPlayer::getVersion() {
+ if (_header._signature == MKTAG('H','N','M','4'))
+ return 4;
+ return -1;
+}
+
+// Original name: CLHNM_AllocMemory
+void HnmPlayer::allocMemory() {
+// TODO: rework this code
+ _tmpBuffer[0] = (byte *)malloc(_header._bufferSize + 2);
+
+ if (!_tmpBuffer[0])
+ return;
+
+ _tmpBuffer[1] = (byte *)malloc(_header._bufferSize + 2);
+
+ if (!_tmpBuffer[1]) {
+ free(_tmpBuffer[0]);
+ _tmpBuffer[0] = nullptr;
+ return;
+ }
+
+ _readBuffer = (byte *)malloc(_header._bufferSize + 2);
+ if (!_readBuffer) {
+ free(_tmpBuffer[0]);
+ _tmpBuffer[0] = nullptr;
+ free(_tmpBuffer[1]);
+ _tmpBuffer[1] = nullptr;
+ }
+}
+
+// Original name: CLHNM_DeallocMemory
+void HnmPlayer::deallocMemory() {
+ free(_tmpBuffer[0]);
+ free(_tmpBuffer[1]);
+ free(_readBuffer);
+
+ _tmpBuffer[0] = nullptr;
+ _tmpBuffer[1] = nullptr;
+ _readBuffer = nullptr;
+}
+
+// Original name: CLHNM_SetFinalBuffer
+void HnmPlayer::setFinalBuffer(byte *buffer) {
+ _finalBuffer = buffer;
+}
+
+// Original name: CLHNM_GetFrameNum
+int HnmPlayer::getFrameNum() {
+ return _frameNum;
+}
+
+// Original name: CLHNM_TryRead
+void HnmPlayer::tryRead(int size) {
+ _file->read(_readBuffer, size);
+}
+
+// Original name: CLHNM_LoadFrame
+bool HnmPlayer::loadFrame() {
+ tryRead(4);
+ int chunk = *(int *)_readBuffer;
+ chunk = LE32(chunk);
+ chunk &= 0xFFFFFF; // upper bit - keyframe mark?
+ if (!chunk)
+ return false;
+
+ if (chunk - 4 > _header._bufferSize)
+ error("loadFrame - Chunk size");
+
+ tryRead(chunk - 4);
+ _dataPtr = _readBuffer;
+ return true;
+}
+
+// Original name CLHNM_DecompLempelZiv
+void HnmPlayer::decompLempelZiv(byte *buffer, byte *output) {
+ byte *inp = buffer;
+ byte *out = output;
+
+ unsigned int queue = 0;
+ int qpos = -1;
+
+ //TODO: fix for BE
+#define GetBit() ( 1 & ( (qpos >= 0) ? (queue >> qpos--) : (queue = *(unsigned int*)((inp += 4) - 4)) >> ((qpos = 30) + 1) ) )
+
+ for (;;) {
+ if (GetBit()) {
+ *out++ = *inp++;
+ } else {
+ int l, o;
+ if (GetBit()) {
+ l = *inp & 7;
+ o = *(uint16 *)inp >> 3;
+ inp += 2;
+ o -= 8192;
+ if (!l)
+ l = *inp++;
+ if (!l)
+ break;
+ } else {
+ l = GetBit() * 2;
+ l += GetBit();
+ o = *(inp++) - 256;
+ }
+ l += 2;
+ while (l--) {
+ *out = *(out + o);
+ out++;
+ }
+ }
+ }
+
+#undef GetBit
+
+ return;
+}
+
+// Original name: CLHNM_Desentrelace320
+void HnmPlayer::desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height) {
+ unsigned int *input = (unsigned int *)frame_buffer;
+ unsigned int *line0 = (unsigned int *)final_buffer;
+ unsigned int *line1 = (unsigned int *)(final_buffer + 320);
+ int count = (height) / 2;
+ while (count--) {
+ int16 i;
+ for (i = 0; i < 320 / 4; i++) {
+ unsigned int p0 = *input++;
+ unsigned int p4 = *input++;
+#if 0
+ *line0++ = ((p4 & 0xFF00) >> 8) | ((p4 & 0xFF000000) >> 16) | ((p0 & 0xFF00) << 8) | (p0 & 0xFF000000);
+ // *line0++ = (p0 & 0xFF000000) | ((p0 & 0xFF00) << 8) | ((p4 & 0xFF000000) >> 16) | ((p4 & 0xFF00) >> 8);
+ *line1++ = ((p0 & 0xFF0000) << 8) | ((p0 & 0xFF) << 16) | ((p4 & 0xFF0000) >> 8) | (p4 & 0xFF);
+#else
+ *line0++ = (p0 & 0xFF) | ((p0 & 0xFF0000) >> 8) | ((p4 & 0xFF) << 16) | ((p4 & 0xFF0000) << 8);
+ *line1++ = ((p0 & 0xFF00) >> 8) | ((p0 & 0xFF000000) >> 16) | ((p4 & 0xFF00) << 8) | (p4 & 0xFF000000);
+#endif
+ }
+ line0 += 320 / 4;
+ line1 += 320 / 4;
+ }
+}
+
+// Original name: CLHNM_Desentrelace
+void HnmPlayer::desentrelace() {
+ switch (_header._width) {
+ case 320:
+ desentrelace320(_newFrameBuffer, _finalBuffer, _header._height);
+ break;
+ // case 480:
+ // CLHNM_Desentrelace480(_newFrameBuffer, finalBuffer, _header._height);
+ // break;
+ default:
+ error("desentrelace - Unexpected width");
+ }
+}
+
+// Original name: CLHNM_DecompUBA
+void HnmPlayer::decompUBA(byte *output, byte *curr_buffer, byte *prev_buffer, byte *input, int width, char flags) {
+ // return;
+ byte *out_start = output;
+ byte count;
+ unsigned int code;
+ uint16 offs;
+ byte mode;
+ byte swap;
+
+ if ((flags & 1) == 0) {
+ //HNM4 classic
+ int twolinesabove = -(width * 2);
+ for (;;) {
+ code = READ_LE_UINT32(input) & 0xFFFFFF; //input++;
+ count = code & 0x1F;
+ if (count) {
+ input += 3;
+ offs = code >> 9;
+ //
+ mode = (code >> 5) & 0xF;
+ swap = mode >> 3;
+ byte *ref = ((mode & 1) ? prev_buffer : curr_buffer) + (output - out_start) + (offs * 2) - 32768;
+ int shft1, shft2;
+ if (mode & 2) {
+ // ref += twolinesabove;
+ shft1 = twolinesabove + 1;
+ shft2 = 0;
+ //swap ^= 1;
+ } else {
+ shft1 = 0;
+ shft2 = 1;
+ }
+ while (count--) {
+ byte b0 = ref[shft1];
+ byte b1 = ref[shft2];
+ output[swap] = b0;
+ output[swap ^ 1] = b1;
+ output += 2;
+ ref += (mode & 4) ? -2 : 2;
+ }
+ } else {
+ input++;
+ mode = code & 0xFF; // bits 0..4 are zero
+ switch (mode) {
+ case 0:
+ *(output++) = *(input++);
+ *(output++) = *(input++);
+ break;
+ case 0x20:
+ output += 2 * *(input++);
+ break;
+ case 0x40:
+ output += 2 * (code >> 8);
+ input += 2;
+ break;
+ case 0x60: {
+ count = *(input++);
+ byte color = *(input++);
+ while (count--) {
+ *(output++) = color;
+ *(output++) = color;
+ }
+ break;
+ }
+ default:
+ return;
+ }
+ }
+ }
+ } else {
+ assert(0);
+ //HNM4 hires
+ for (;;) {
+ code = READ_LE_UINT32(input) & 0xFFFFFF;
+ input++;
+ count = code & 0x3F;
+ if (count) {
+ mode = (code >> 5) & 0xF;
+ offs = code >> 9;
+ //
+ } else {
+ mode = code & 0xFF; // bits 0..5 are zero
+ switch (mode) {
+ case 0x00:
+ output += *input++;
+ break;
+ case 0x40:
+ *output++ = *input++;
+ *(output++ + width) = *input++;
+ break;
+ case 0x80:
+ output += width;
+ break;
+ default:
+ return;
+ }
+ }
+ }
+ }
+}
+
+// Original name: CLHNM_NextElement
+bool HnmPlayer::nextElement() {
+ if (_frameNum == 0) {
+ resetInternalTimer();
+ _prevLeft = _prevRight = 0;
+ }
+ if (_frameNum == _header._numbFrame)
+ return false;
+
+ if (!loadFrame())
+ return false;
+
+ for (;;) {
+ int sz = READ_LE_UINT32(_dataPtr) & 0xFFFFFF;
+ _dataPtr += 4;
+ int16 id = READ_LE_UINT16(_dataPtr);
+ _dataPtr += 2;
+ char h6 = *_dataPtr;
+ _dataPtr += 1;
+ char h7 = *_dataPtr;
+ _dataPtr += 1;
+ switch (id) {
+ case MKTAG16('L', 'P'):
+ changePalette();
+ _dataPtr += sz - 8;
+ break;
+ case MKTAG16('Z', 'I'):
+ _frameNum++;
+ selectBuffers();
+ decompLempelZiv(_dataPtr + 4, _newFrameBuffer);
+#if 0
+ switch (_header._width) {
+ case 320:
+ CLBlitter_RawCopy320ASM(_newFrameBuffer, _oldFrameBuffer, _header._height);
+ break;
+ case 480:
+ CLBlitter_RawCopy480ASM(_newFrameBuffer, _oldFrameBuffer, _header._height);
+ break;
+ case 640:
+ CLBlitter_RawCopy640ASM(_newFrameBuffer, _oldFrameBuffer, _header._height);
+ break;
+ default:
+ memcpy(_oldFrameBuffer, _newFrameBuffer, _header._width * _header._height);
+ }
+#else
+ memcpy(_oldFrameBuffer, _newFrameBuffer, _header._bufferSize); //TODO strange buffer size here
+#endif
+ if (!(h6 & 1))
+ desentrelace();
+ else {
+ // if(_header._width == 640)
+ // CLBlitter_RawCopy640(_newFrameBuffer, finalBuffer, _header._height);
+ // else
+ memcpy(_finalBuffer, _newFrameBuffer, _header._height); //TODO: wrong size?
+ }
+
+ if (!_soundStarted) {
+ _soundChannel->play();
+ _soundStarted = true;
+ }
+
+ return true;
+ case MKTAG16('U', 'I'):
+ _frameNum++;
+ selectBuffers();
+ decompUBA(_newFrameBuffer, _newFrameBuffer, _oldFrameBuffer, _dataPtr, _header._width, h6);
+ if (!(h6 & 1))
+ desentrelace();
+ else {
+ // if(_header._width == 640)
+ // CLBlitter_RawCopy640(_newFrameBuffer, _finalBuffer, _header._height);
+ // else
+ memcpy(_finalBuffer, _newFrameBuffer, _header._width * _header._height);
+ }
+ return true;
+
+ case MKTAG16('d', 's'):
+ case MKTAG16('D', 'S'):
+ if (_useSound) {
+ if (!h6) {
+ int sound_size = sz - 8;
+ if (!_useAdpcm) {
+ _soundChannel->queueBuffer(_dataPtr, sound_size - 2, false, _soundStarted);
+ } else {
+#if 0
+ // Not used in Lost Eden
+ int16 *sound_buffer = (int16 *)_soundGroup->getNextBuffer();
+ if (!_pendingSounds) {
+ const int kDecompTableSize = 256 * sizeof(int16);
+ loadDecompTable((int16 *)_dataPtr);
+ decompADPCM(_dataPtr + kDecompTableSize, sound_buffer, sound_size - kDecompTableSize);
+ _soundGroup->assignDatas(sound_buffer, (sound_size - kDecompTableSize) * 2, false);
+ } else {
+ decompADPCM(_dataPtr, sound_buffer, sound_size);
+ _soundGroup->assignDatas(sound_buffer, sound_size * 2, false);
+ }
+ _pendingSounds++;
+ if (_soundStarted)
+ _soundGroup->playNextSample(_soundChannel);
+#endif
+ }
+ } else
+ error("nextElement - unexpected flag");
+ }
+ _dataPtr += sz - 8;
+ break;
+ default:
+ if (_customChunkHandler)
+ _customChunkHandler(_dataPtr, sz - 8, id, h6, h7);
+ _dataPtr += sz - 8;
+ }
+ }
+ return true;
+}
+
+// Original name: CLHNM_GetSoundChannel
+CSoundChannel *HnmPlayer::getSoundChannel() {
+ return _soundChannel;
+}
+
+// Original name: CLHNM_ChangePalette
+void HnmPlayer::changePalette() {
+ CLPalette_GetLastPalette(_palette);
+ byte *pal = _dataPtr;
+ if (*(uint16 *)pal == 0xFFFF)
+ return;
+
+ int16 mincolor = 255;
+ int16 maxcolor = 0;
+ do {
+ uint16 fst = *pal++;
+ uint16 cnt = *pal++;
+ if (cnt == 0)
+ cnt = 256;
+ debug("hnm: setting palette, fst = %d, cnt = %d, last = %d", fst, cnt, fst + cnt - 1);
+ assert(fst + cnt <= 256);
+ if (mincolor > fst)
+ mincolor = fst;
+ if (maxcolor < fst + cnt)
+ maxcolor = fst + cnt;
+ color_t *color = _palette + fst;
+ if (_safePalette) {
+ while (cnt--) {
+ byte r = *pal++;
+ byte g = *pal++;
+ byte b = *pal++;
+ int16 rr = r << 10;
+ int16 gg = g << 10;
+ int16 bb = b << 10;
+ if (color->r != rr || color->g != gg || color->b != bb)
+ CLBlitter_OneBlackFlash();
+ color->r = rr;
+ color->g = gg;
+ color->b = bb;
+ color++;
+ }
+ } else {
+ while (cnt--) {
+ byte r = *pal++;
+ byte g = *pal++;
+ byte b = *pal++;
+ color->r = r << 10;
+ color->g = g << 10;
+ color->b = b << 10;
+ color++;
+ }
+ }
+
+ } while (*(uint16 *)pal != 0xFFFF);
+#if 0
+ if (preserve_color0) {
+ _palette[0].r = 0;
+ _palette[0].g = 0;
+ _palette[0].b = 0;
+ }
+#endif
+ // CLBlitter_Send2ScreenNextCopy(_palette, mincolor, maxcolor - mincolor);
+ CLBlitter_Send2ScreenNextCopy(_palette, 0, 256);
+}
+
+// Original name: CLHNM_SelectBuffers
+void HnmPlayer::selectBuffers() {
+ if (_frameNum % 2) {
+ _newFrameBuffer = _tmpBuffer[1];
+ _oldFrameBuffer = _tmpBuffer[0];
+ } else {
+ _newFrameBuffer = _tmpBuffer[0];
+ _oldFrameBuffer = _tmpBuffer[1];
+ }
+}
+
+} // namespace Cryo
+
diff --git a/engines/cryo/video.h b/engines/cryo/video.h
new file mode 100644
index 0000000000..83eddfb9b1
--- /dev/null
+++ b/engines/cryo/video.h
@@ -0,0 +1,106 @@
+/* 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.
+ *
+ */
+
+#ifndef CRYO_VIDEO_H
+#define CRYO_VIDEO_H
+
+#include "cryo/sound.h"
+
+namespace Cryo {
+
+class CryoEngine;
+
+class HnmPlayer {
+public:
+ Common::File *_file;
+ HNMHeader _header;
+
+private:
+ CryoEngine *_vm;
+
+ void resetInternalTimer();
+ void wantsSound(bool sound);
+ void decompADPCM(byte *buffer, int16 *output, int size);
+ void loadDecompTable(int16 *buffer);
+ bool loadFrame();
+ void tryRead(int size);
+ void changePalette();
+ void selectBuffers();
+ void decompLempelZiv(byte *buffer, byte *output);
+ void desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height);
+ void desentrelace();
+ void decompUBA(byte *output, byte *curr_buffer, byte *prev_buffer, byte *input, int width, char flags);
+ void setupSoundADPCM(int16 numSounds, int16 length, int16 sampleSize, float rate, int16 mode);
+ void init();
+
+ bool _soundStarted;
+ int16 _pendingSounds;
+ float _timeDrift;
+ float _nextFrameTime;
+ float _expectedFrameTime;
+ float _rate;
+ bool _useSoundSync;
+ bool _useSound;
+ int16 _prevRight;
+ int16 _prevLeft;
+ bool _useAdpcm;
+ bool _preserveColor0;
+ int16 decompTable[256];
+ bool _safePalette;
+ int _frameNum;
+ byte *_tmpBuffer[2];
+ byte *_finalBuffer;
+ byte *_newFrameBuffer;
+ byte *_oldFrameBuffer;
+ byte *_readBuffer;
+ byte *_dataPtr;
+ color_t _palette[256];
+ int _totalRead;
+
+ void (*_customChunkHandler)(byte *buffer, int size, int16 id, char h6, char h7);
+
+ CSoundChannel *_soundChannel;
+
+public:
+ HnmPlayer(CryoEngine *vm);
+
+ void allocMemory();
+ void closeSound();
+ void deallocMemory();
+ int getFrameNum();
+ CSoundChannel *getSoundChannel();
+ int16 getVersion();
+ bool nextElement();
+ void reset();
+ void readHeader();
+ void resetInternals();
+ void setFile(Common::File *file);
+ void setFinalBuffer(byte *buffer);
+ void setForceZero2Black(bool forceblack);
+ void setupSound(unsigned int rate, bool stereo, bool is16bits);
+ void setupTimer(float rate);
+ void waitLoop();
+};
+
+} // End of namespace Cryo
+
+#endif
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 496f47cc23..f426107ee3 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -411,7 +411,7 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff
keyRes = &resources[resources.size() - 1];
else if (tag == MKTAG('C', 'A', 'S', '*'))
casRes = &resources[resources.size() - 1];
- //or the children of
+ // or the children of
else if (tag == MKTAG('S', 'T', 'X', 'T') ||
tag == MKTAG('B', 'I', 'T', 'D') ||
tag == MKTAG('D', 'I', 'B', ' '))
@@ -441,14 +441,13 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff
debugCN(2, kDebugLoading, "CAS*: %d [", casSize);
for (uint i = 0; i < casSize; i++) {
- uint32 index = casStream.readUint32();
+ uint32 index = casStream.readUint32BE();
+ debugCN(2, kDebugLoading, "%d ", index);
Resource &res = resources[index];
res.index = index;
res.castId = i + 1;
_types[castTag][res.castId] = res;
-
- debugCN(2, kDebugLoading, "%d ", index);
}
debugC(2, kDebugLoading, "]");
}
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 4522eaeeb6..4b391bd8cc 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -83,7 +83,7 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
textSlant = 0;
palinfo1 = palinfo2 = palinfo3 = 0;
- if (version < 4) {
+ if (version <= 3) {
flags1 = stream.readByte();
borderSize = static_cast<SizeType>(stream.readByte());
gutterSize = static_cast<SizeType>(stream.readByte());
@@ -95,7 +95,9 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
palinfo3 = stream.readUint16();
int t = stream.readUint32();
- assert(t == 0); // So far we saw only 0 here
+ if (t != 0) { // In D2 there are values
+ warning("TextCast: t: %x", t);
+ }
initialRect = Score::readRect(stream);
textShadow = static_cast<SizeType>(stream.readByte());
@@ -113,18 +115,18 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
fontId = stream.readByte();
fontSize = stream.readByte();
textSlant = 0;
- } else if (version < 5) {
+ } else if (version == 4) {
borderSize = static_cast<SizeType>(stream.readByte());
gutterSize = static_cast<SizeType>(stream.readByte());
boxShadow = static_cast<SizeType>(stream.readByte());
textType = static_cast<TextType>(stream.readByte());
- textAlign = static_cast<TextAlignType>(stream.readSint16()); //this is because 'right' is -1? or should that be 255?
+ textAlign = static_cast<TextAlignType>(stream.readSint16()); // this is because 'right' is -1? or should that be 255?
stream.readUint16();
stream.readUint16();
stream.readUint16();
stream.readUint16();
- fontId = 1; //this is in STXT
+ fontId = 1; // this is in STXT
initialRect = Score::readRect(stream);
stream.readUint16();
@@ -132,7 +134,7 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
byte flags = stream.readByte();
if (flags)
- warning("Unproxessed text cast flags: %x", flags);
+ warning("Unprocessed text cast flags: %x", flags);
fontSize = stream.readUint16();
textSlant = 0;
@@ -180,8 +182,9 @@ ButtonCast::ButtonCast(Common::ReadStreamEndian &stream, uint16 version) : TextC
stream.readByte();
stream.readByte();
- initialRect = Score::readRect(stream);
- boundingRect = Score::readRect(stream);
+ //This has already been populated in the super TextCast constructor
+ //initialRect = Score::readRect(stream);
+ //boundingRect = Score::readRect(stream);
buttonType = static_cast<ButtonType>(stream.readUint16BE());
}
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index c26084ac6c..43c5bf2b4f 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -78,6 +78,7 @@ static const PlainGameDescriptor directorGames[] = {
{ "jewels", "Jewels of the Oracle" },
{ "jman", "The Journeyman Project" },
{ "majestic", "Majestic Part I: Alien Encounter" },
+ { "mediaband", "Meet Mediaband" },
{ "melements", "Masters of the Elements" },
{ "spyclub", "Spy Club" },
{ "amber", "AMBER: Journeys Beyond"},
diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 15bdf37968..11f70e033c 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -69,8 +69,21 @@ static const DirectorGameDescription gameDescriptions[] = {
{
{
"theapartment",
+ "D2",
+ AD_ENTRY1s("Main Menu", "fc56c179cb8c6d4938e61ee61fd0032c", 48325), // Original name is "•Main Menu"
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_MACRESFORK,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GID_GENERIC,
+ 2
+ },
+ {
+ {
+ "theapartment",
"D3",
- AD_ENTRY1s("Main Menu", "9e838fe1a6af7992d656ca325e38dee5", 47911),
+ AD_ENTRY1s("Main Menu", "9e838fe1a6af7992d656ca325e38dee5", 47911), // Original name is "•Main Menu"
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK,
@@ -83,7 +96,7 @@ static const DirectorGameDescription gameDescriptions[] = {
{
"theapartment",
"D4",
- AD_ENTRY1s("Main Menu", "ff86181f03fe6eb060f65a985ca0580d", 160612),
+ AD_ENTRY1s("Main Menu", "ff86181f03fe6eb060f65a985ca0580d", 160612),// Original name is "•Main Menu"
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
@@ -291,6 +304,20 @@ static const DirectorGameDescription gameDescriptions[] = {
4
},
+ { // Meet Mediaband
+ {
+ "mediaband",
+ "",
+ AD_ENTRY1s("MEDIABND.EXE", "0cfb9b4762e33ab56d656a0eb146a048", 717921),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ GID_GENERIC,
+ 4
+ },
+
{
{
// Masters of the Elements - English (from rootfather)
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 3e95d6bcbb..bfe9a724be 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -42,9 +42,11 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
_rnd("director") {
DebugMan.addDebugChannel(kDebugLingoExec, "lingoexec", "Lingo Execution");
DebugMan.addDebugChannel(kDebugLingoCompile, "lingocompile", "Lingo Compilation");
+ DebugMan.addDebugChannel(kDebugLingoParse, "lingoparse", "Lingo code parsing");
DebugMan.addDebugChannel(kDebugLoading, "loading", "Loading");
DebugMan.addDebugChannel(kDebugImages, "images", "Image drawing");
DebugMan.addDebugChannel(kDebugText, "text", "Text rendering");
+ DebugMan.addDebugChannel(kDebugEvents, "events", "Event processing");
g_director = this;
@@ -76,16 +78,21 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
_movies = nullptr;
+ _nextMovieFrameI = -1;
+
_wm = nullptr;
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "data");
SearchMan.addSubDirectoryMatching(gameDataDir, "install");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "main"); // Meet Mediaband
_colorDepth = 8; // 256-color
_key = 0;
_keyCode = 0;
_machineType = 9; // Macintosh IIci
+ _playbackPaused = false;
+ g_director->_skipFrameAdvance = false;
}
DirectorEngine::~DirectorEngine() {
@@ -119,8 +126,10 @@ Common::Error DirectorEngine::run() {
_mainArchive = nullptr;
_currentScore = nullptr;
- testFontScaling();
- testFonts();
+ if (debugChannelSet(-1, kDebugText)) {
+ testFontScaling();
+ testFonts();
+ }
_lingo->runTests();
@@ -131,10 +140,15 @@ Common::Error DirectorEngine::run() {
//_mainArchive = new RIFFArchive();
//_mainArchive->openFile("bookshelf_example.mmm");
- if (getPlatform() == Common::kPlatformWindows)
- _sharedCastFile = "SHARDCST.MMM";
- else
- _sharedCastFile = "Shared Cast";
+ if (getVersion() < 4) {
+ if (getPlatform() == Common::kPlatformWindows) {
+ _sharedCastFile = "SHARDCST.MMM";
+ } else {
+ _sharedCastFile = "Shared Cast";
+ }
+ } else {
+ _sharedCastFile = "Shared.dir";
+ }
loadSharedCastsFrom(_sharedCastFile);
@@ -143,8 +157,43 @@ Common::Error DirectorEngine::run() {
_currentScore = new Score(this, _mainArchive);
debug(0, "Score name %s", _currentScore->getMacName().c_str());
- _currentScore->loadArchive();
- _currentScore->startLoop();
+ bool loop = true;
+
+ while (loop) {
+ loop = false;
+
+ _currentScore->loadArchive();
+
+ // If we came in a loop, then skip as requested
+ if (!_nextMovieFrameS.empty())
+ _currentScore->setStartToLabel(_nextMovieFrameS);
+
+ if (_nextMovieFrameI != -1)
+ _currentScore->setCurrentFrame(_nextMovieFrameI);
+
+ _currentScore->startLoop();
+
+ // If a loop was requested, do it
+ if (!_nextMovie.empty()) {
+ _lingo->restartLingo();
+
+ delete _currentScore;
+
+ Archive *mov = openMainArchive(_nextMovie);
+
+ if (!mov) {
+ warning("nextMovie: No score is loaded");
+
+ return Common::kNoError;
+ }
+
+ _currentScore = new Score(this, mov);
+ debug(0, "Score name %s", _currentScore->getMacName().c_str());
+
+ _nextMovie.clear();
+ loop = true;
+ }
+ }
return Common::kNoError;
}
@@ -189,32 +238,4 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo
return nameMap;
}
-void DirectorEngine::setPalette(byte *palette, uint16 count) {
- _currentPalette = palette;
- _currentPaletteLength = count;
-}
-
-void DirectorEngine::testFonts() {
- Common::String fontName("Helvetica");
-
- Common::MacResManager *fontFile = new Common::MacResManager();
- if (!fontFile->open(fontName))
- error("Could not open %s as a resource fork", fontName.c_str());
-
- Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D'));
- if (fonds.size() > 0) {
- for (Common::Array<uint16>::iterator iterator = fonds.begin(); iterator != fonds.end(); ++iterator) {
- Common::SeekableReadStream *stream = fontFile->getResource(MKTAG('F', 'O', 'N', 'D'), *iterator);
- Common::String name = fontFile->getResName(MKTAG('F', 'O', 'N', 'D'), *iterator);
-
- debug("Font: %s", name.c_str());
-
- Graphics::MacFontFamily font;
- font.load(*stream);
- }
- }
-
- delete fontFile;
-}
-
} // End of namespace Director
diff --git a/engines/director/director.h b/engines/director/director.h
index 8d5f6b5211..fdbe8ded48 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -57,9 +57,12 @@ enum {
kDebugLingoCompile = 1 << 1,
kDebugLoading = 1 << 2,
kDebugImages = 1 << 3,
- kDebugText = 1 << 4
+ kDebugText = 1 << 4,
+ kDebugEvents = 1 << 5,
+ kDebugLingoParse = 1 << 6
};
+extern byte defaultPalette[768];
class DirectorEngine : public ::Engine {
public:
@@ -97,7 +100,6 @@ public:
Common::HashMap<int, Cast *> *getSharedCasts() const { return _sharedCasts; }
Common::HashMap<Common::String, Score *> *_movies;
- Score *_currentScore;
Common::RandomSource _rnd;
Graphics::MacWindowManager *_wm;
@@ -107,6 +109,12 @@ public:
unsigned char _key;
int _keyCode;
int _machineType;
+ bool _playbackPaused;
+ bool _skipFrameAdvance;
+
+ Common::String _nextMovie;
+ Common::String _nextMovieFrameS;
+ int _nextMovieFrameI;
protected:
virtual Common::Error run();
@@ -136,6 +144,8 @@ private:
uint16 _currentPaletteLength;
Lingo *_lingo;
+ Score *_currentScore;
+
Graphics::MacPatterns _director3Patterns;
Graphics::MacPatterns _director3QuickDrawPatterns;
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 402056ad20..d20026cb62 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -304,7 +304,7 @@ void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
_palette->flags = stream.readByte();
_palette->speed = stream.readByte();
_palette->frameCount = stream.readUint16();
- stream.skip(8); //unknown
+ stream.skip(8); // unknown
}
void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
@@ -380,7 +380,7 @@ void Frame::prepareFrame(Score *score) {
renderSprites(*score->_trailSurface, true);
if (_transType != 0)
- //T ODO Handle changing area case
+ // TODO Handle changing area case
playTransition(score);
if (_sound1 != 0 || _sound2 != 0) {
@@ -391,8 +391,7 @@ void Frame::prepareFrame(Score *score) {
}
void Frame::playSoundChannel() {
- debug(0, "Sound1 %d", _sound1);
- debug(0, "Sound2 %d", _sound2);
+ debug(0, "STUB: playSoundChannel(), Sound1 %d Sound2 %d", _sound1, _sound2);
}
void Frame::playTransition(Score *score) {
@@ -553,7 +552,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
castType = kCastBitmap;
break;
case 0x02:
- case 0x0c: //this is actually a mouse-over shape? I don't think it's a real button.
+ case 0x0c: // this is actually a mouse-over shape? I don't think it's a real button.
castType = kCastShape;
break;
case 0x07:
@@ -561,7 +560,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
break;
}
} else {
- if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
+ if (!_vm->getCurrentScore()->_casts.contains(_sprites[i]->_castId)) {
if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
warning("Cast id %d not found", _sprites[i]->_castId);
continue;
@@ -570,13 +569,13 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
}
} else {
- cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+ cast = _vm->getCurrentScore()->_casts[_sprites[i]->_castId];
}
castType = cast->type;
}
- //this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes.
- //I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null?
+ // this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes.
+ // I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null?
if (castType == kCastShape) {
renderShape(surface, i);
} else if (castType == kCastText) {
@@ -596,10 +595,13 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
continue;
}
- assert(_sprites[i]->_cast);
+ if (!_sprites[i]->_cast) {
+ warning("No cast ID for sprite %d", i);
+ continue;
+ }
BitmapCast *bitmapCast = static_cast<BitmapCast *>(_sprites[i]->_cast);
- //TODO: might want a quicker way to determine if cast is from Shared Cast.
+ // TODO: might want a quicker way to determine if cast is from Shared Cast.
if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(_sprites[i]->_castId + 1024)) {
debugC(2, kDebugImages, "Shared cast sprite BMP: id: %d", _sprites[i]->_castId + 1024);
bitmapCast = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(_sprites[i]->_castId));
@@ -642,10 +644,10 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
if (_vm->getVersion() <= 3 && _sprites[spriteId]->_spriteType == 0x0c) {
tmpSurface.fillRect(Common::Rect(shapeRect.width(), shapeRect.height()), 255);
tmpSurface.frameRect(Common::Rect(shapeRect.width(), shapeRect.height()), 0);
- //TODO: don't override, work out how to display correctly.
+ // TODO: don't override, work out how to display correctly.
_sprites[spriteId]->_ink = kInkTypeTransparent;
} else {
- //No minus one on the pattern here! MacPlotData will do that for us!
+ // No minus one on the pattern here! MacPlotData will do that for us!
Graphics::MacPlotData pd(&tmpSurface, &_vm->getPatterns(), _sprites[spriteId]->_castId, 1, _sprites[spriteId]->_backColor);
Common::Rect fillRect(shapeRect.width(), shapeRect.height());
Graphics::drawFilledRect(fillRect, _sprites[spriteId]->_foreColor, Graphics::macDrawPixel, &pd);
@@ -661,18 +663,23 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
}
void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) {
- renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), true);
-
uint16 castId = _sprites[spriteId]->_castId;
- ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castId]);
+ ButtonCast *button = static_cast<ButtonCast *>(_vm->getCurrentScore()->_casts[castId]);
uint32 rectLeft = button->initialRect.left;
uint32 rectTop = button->initialRect.top;
int x = _sprites[spriteId]->_startPoint.x + rectLeft;
int y = _sprites[spriteId]->_startPoint.y + rectTop;
- int height = _sprites[spriteId]->_height;
- int width = _sprites[spriteId]->_width;
+ int height = button->initialRect.height(); // _sprites[spriteId]->_height;
+ int width = button->initialRect.width() + 3; // _sprites[spriteId]->_width;
+
+ Common::Rect textRect(0, 0, width, height);
+ // pass the rect of the button into the label.
+ renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), &textRect);
+
+ // TODO: review all cases to confirm if we should use text height.
+ // height = textRect.height();
Common::Rect _rect;
@@ -684,7 +691,7 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin
addDrawRect(spriteId, _rect);
break;
case kTypeButton: {
- _rect = Common::Rect(x, y, x + width - 1, y + height + 5);
+ _rect = Common::Rect(x, y, x + width, y + height + 3);
Graphics::MacPlotData pd(&surface, &_vm->getMacWindowManager()->getPatterns(), Graphics::MacGUIConstants::kPatternSolid, 1);
Graphics::drawRoundRect(_rect, 4, 0, false, Graphics::macDrawPixel, &pd);
addDrawRect(spriteId, _rect);
@@ -699,14 +706,14 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin
Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
uint16 imgId = spriteId + 1024;
- if (_vm->getVersion() >= 4 && _vm->_currentScore->_casts[spriteId]->children.size() > 0)
- imgId = _vm->_currentScore->_casts[spriteId]->children[0].index;
+ if (_vm->getVersion() >= 4 && _vm->getCurrentScore()->_casts[spriteId]->children.size() > 0)
+ imgId = _vm->getCurrentScore()->_casts[spriteId]->children[0].index;
Image::ImageDecoder *img = NULL;
- if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
+ if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
img = new DIBDecoder();
- img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId));
+ img->loadStream(*_vm->getCurrentScore()->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId));
return img;
}
@@ -720,27 +727,27 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
BitmapCast *bc = NULL;
if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
- debugC(2, kDebugImages, "Shared cast BMP: id: %d", imgId);
+ debugC(4, kDebugImages, "Shared cast BMP: id: %d", imgId);
pic = _vm->getSharedBMP()->getVal(imgId);
- pic->seek(0); //TODO: this actually gets re-read every loop... we need to rewind it!
+ pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it!
bc = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(spriteId));
- } else if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
- pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
- bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ } else if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
+ pic = _vm->getCurrentScore()->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
+ bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]);
}
if (pic != NULL && bc != NULL) {
if (_vm->getVersion() < 4) {
int w = bc->initialRect.width(), h = bc->initialRect.height();
- debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
+ debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
img = new BITDDecoder(w, h);
} else if (_vm->getVersion() < 6) {
- bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]);
int w = bc->initialRect.width(), h = bc->initialRect.height();
- debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
+ debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
img = new BITDDecoderV4(w, h, bc->bitsPerPixel);
} else {
@@ -794,21 +801,21 @@ void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics
void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castId) {
Common::SeekableSubReadStreamEndian *textStream = NULL;
- if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castId)) {
- textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castId);
+ if (_vm->getCurrentScore()->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castId)) {
+ textStream = _vm->getCurrentScore()->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castId);
} else if (_vm->getSharedSTXT() != nullptr) {
textStream = _vm->getSharedSTXT()->getVal(spriteId + 1024);
}
- renderText(surface, spriteId, textStream, false);
+ renderText(surface, spriteId, textStream, NULL);
}
-void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel) {
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, Common::Rect *textSize) {
if (textStream == NULL)
return;
uint16 castId = _sprites[spriteId]->_castId;
- TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castId]);
+ TextCast *textCast = static_cast<TextCast *>(_vm->getCurrentScore()->_casts[castId]);
uint32 unk1 = textStream->readUint32();
uint32 strLen = textStream->readUint32();
@@ -823,11 +830,15 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
text += ch;
}
+ Common::String ftext;
+
debugC(3, kDebugText, "renderText: unk1: %d strLen: %d dataLen: %d textlen: %u", unk1, strLen, dataLen, text.size());
if (strLen < 200)
debugC(3, kDebugText, "text: '%s'", text.c_str());
uint16 formattingCount = textStream->readUint16();
+ uint32 prevPos = 0;
+
while (formattingCount) {
uint32 formatStartOffset = textStream->readUint32();
uint16 unk1f = textStream->readUint16();
@@ -848,11 +859,42 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
debugC(3, kDebugText, " unk3: %d, fontSize: %d, p0: %x p1: %x p2: %x", unk3f, textCast->fontSize,
textCast->palinfo1, textCast->palinfo2, textCast->palinfo3);
+ assert (prevPos <= formatStartOffset); // If this is triggered, we have to implement sorting
+
+ while (prevPos != formatStartOffset) {
+ char f = text.firstChar();
+ ftext += text.firstChar();
+ text.deleteChar(0);
+
+ if (f == '\001') // Insert two \001s as a replacement
+ ftext += '\001';
+
+ prevPos++;
+
+ debugCN(4, kDebugText, "%c", f);
+ }
+
+ debugCN(4, kDebugText, "*");
+
+ ftext += Common::String::format("\001\015%c%c%c%c%c%c%c%c%c%c%c%c",
+ (textCast->fontId >> 8) & 0xff, textCast->fontId & 0xff,
+ textCast->textSlant & 0xff, unk3f & 0xff,
+ (textCast->fontSize >> 8) & 0xff, textCast->fontSize & 0xff,
+ (textCast->palinfo1 >> 8) & 0xff, textCast->palinfo1 & 0xff,
+ (textCast->palinfo2 >> 8) & 0xff, textCast->palinfo2 & 0xff,
+ (textCast->palinfo3 >> 8) & 0xff, textCast->palinfo3 & 0xff);
+
formattingCount--;
}
+ ftext += text;
+
+ debugC(4, kDebugText, "%s", text.c_str());
+
uint16 boxShadow = (uint16)textCast->boxShadow;
uint16 borderSize = (uint16)textCast->borderSize;
+ if (textSize != NULL)
+ borderSize = 0;
uint16 padding = (uint16)textCast->gutterSize;
uint16 textShadow = (uint16)textCast->textShadow;
@@ -861,18 +903,21 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
int x = _sprites[spriteId]->_startPoint.x; // +rectLeft;
int y = _sprites[spriteId]->_startPoint.y; // +rectTop;
-
int height = _sprites[spriteId]->_height;
- if (_vm->getVersion() >= 4 && !isButtonLabel) height = textCast->initialRect.bottom;
- height += textShadow;
-
int width = _sprites[spriteId]->_width;
- if (_vm->getVersion() >= 4 && !isButtonLabel) width = textCast->initialRect.right;
- if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
- // We need to make sure that teh Shared Cast fonts have been loaded in?
- //might need a mapping table here of our own.
- //textCast->fontId = _vm->_wm->_fontMan->getFontIdByName(_vm->_currentScore->_fontMap[textCast->fontId]);
+ if (_vm->getVersion() >= 4 && textSize != NULL)
+ width = textCast->initialRect.right;
+
+ if (_vm->getCurrentScore()->_fontMap.contains(textCast->fontId)) {
+ // We need to make sure that the Shared Cast fonts have been loaded in?
+ // might need a mapping table here of our own.
+ // textCast->fontId = _vm->_wm->_fontMan->getFontIdByName(_vm->getCurrentScore()->_fontMap[textCast->fontId]);
+ }
+
+ if (width == 0 || height == 0) {
+ warning("renderText: Requested to draw on an empty surface: %d x %d", width, height);
+ return;
}
Graphics::MacFont macFont = Graphics::MacFont(textCast->fontId, textCast->fontSize, textCast->textSlant);
@@ -887,16 +932,28 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
else
alignment++;
- Graphics::MacText mt(text, font, 0x00, 0xff, width, (Graphics::TextAlign)alignment);
+ if (_vm->getVersion() >= 4) {
+ if (textSize == NULL)
+ width = textCast->initialRect.right;
+ else {
+ width = textSize->width();
+ }
+ }
+
+ Graphics::MacText mt(ftext, _vm->_wm, font, 0x00, 0xff, width, (Graphics::TextAlign)alignment);
mt.setInterLinear(1);
mt.render();
const Graphics::ManagedSurface *textSurface = mt.getSurface();
height = textSurface->h;
+ if (textSize != NULL) {
+ // TODO: this offset could be due to incorrect fonts loaded!
+ textSize->bottom = height + mt.getLineCount();
+ }
uint16 textX = 0, textY = 0;
- if (!isButtonLabel) {
+ if (textSize == NULL) {
if (borderSize > 0) {
if (_vm->getVersion() <= 3)
height++;
@@ -921,6 +978,9 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
if (textShadow > 0)
textX--;
} else {
+ x++;
+ if (width % 2 != 0)
+ x++;
y += 2;
}
@@ -938,11 +998,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
Graphics::ManagedSurface textWithFeatures(width + (borderSize * 2) + boxShadow + textShadow, height + borderSize + boxShadow + textShadow);
textWithFeatures.fillRect(Common::Rect(textWithFeatures.w, textWithFeatures.h), 0xff);
- if (!isButtonLabel && boxShadow > 0) {
+ if (textSize == NULL && boxShadow > 0) {
textWithFeatures.fillRect(Common::Rect(boxShadow, boxShadow, textWithFeatures.w + boxShadow, textWithFeatures.h), 0);
}
- if (!isButtonLabel && borderSize != kSizeNone) {
+ if (textSize == NULL && borderSize != kSizeNone) {
for (int bb = 0; bb < borderSize; bb++) {
Common::Rect borderRect(bb, bb, textWithFeatures.w - bb - boxShadow - textShadow, textWithFeatures.h - bb - boxShadow - textShadow);
textWithFeatures.fillRect(borderRect, 0xff);
diff --git a/engines/director/frame.h b/engines/director/frame.h
index f822a83fdb..3799c2043c 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -125,7 +125,7 @@ private:
void playSoundChannel();
void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail);
void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castId);
- void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel);
+ void renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, Common::Rect *textSize);
void renderShape(Graphics::ManagedSurface &surface, uint16 spriteId);
void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId);
void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index f980edee5c..76ff41788c 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -19,10 +19,72 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "common/events.h"
+#include "common/macresman.h"
+#include "common/system.h"
+#include "engines/util.h"
+
+#include "graphics/palette.h"
+#include "graphics/fonts/macfont.h"
+#include "graphics/macgui/macfontmanager.h"
+#include "graphics/macgui/macwindowmanager.h"
+
#include "director/director.h"
namespace Director {
+// Referred as extern
+byte defaultPalette[768] = {
+ 0, 0, 0, 17, 17, 17, 34, 34, 34, 68, 68, 68, 85, 85, 85, 119,
+ 119, 119, 136, 136, 136, 170, 170, 170, 187, 187, 187, 221, 221, 221, 238, 238,
+ 238, 0, 0, 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119,
+ 0, 0, 136, 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0,
+ 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136,
+ 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 17, 0, 0,
+ 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, 0, 0, 170,
+ 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 0, 0, 0, 51, 0, 0,
+ 102, 0, 0, 153, 0, 0, 204, 0, 0, 255, 0, 51, 0, 0, 51, 51,
+ 0, 51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 102, 0, 0,
+ 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0, 102, 255, 0, 153,
+ 0, 0, 153, 51, 0, 153, 102, 0, 153, 153, 0, 153, 204, 0, 153, 255,
+ 0, 204, 0, 0, 204, 51, 0, 204, 102, 0, 204, 153, 0, 204, 204, 0,
+ 204, 255, 0, 255, 0, 0, 255, 51, 0, 255, 102, 0, 255, 153, 0, 255,
+ 204, 0, 255, 255, 51, 0, 0, 51, 0, 51, 51, 0, 102, 51, 0, 153,
+ 51, 0, 204, 51, 0, 255, 51, 51, 0, 51, 51, 51, 51, 51, 102, 51,
+ 51, 153, 51, 51, 204, 51, 51, 255, 51, 102, 0, 51, 102, 51, 51, 102,
+ 102, 51, 102, 153, 51, 102, 204, 51, 102, 255, 51, 153, 0, 51, 153, 51,
+ 51, 153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 204, 0, 51,
+ 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51, 204, 255, 51, 255,
+ 0, 51, 255, 51, 51, 255, 102, 51, 255, 153, 51, 255, 204, 51, 255, 255,
+ 102, 0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0, 204, 102,
+ 0, 255, 102, 51, 0, 102, 51, 51, 102, 51, 102, 102, 51, 153, 102, 51,
+ 204, 102, 51, 255, 102, 102, 0, 102, 102, 51, 102, 102, 102, 102, 102, 153,
+ 102, 102, 204, 102, 102, 255, 102, 153, 0, 102, 153, 51, 102, 153, 102, 102,
+ 153, 153, 102, 153, 204, 102, 153, 255, 102, 204, 0, 102, 204, 51, 102, 204,
+ 102, 102, 204, 153, 102, 204, 204, 102, 204, 255, 102, 255, 0, 102, 255, 51,
+ 102, 255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 153, 0, 0, 153,
+ 0, 51, 153, 0, 102, 153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 51,
+ 0, 153, 51, 51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255,
+ 153, 102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102, 204, 153,
+ 102, 255, 153, 153, 0, 153, 153, 51, 153, 153, 102, 153, 153, 153, 153, 153,
+ 204, 153, 153, 255, 153, 204, 0, 153, 204, 51, 153, 204, 102, 153, 204, 153,
+ 153, 204, 204, 153, 204, 255, 153, 255, 0, 153, 255, 51, 153, 255, 102, 153,
+ 255, 153, 153, 255, 204, 153, 255, 255, 204, 0, 0, 204, 0, 51, 204, 0,
+ 102, 204, 0, 153, 204, 0, 204, 204, 0, 255, 204, 51, 0, 204, 51, 51,
+ 204, 51, 102, 204, 51, 153, 204, 51, 204, 204, 51, 255, 204, 102, 0, 204,
+ 102, 51, 204, 102, 102, 204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 153,
+ 0, 204, 153, 51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255,
+ 204, 204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204, 204, 204,
+ 204, 255, 204, 255, 0, 204, 255, 51, 204, 255, 102, 204, 255, 153, 204, 255,
+ 204, 204, 255, 255, 255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153,
+ 255, 0, 204, 255, 0, 255, 255, 51, 0, 255, 51, 51, 255, 51, 102, 255,
+ 51, 153, 255, 51, 204, 255, 51, 255, 255, 102, 0, 255, 102, 51, 255, 102,
+ 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51,
+ 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255,
+ 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255,
+ 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 };
+
+
static byte director3Patterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF },
{ 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF },
@@ -152,4 +214,90 @@ Graphics::MacPatterns &DirectorEngine::getPatterns() {
return _director3QuickDrawPatterns;
}
+void DirectorEngine::setPalette(byte *palette, uint16 count) {
+ _currentPalette = palette;
+ _currentPaletteLength = count;
+}
+
+void DirectorEngine::testFontScaling() {
+ int x = 10;
+ int y = 10;
+ int w = 640;
+ int h = 480;
+
+ initGraphics(w, h, true);
+ _system->getPaletteManager()->setPalette(defaultPalette, 0, 256);
+
+ Graphics::ManagedSurface surface;
+
+ surface.create(w, h);
+ surface.clear(255);
+
+ Graphics::MacFont origFont(Graphics::kMacFontNewYork, 18);
+
+ const Graphics::MacFONTFont *font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(origFont);
+
+ Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 200, 500);
+
+ Graphics::MacFont bigFont(Graphics::kMacFontNewYork, 15);
+
+ font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(bigFont);
+
+ Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 50 + 200, 500);
+
+ const char *text = "d";
+
+ for (int i = 9; i <= 20; i++) {
+ Graphics::MacFont macFont(Graphics::kMacFontNewYork, i);
+
+ const Graphics::Font *font = _wm->_fontMan->getFont(macFont);
+
+ int width = font->getStringWidth(text);
+
+ Common::Rect bbox = font->getBoundingBox(text, x, y, w);
+ surface.frameRect(bbox, 15);
+
+ font->drawString(&surface, text, x, y, width, 0);
+
+ x += width + 1;
+ }
+
+ g_system->copyRectToScreen(surface.getPixels(), surface.pitch, 0, 0, w, h);
+
+ Common::Event event;
+
+ while (true) {
+ if (g_system->getEventManager()->pollEvent(event))
+ if (event.type == Common::EVENT_QUIT)
+ break;
+
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+}
+
+void DirectorEngine::testFonts() {
+ Common::String fontName("Helvetica");
+
+ Common::MacResManager *fontFile = new Common::MacResManager();
+ if (!fontFile->open(fontName))
+ error("Could not open %s as a resource fork", fontName.c_str());
+
+ Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D'));
+ if (fonds.size() > 0) {
+ for (Common::Array<uint16>::iterator iterator = fonds.begin(); iterator != fonds.end(); ++iterator) {
+ Common::SeekableReadStream *stream = fontFile->getResource(MKTAG('F', 'O', 'N', 'D'), *iterator);
+ Common::String name = fontFile->getResName(MKTAG('F', 'O', 'N', 'D'), *iterator);
+
+ debug("Font: %s", name.c_str());
+
+ Graphics::MacFontFamily font;
+ font.load(*stream);
+ }
+ }
+
+ delete fontFile;
+}
+
+
}
diff --git a/engines/director/images.cpp b/engines/director/images.cpp
index 7d5e08936e..4574165bb6 100644
--- a/engines/director/images.cpp
+++ b/engines/director/images.cpp
@@ -147,7 +147,7 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
// If the stream has exactly the required number of bits for this image,
// we assume it is uncompressed.
if (stream.size() * 8 == _surface->pitch * _surface->h) {
- debugC(3, kDebugImages, "Skipping compression");
+ debugC(6, kDebugImages, "Skipping compression");
for (y = 0; y < _surface->h; y++) {
for (x = 0; x < _surface->pitch; ) {
byte color = stream.readByte();
@@ -265,7 +265,7 @@ bool BITDDecoderV4::loadStream(Common::SeekableReadStream &stream) {
// If the stream has exactly the required number of bits for this image,
// we assume it is uncompressed.
if (stream.size() * 8 == _surface->pitch * _surface->h) {
- debugC(3, kDebugImages, "Skipping compression");
+ debugC(6, kDebugImages, "Skipping compression");
for (y = 0; y < _surface->h; y++) {
for (x = 0; x < _surface->pitch; ) {
byte color = stream.readByte();
@@ -301,7 +301,7 @@ bool BITDDecoderV4::loadStream(Common::SeekableReadStream &stream) {
}
int offset = 0;
- if (_surface->w < (pixels.size() / _surface->h))
+ if (_surface->w < (pixels.size() / _surface->h))
offset = (pixels.size() / _surface->h) - _surface->w;
if (pixels.size() > 0) {
@@ -316,7 +316,7 @@ bool BITDDecoderV4::loadStream(Common::SeekableReadStream &stream) {
}
case 8:
- //this calculation is wrong.. need a demo with colours.
+ // this calculation is wrong.. need a demo with colours.
*((byte *)_surface->getBasePtr(x, y)) = 0xff - pixels[(y * _surface->w) + x + (y * offset)];
x++;
break;
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index cf044f2072..6411c59d4f 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/system.h"
#include "director/lingo/lingo.h"
namespace Director {
@@ -27,141 +28,171 @@ namespace Director {
static struct BuiltinProto {
const char *name;
void (*func)(int);
- int minArgs;
+ int minArgs; // -1 -- arglist
int maxArgs;
bool parens;
} builtins[] = {
// Math
- { "abs", Lingo::b_abs, 1, 1, true }, // D2
- { "atan", Lingo::b_atan, 1, 1, true }, // D4
- { "cos", Lingo::b_cos, 1, 1, true }, // D4
- { "exp", Lingo::b_exp, 1, 1, true }, // D4
- { "float", Lingo::b_float, 1, 1, true }, // D4
- { "integer", Lingo::b_integer, 1, 1, true },
- { "log", Lingo::b_log, 1, 1, true }, // D4
- { "pi", Lingo::b_pi, 0, 0, true }, // D4
- { "power", Lingo::b_power, 2, 2, true }, // D4
- { "random", Lingo::b_random, 1, 1, true }, // D2
- { "sin", Lingo::b_sin, 1, 1, true },
- { "sqrt", Lingo::b_sqrt, 1, 1, true }, // D2
- { "tan", Lingo::b_tan, 1, 1, true }, // D4
+ { "abs", Lingo::b_abs, 1, 1, true }, // D2 function
+ { "atan", Lingo::b_atan, 1, 1, true }, // D4 f
+ { "cos", Lingo::b_cos, 1, 1, true }, // D4 f
+ { "exp", Lingo::b_exp, 1, 1, true }, // D4 f
+ { "float", Lingo::b_float, 1, 1, true }, // D4 f
+ { "integer", Lingo::b_integer, 1, 1, true }, // D3 f
+ { "log", Lingo::b_log, 1, 1, true }, // D4 f
+ { "pi", Lingo::b_pi, 0, 0, true }, // D4 f
+ { "power", Lingo::b_power, 2, 2, true }, // D4 f
+ { "random", Lingo::b_random, 1, 1, true }, // D2 f
+ { "sin", Lingo::b_sin, 1, 1, true }, // D4 f
+ { "sqrt", Lingo::b_sqrt, 1, 1, true }, // D2 f
+ { "tan", Lingo::b_tan, 1, 1, true }, // D4 f
// String
- { "chars", Lingo::b_chars, 3, 3, true }, // D2
- { "charToNum", Lingo::b_charToNum, 1, 1, true }, // D2
- { "delete", Lingo::b_delete, 1, 1, true }, // D3
- { "hilite", Lingo::b_hilite, 1, 1, true }, // D3
- { "length", Lingo::b_length, 1, 1, true }, // D2
- { "numToChar", Lingo::b_numToChar, 1, 1, true }, // D2
- { "offset", Lingo::b_offset, 2, 2, true }, // D2
- { "string", Lingo::b_string, 1, 1, true }, // D2
- { "value", Lingo::b_value, 1, 1, true }, // D2
+ { "chars", Lingo::b_chars, 3, 3, true }, // D2 f
+ { "charToNum", Lingo::b_charToNum, 1, 1, true }, // D2 f
+ { "delete", Lingo::b_delete, 1, 1, true }, // D3 c
+ { "hilite", Lingo::b_hilite, 1, 1, true }, // D3 c
+ { "length", Lingo::b_length, 1, 1, true }, // D2 f
+ { "numToChar", Lingo::b_numToChar, 1, 1, true }, // D2 f
+ { "offset", Lingo::b_offset, 2, 3, true }, // D2 f
+ { "string", Lingo::b_string, 1, 1, true }, // D2 f
+ { "value", Lingo::b_value, 1, 1, true }, // D2 f
// Lists
- { "add", Lingo::b_add, 2, 2, false }, // D4
- { "addAt", Lingo::b_addAt, 3, 3, false }, // D4
- { "addProp", Lingo::b_addProp, 3, 3, false }, // D4
- { "append", Lingo::b_append, 2, 2, false }, // D4
- { "count", Lingo::b_count, 1, 1, true }, // D4
- { "deleteAt", Lingo::b_deleteAt, 2, 2, false }, // D4
- { "deleteProp", Lingo::b_deleteProp, 2, 2, false }, // D4
- { "findPos", Lingo::b_findPos, 2, 2, true }, // D4
- { "findPosNear", Lingo::b_findPosNear, 2, 2, true }, // D4
- { "getaProp", Lingo::b_getaProp, 2, 2, true }, // D4
- { "getAt", Lingo::b_getAt, 2, 2, true }, // D4
- { "getLast", Lingo::b_getLast, 1, 1, true }, // D4
- { "getOne", Lingo::b_getOne, 2, 2, true }, // D4
- { "getPos", Lingo::b_getPos, 2, 2, true }, // D4
- { "getProp", Lingo::b_getProp, 2, 2, true }, // D4
- { "getPropAt", Lingo::b_getPropAt, 2, 2, true }, // D4
- { "list", Lingo::b_list, -1, 0, true }, // D4
- { "listP", Lingo::b_listP, 1, 1, true }, // D4
- { "max", Lingo::b_max, 1, 1, true }, // D4
- { "min", Lingo::b_min, 1, 1, true }, // D4
- { "setaProp", Lingo::b_setaProp, 3, 3, false }, // D4
- { "setAt", Lingo::b_setAt, 3, 3, false }, // D4
- { "setProp", Lingo::b_setProp, 3, 3, false }, // D4
- { "sort", Lingo::b_sort, 1, 1, false }, // D4
+ { "add", Lingo::b_add, 2, 2, false }, // D4 command
+ { "addAt", Lingo::b_addAt, 3, 3, false }, // D4 c
+ { "addProp", Lingo::b_addProp, 3, 3, false }, // D4 c
+ { "append", Lingo::b_append, 2, 2, false }, // D4 c
+ { "count", Lingo::b_count, 1, 1, true }, // D4 f
+ { "deleteAt", Lingo::b_deleteAt, 2, 2, false }, // D4 c
+ { "deleteProp", Lingo::b_deleteProp, 2, 2, false }, // D4 c
+ { "findPos", Lingo::b_findPos, 2, 2, true }, // D4 f
+ { "findPosNear", Lingo::b_findPosNear, 2, 2, true }, // D4 f
+ { "getaProp", Lingo::b_getaProp, 2, 2, true }, // D4 f
+ { "getAt", Lingo::b_getAt, 2, 2, true }, // D4 f
+ { "getLast", Lingo::b_getLast, 1, 1, true }, // D4 f
+ { "getOne", Lingo::b_getOne, 2, 2, true }, // D4 f
+ { "getPos", Lingo::b_getPos, 2, 2, true }, // D4 f
+ { "getProp", Lingo::b_getProp, 2, 2, true }, // D4 f
+ { "getPropAt", Lingo::b_getPropAt, 2, 2, true }, // D4 f
+ { "list", Lingo::b_list, -1, 0, true }, // D4 f
+ { "listP", Lingo::b_listP, 1, 1, true }, // D4 f
+ { "max", Lingo::b_max, 1, 1, true }, // D4 f
+ { "min", Lingo::b_min, 1, 1, true }, // D4 f
+ { "setaProp", Lingo::b_setaProp, 3, 3, false }, // D4 c
+ { "setAt", Lingo::b_setAt, 3, 3, false }, // D4 c
+ { "setProp", Lingo::b_setProp, 3, 3, false }, // D4 c
+ { "sort", Lingo::b_sort, 1, 1, false }, // D4 c
// Files
- { "closeDA", Lingo::b_closeDA, 0, 0, false }, // D2
- { "closeResFile", Lingo::b_closeResFile, 0, 1, false }, // D2
- { "closeXlib", Lingo::b_closeXlib, 0, 1, false }, // D2
- // open // D2
- { "openDA", Lingo::b_openDA, 1, 1, false }, // D2
- { "openResFile", Lingo::b_openResFile, 1, 1, false }, // D2
- { "openXlib", Lingo::b_openXlib, 1, 1, false }, // D2
- { "setCallBack", Lingo::b_setCallBack, 2, 2, false }, // D3
- { "showResFile", Lingo::b_showResFile, 0, 1, false }, // D2
- { "showXlib", Lingo::b_showXlib, 0, 1, false }, // D2
- { "xFactoryList", Lingo::b_xFactoryList, 1, 1, true }, // D3
+ { "closeDA", Lingo::b_closeDA, 0, 0, false }, // D2 c
+ { "closeResFile", Lingo::b_closeResFile, 0, 1, false }, // D2 c
+ { "closeXlib", Lingo::b_closeXlib, 0, 1, false }, // D2 c
+ { "getNthFileNameInFolder",Lingo::b_getNthFileNameInFolder,2,2,true },//D4 f
+ // open // D2 c
+ { "openDA", Lingo::b_openDA, 1, 1, false }, // D2 c
+ { "openResFile", Lingo::b_openResFile, 1, 1, false }, // D2 c
+ { "openXlib", Lingo::b_openXlib, 1, 1, false }, // D2 c
+ { "saveMovie", Lingo::b_saveMovie, 1, 1, false }, // D4 c
+ { "setCallBack", Lingo::b_setCallBack, 2, 2, false }, // D3 c
+ { "showResFile", Lingo::b_showResFile, 0, 1, false }, // D2 c
+ { "showXlib", Lingo::b_showXlib, 0, 1, false }, // D2 c
+ { "xFactoryList", Lingo::b_xFactoryList, 1, 1, true }, // D3 f
// Control
- { "abort", Lingo::b_abort, 0, 0, false }, // D4
- { "continue", Lingo::b_continue, 0, 0, false }, // D2
- { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2
- { "delay", Lingo::b_delay, 1, 1, false }, // D2
- { "do", Lingo::b_do, 1, 1, false }, // D2
- { "nothing", Lingo::b_nothing, 0, 0, false }, // D2
- { "pause", Lingo::b_pause, 0, 0, false }, // D2
- // play // D2
+ { "abort", Lingo::b_abort, 0, 0, false }, // D4 c
+ { "continue", Lingo::b_continue, 0, 0, false }, // D2 c
+ { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 c
+ { "delay", Lingo::b_delay, 1, 1, false }, // D2 c
+ { "do", Lingo::b_do, 1, 1, false }, // D2 c
+ { "halt", Lingo::b_halt, 0, 0, false }, // D4 c
+ { "nothing", Lingo::b_nothing, 0, 0, false }, // D2 c
+ { "pass", Lingo::b_pass, 0, 0, false }, // D4 c
+ { "pause", Lingo::b_pause, 0, 0, false }, // D2 c
+ // play // D2 c
{ "playAccel", Lingo::b_playAccel, -1,0, false }, // D2
// play done // D2
- { "preLoad", Lingo::b_preLoad, -1,0, false }, // D3
- { "preLoadCast", Lingo::b_preLoadCast, -1,0, false }, // D3
- { "quit", Lingo::b_quit, 0, 0, false }, // D2
- { "restart", Lingo::b_restart, 0, 0, false }, // D2
- { "shutDown", Lingo::b_shutDown, 0, 0, false }, // D2
- { "startTimer", Lingo::b_startTimer, 0, 0, false }, // D2
+ { "preLoad", Lingo::b_preLoad, -1,0, false }, // D3 c
+ { "preLoadCast", Lingo::b_preLoadCast, -1,0, false }, // D3 c
+ { "quit", Lingo::b_quit, 0, 0, false }, // D2 c
+ { "restart", Lingo::b_restart, 0, 0, false }, // D2 c
+ { "shutDown", Lingo::b_shutDown, 0, 0, false }, // D2 c
+ { "startTimer", Lingo::b_startTimer, 0, 0, false }, // D2 c
// when keyDown // D2
// when mouseDown // D2
// when mouseUp // D2
// when timeOut // D2
// Types
{ "floatP", Lingo::b_floatP, 1, 1, true }, // D3
- { "ilk", Lingo::b_ilk, 1, 2, false }, // D4
- { "integerp", Lingo::b_integerp, 1, 1, true }, // D2
- { "objectp", Lingo::b_objectp, 1, 1, true }, // D2
- { "stringp", Lingo::b_stringp, 1, 1, true }, // D2
- { "symbolp", Lingo::b_symbolp, 1, 1, true }, // D2
+ { "ilk", Lingo::b_ilk, 1, 2, false }, // D4 f
+ { "integerp", Lingo::b_integerp, 1, 1, true }, // D2 f
+ { "objectp", Lingo::b_objectp, 1, 1, true }, // D2 f
+ { "pictureP", Lingo::b_pictureP, 1, 1, true }, // D4 f
+ { "stringp", Lingo::b_stringp, 1, 1, true }, // D2 f
+ { "symbolp", Lingo::b_symbolp, 1, 1, true }, // D2 f
+ { "voidP", Lingo::b_voidP, 1, 1, true }, // D4 f
// Misc
- { "alert", Lingo::b_alert, 1, 1, false }, // D2
- { "cursor", Lingo::b_cursor, 1, 1, false }, // D2
- { "framesToHMS", Lingo::b_framesToHMS, 4, 4, false }, // D3
- { "HMStoFrames", Lingo::b_HMStoFrames, 4, 4, false }, // D3
- { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2
+ { "alert", Lingo::b_alert, 1, 1, false }, // D2 c
+ { "birth", Lingo::b_birth, -1,0, false }, // D4 f
+ { "clearGlobals", Lingo::b_clearGlobals, 0, 0, false }, // D4 c
+ { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 c
+ { "framesToHMS", Lingo::b_framesToHMS, 4, 4, false }, // D3 f
+ { "HMStoFrames", Lingo::b_HMStoFrames, 4, 4, false }, // D3 f
+ { "param", Lingo::b_param, 1, 1, true }, // D4 f
+ { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2 c
// put // D2
// set // D2
- { "showGlobals", Lingo::b_showGlobals, 0, 0, false }, // D2
- { "showLocals", Lingo::b_showLocals, 0, 0, false }, // D2
+ { "showGlobals", Lingo::b_showGlobals, 0, 0, false }, // D2 c
+ { "showLocals", Lingo::b_showLocals, 0, 0, false }, // D2 c
// Score
- { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2
- { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2
- { "duplicate-cast", Lingo::b_duplicateCast, 1, 2, false }, // D4
+ { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2 f
+ { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2 f
+ { "copyToClipBoard",Lingo::b_copyToClipBoard,1,1, false }, // D4 c
+ { "duplicate", Lingo::b_duplicate, 1, 2, false }, // D4 c
{ "editableText", Lingo::b_editableText, 0, 0, false }, // D2
- { "erase-cast", Lingo::b_eraseCast, 1, 2, false }, // D4
+ { "erase", Lingo::b_erase, 1, 1, false }, // D4 c
+ { "findEmpty", Lingo::b_findEmpty, 1, 1, true }, // D4 f
// go // D2
- { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2
- { "label", Lingo::b_label, 1, 1, true }, // D2
- { "marker", Lingo::b_marker, 1, 1, true }, // D2
+ { "importFileInto", Lingo::b_importFileInto,2, 2, false }, // D4 c
+ { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 c
+ { "label", Lingo::b_label, 1, 1, true }, // D2 f
+ { "marker", Lingo::b_marker, 1, 1, true }, // D2 f
+ { "move", Lingo::b_move, 1, 2, false }, // D4 c
{ "moveableSprite", Lingo::b_moveableSprite,0, 0, false }, // D2
- { "puppetPalette", Lingo::b_puppetPalette, -1,0, false }, // D2
- { "puppetSound", Lingo::b_puppetSound, -1,0, false }, // D2
- { "puppetSprite", Lingo::b_puppetSprite, -1,0, false }, // D2
- { "puppetTempo", Lingo::b_puppetTempo, 1, 1, false }, // D2
- { "puppetTransition",Lingo::b_puppetTransition,-1,0, false },// D2
- { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2
- { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2
- { "updateStage", Lingo::b_updateStage, 0, 0, false }, // D2
- { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2
+ { "pasteClipBoardInto",Lingo::b_pasteClipBoardInto,1, 1, false }, // D4 c
+ { "puppetPalette", Lingo::b_puppetPalette, -1,0, false }, // D2 c
+ { "puppetSound", Lingo::b_puppetSound, -1,0, false }, // D2 c
+ { "puppetSprite", Lingo::b_puppetSprite, -1,0, false }, // D2 c
+ { "puppetTempo", Lingo::b_puppetTempo, 1, 1, false }, // D2 c
+ { "puppetTransition",Lingo::b_puppetTransition,-1,0, false },// D2 c
+ { "ramNeeded", Lingo::b_ramNeeded, 2, 2, true }, // D4 f
+ { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2 f
+ { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2 c
+ { "unLoad", Lingo::b_unLoad, 0, 2, false }, // D4 c
+ { "unLoadCast", Lingo::b_unLoadCast, 0, 2, false }, // D4 c
+ { "updateStage", Lingo::b_updateStage, 0, 0, false }, // D2 c
+ { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2 c
// Point
- { "point", Lingo::b_point, 2, 2, true },
+ { "point", Lingo::b_point, 2, 2, true }, // D4 f
+ { "inside", Lingo::b_inside, 2, 2, true }, // D4 f
+ { "intersect", Lingo::b_intersect, 2, 2, false }, // D4 f
+ { "map", Lingo::b_map, 3, 3, true }, // D4 f
+ { "rect", Lingo::b_rect, 4, 4, true }, // D4 f
+ { "union", Lingo::b_union, 2, 2, true }, // D4 f
// Sound
{ "beep", Lingo::b_beep, 0, 1, false }, // D2
- { "mci", Lingo::b_mci, 1, 1, false },
+ { "mci", Lingo::b_mci, 1, 1, false }, // D4 c
{ "mciwait", Lingo::b_mciwait, 1, 1, false },
- { "sound-fadeIn", Lingo::b_soundFadeIn, 1, 2, false }, // D3
- { "sound-fadeOut", Lingo::b_soundFadeOut, 1, 2, false }, // D3
- { "sound-playFile", Lingo::b_soundPlayFile, 2, 2, false }, // D3
- { "sound-stop", Lingo::b_soundStop, 1, 1, false }, // D3
- { "soundBusy", Lingo::b_soundBusy, 1, 1, true }, // D3
+ { "sound-close", Lingo::b_soundClose, 1, 1, false }, // D4 c
+ { "sound-fadeIn", Lingo::b_soundFadeIn, 1, 2, false }, // D3 c
+ { "sound-fadeOut", Lingo::b_soundFadeOut, 1, 2, false }, // D3 c
+ { "sound-playFile", Lingo::b_soundPlayFile, 2, 2, false }, // D3 c
+ { "sound-stop", Lingo::b_soundStop, 1, 1, false }, // D3 c
+ { "soundBusy", Lingo::b_soundBusy, 1, 1, true }, // D3 f
+ // Window
+ { "close", Lingo::b_close, 1, 1, false }, // D4 c
+ { "forget", Lingo::b_forget, 1, 1, false }, // D4 c
+ { "inflate", Lingo::b_inflate, 3, 3, true }, // D4 f
+ { "moveToBack", Lingo::b_moveToBack, 1, 1, false }, // D4 c
+ { "moveToFront", Lingo::b_moveToFront, 1, 1, false }, // D4 c
// Constants
+ { "ancestor", Lingo::b_ancestor, 0, 0, false }, // D4
{ "backspace", Lingo::b_backspace, 0, 0, false }, // D2
{ "empty", Lingo::b_empty, 0, 0, false }, // D2
{ "enter", Lingo::b_enter, 0, 0, false }, // D2
@@ -172,26 +203,129 @@ static struct BuiltinProto {
{ "true", Lingo::b_true, 0, 0, false }, // D2
{ "version", Lingo::b_version, 0, 0, false }, // D3
// References
- { "field", Lingo::b_field, 1, 1, false }, // D3
+ { "cast", Lingo::b_cast, 1, 1, false }, // D4 f
+ { "field", Lingo::b_field, 1, 1, false }, // D3 f
{ "me", Lingo::b_me, -1,0, false }, // D3
-
+ { "script", Lingo::b_script, 1, 1, false }, // D4 f
+ { "window", Lingo::b_window, 1, 1, false }, // D4 f
{ 0, 0, 0, 0, false }
};
static const char *twoWordBuiltins[] = {
- "duplicate",
- "erase",
+ //"duplicate",
+ //"erase",
"sound",
0
};
+static const char *builtinFunctions[] = {
+ "abs",
+ "atan",
+ "backspace",
+ "birth",
+ "cast",
+ "chars",
+ "charToNum",
+ "constrainH",
+ "constrainV",
+ "cos",
+ "count",
+ "empty",
+ "enter",
+ "exp",
+ "false",
+ "field",
+ "findEmpty",
+ "findPos",
+ "findPosNear",
+ "float",
+ "framesToHMS",
+ "getaProp",
+ "getAt",
+ "getLast",
+ "getNthFileNameInFolder",
+ "getOne",
+ "getPos",
+ "getProp",
+ "getPropAt",
+ "HMStoFrames",
+ "ilk",
+ "inflate",
+ "inside",
+ "integer",
+ "integerp",
+ "intersect",
+ "label",
+ "length",
+ "list",
+ "listP",
+ "log",
+ "map",
+ "marker",
+ "max",
+ "min",
+ "numToChar",
+ "objectp",
+ "offset",
+ "param",
+ "pi",
+ "pictureP",
+ "point",
+ "power",
+ "ramNeeded",
+ "random",
+ "rect",
+ "rollOver",
+ "quote",
+ "return",
+ "script",
+ "sin",
+ "sqrt",
+ "soundBusy",
+ "string",
+ "stringp",
+ "symbolp",
+ "tab",
+ "tan",
+ "true",
+ "value",
+ "version",
+ "voidP",
+ "window",
+ "xFactoryList",
+ 0
+};
+
+static const char *builtinReferences[] = {
+ "cast",
+ "field",
+ "script",
+ "window",
+ 0
+};
+
+
+static const char *predefinedMethods[] = {
+ "mAtFrame", // D3
+ "mDescribe", // D3
+ "mDispose", // D3
+ "mGet", // D3
+ "mInstanceRespondsTo", // D3
+ "mMessageList", // D3
+ "mName", // D3
+ "mNew", // D3
+ "mPerform", // D3
+ "mPut", // D3
+ "mRespondsTo", // D3
+ 0
+};
+
void Lingo::initBuiltIns() {
for (BuiltinProto *blt = builtins; blt->name; blt++) {
Symbol *sym = new Symbol;
- sym->name = (char *)calloc(strlen(blt->name) + 1, 1);
- Common::strlcpy(sym->name, blt->name, strlen(blt->name));
+ sym->name = blt->name;
sym->type = BLTIN;
sym->nargs = blt->minArgs;
sym->maxArgs = blt->maxArgs;
@@ -203,11 +337,32 @@ void Lingo::initBuiltIns() {
_functions[(void *)sym->u.s] = new FuncDesc(blt->name, "");
}
+ for (const char **b = builtinFunctions; *b; b++) {
+ if (!_builtins.contains(*b))
+ error("Incorrectly setup builtinFunctions[]: %s", *b);
+
+ _builtins[*b]->type = FBLTIN;
+ }
+
+ for (const char **b = builtinReferences; *b; b++) {
+ if (!_builtins.contains(*b))
+ error("Incorrectly setup builtinReferences[]: %s", *b);
+
+ _builtins[*b]->type = RBLTIN;
+ }
+
for (const char **b = twoWordBuiltins; *b; b++)
_twoWordBuiltins[*b] = true;
+
+ // Set predefined methods
+ for (const char **b = predefinedMethods; *b; b++) {
+ Symbol *s = g_lingo->lookupVar(*b, true, true);
+ s->type = SYMBOL;
+ s->u.s = new Common::String(*b);
+ }
}
-void Lingo::printStubWithArglist(const char *funcname, int nargs) {
+void Lingo::printSTUBWithArglist(const char *funcname, int nargs) {
Common::String s(funcname);
s += '(';
@@ -438,6 +593,10 @@ void Lingo::b_numToChar(int nargs) {
}
void Lingo::b_offset(int nargs) {
+ if (nargs == 3) {
+ b_offsetRect(nargs);
+ return;
+ }
Datum target = g_lingo->pop();
Datum source = g_lingo->pop();
@@ -466,122 +625,122 @@ void Lingo::b_value(int nargs) {
// Lists
///////////////////
void Lingo::b_add(int nargs) {
- g_lingo->printStubWithArglist("b_add", nargs);
+ g_lingo->printSTUBWithArglist("b_add", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_addAt(int nargs) {
- g_lingo->printStubWithArglist("b_addAt", nargs);
+ g_lingo->printSTUBWithArglist("b_addAt", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_addProp(int nargs) {
- g_lingo->printStubWithArglist("b_addProp", nargs);
+ g_lingo->printSTUBWithArglist("b_addProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_append(int nargs) {
- g_lingo->printStubWithArglist("b_append", nargs);
+ g_lingo->printSTUBWithArglist("b_append", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_count(int nargs) {
- g_lingo->printStubWithArglist("b_count", nargs);
+ g_lingo->printSTUBWithArglist("b_count", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_deleteAt(int nargs) {
- g_lingo->printStubWithArglist("b_deleteAt", nargs);
+ g_lingo->printSTUBWithArglist("b_deleteAt", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_deleteProp(int nargs) {
- g_lingo->printStubWithArglist("b_deleteProp", nargs);
+ g_lingo->printSTUBWithArglist("b_deleteProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_findPos(int nargs) {
- g_lingo->printStubWithArglist("b_findPos", nargs);
+ g_lingo->printSTUBWithArglist("b_findPos", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_findPosNear(int nargs) {
- g_lingo->printStubWithArglist("b_findPosNear", nargs);
+ g_lingo->printSTUBWithArglist("b_findPosNear", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getaProp(int nargs) {
- g_lingo->printStubWithArglist("b_getaProp", nargs);
+ g_lingo->printSTUBWithArglist("b_getaProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getAt(int nargs) {
- g_lingo->printStubWithArglist("b_getAt", nargs);
+ g_lingo->printSTUBWithArglist("b_getAt", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getLast(int nargs) {
- g_lingo->printStubWithArglist("b_getLast", nargs);
+ g_lingo->printSTUBWithArglist("b_getLast", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getOne(int nargs) {
- g_lingo->printStubWithArglist("b_getOne", nargs);
+ g_lingo->printSTUBWithArglist("b_getOne", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getPos(int nargs) {
- g_lingo->printStubWithArglist("b_getPos", nargs);
+ g_lingo->printSTUBWithArglist("b_getPos", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getProp(int nargs) {
- g_lingo->printStubWithArglist("b_getProp", nargs);
+ g_lingo->printSTUBWithArglist("b_getProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_getPropAt(int nargs) {
- g_lingo->printStubWithArglist("b_getPropAt", nargs);
+ g_lingo->printSTUBWithArglist("b_getPropAt", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_list(int nargs) {
- g_lingo->printStubWithArglist("b_list", nargs);
+ g_lingo->printSTUBWithArglist("b_list", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_listP(int nargs) {
- g_lingo->printStubWithArglist("b_listP", nargs);
+ g_lingo->printSTUBWithArglist("b_listP", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_max(int nargs) {
- g_lingo->printStubWithArglist("b_max", nargs);
+ g_lingo->printSTUBWithArglist("b_max", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_min(int nargs) {
- g_lingo->printStubWithArglist("b_min", nargs);
+ g_lingo->printSTUBWithArglist("b_min", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_setaProp(int nargs) {
- g_lingo->printStubWithArglist("b_setaProp", nargs);
+ g_lingo->printSTUBWithArglist("b_setaProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_setAt(int nargs) {
- g_lingo->printStubWithArglist("b_setAt", nargs);
+ g_lingo->printSTUBWithArglist("b_setAt", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_setProp(int nargs) {
- g_lingo->printStubWithArglist("b_setProp", nargs);
+ g_lingo->printSTUBWithArglist("b_setProp", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_sort(int nargs) {
- g_lingo->printStubWithArglist("b_sort", nargs);
+ g_lingo->printSTUBWithArglist("b_sort", nargs);
g_lingo->dropStack(nargs);
}
@@ -613,6 +772,14 @@ void Lingo::b_closeXlib(int nargs) {
delete d.u.s;
}
+void Lingo::b_getNthFileNameInFolder(int nargs) {
+ g_lingo->printSTUBWithArglist("b_getNthFileNameInFolder", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
void Lingo::b_openDA(int nargs) {
Datum d = g_lingo->pop();
@@ -643,6 +810,12 @@ void Lingo::b_openXlib(int nargs) {
delete d.u.s;
}
+void Lingo::b_saveMovie(int nargs) {
+ g_lingo->printSTUBWithArglist("b_saveMovie", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_setCallBack(int nargs) {
warning("STUB: b_setCallBack");
}
@@ -681,11 +854,11 @@ void Lingo::b_xFactoryList(int nargs) {
// Control
///////////////////
void Lingo::b_abort(int nargs) {
- warning("STUB: b_continue");
+ warning("STUB: b_abort");
}
void Lingo::b_continue(int nargs) {
- warning("STUB: b_continue");
+ g_director->_playbackPaused = false;
}
void Lingo::b_dontPassEvent(int nargs) {
@@ -699,7 +872,8 @@ void Lingo::b_nothing(int nargs) {
void Lingo::b_delay(int nargs) {
Datum d = g_lingo->pop();
d.toInt();
- warning("STUB: b_delay(%d)", d.u.i);
+
+ g_director->getCurrentScore()->_nextFrameTime = g_system->getMillis() + (float)d.u.i / 60 * 1000;
}
void Lingo::b_do(int nargs) {
@@ -708,30 +882,42 @@ void Lingo::b_do(int nargs) {
warning("STUB: b_do(%s)", d.u.s->c_str());
}
+void Lingo::b_halt(int nargs) {
+ b_quit(nargs);
+
+ warning("Movie halted");
+}
+
+void Lingo::b_pass(int nargs) {
+ g_lingo->printSTUBWithArglist("b_pass", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_pause(int nargs) {
- warning("STUB: b_pause");
+ g_director->_playbackPaused = true;
}
void Lingo::b_playAccel(int nargs) {
- g_lingo->printStubWithArglist("b_playAccel", nargs);
+ g_lingo->printSTUBWithArglist("b_playAccel", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_preLoad(int nargs) {
- g_lingo->printStubWithArglist("b_preLoad", nargs);
+ g_lingo->printSTUBWithArglist("b_preLoad", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_preLoadCast(int nargs) {
- g_lingo->printStubWithArglist("b_preLoadCast", nargs);
+ g_lingo->printSTUBWithArglist("b_preLoadCast", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_framesToHMS(int nargs) {
- g_lingo->printStubWithArglist("b_framesToHMS", nargs);
+ g_lingo->printSTUBWithArglist("b_framesToHMS", nargs);
g_lingo->dropStack(nargs);
@@ -739,29 +925,42 @@ void Lingo::b_framesToHMS(int nargs) {
}
void Lingo::b_HMStoFrames(int nargs) {
- g_lingo->printStubWithArglist("b_HMStoFrames", nargs);
+ g_lingo->printSTUBWithArglist("b_HMStoFrames", nargs);
g_lingo->dropStack(nargs);
g_lingo->push(Datum(0));
}
+void Lingo::b_param(int nargs) {
+ g_lingo->printSTUBWithArglist("b_param", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_printFrom(int nargs) {
- g_lingo->printStubWithArglist("b_printFrom", nargs);
+ g_lingo->printSTUBWithArglist("b_printFrom", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_quit(int nargs) {
- warning("STUB: b_quit");
+ if (g_director->getCurrentScore())
+ g_director->getCurrentScore()->_stopPlay = true;
+
+ g_lingo->pushVoid();
}
void Lingo::b_restart(int nargs) {
- warning("STUB: b_restart");
+ b_quit(nargs);
+
+ warning("Computer restarts");
}
void Lingo::b_shutDown(int nargs) {
- warning("STUB: b_shutDown");
+ b_quit(nargs);
+
+ warning("Computer shuts down");
}
void Lingo::b_startTimer(int nargs) {
@@ -802,6 +1001,12 @@ void Lingo::b_objectp(int nargs) {
g_lingo->push(d);
}
+void Lingo::b_pictureP(int nargs) {
+ g_lingo->pop();
+ warning("STUB: b_pictureP");
+ g_lingo->push(Datum(0));
+}
+
void Lingo::b_stringp(int nargs) {
Datum d = g_lingo->pop();
int res = (d.type == STRING) ? 1 : 0;
@@ -818,6 +1023,14 @@ void Lingo::b_symbolp(int nargs) {
g_lingo->push(d);
}
+void Lingo::b_voidP(int nargs) {
+ Datum d = g_lingo->pop();
+ int res = (d.type == VOID) ? 1 : 0;
+ d.toInt();
+ d.u.i = res;
+ g_lingo->push(d);
+}
+
///////////////////
// Misc
@@ -832,6 +1045,20 @@ void Lingo::b_alert(int nargs) {
delete d.u.s;
}
+void Lingo::b_birth(int nargs) {
+ g_lingo->printSTUBWithArglist("b_birth", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_clearGlobals(int nargs) {
+ g_lingo->printSTUBWithArglist("b_clearGlobals", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_cursor(int nargs) {
Datum d = g_lingo->pop();
d.toInt();
@@ -873,8 +1100,14 @@ void Lingo::b_constrainV(int nargs) {
g_lingo->push(Datum(0));
}
-void Lingo::b_duplicateCast(int nargs) {
- g_lingo->printStubWithArglist("b_duplicateCast", nargs);
+void Lingo::b_copyToClipBoard(int nargs) {
+ g_lingo->printSTUBWithArglist("b_copyToClipBoard", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_duplicate(int nargs) {
+ g_lingo->printSTUBWithArglist("b_duplicate", nargs);
g_lingo->dropStack(nargs);
}
@@ -883,8 +1116,22 @@ void Lingo::b_editableText(int nargs) {
warning("STUB: b_editableText");
}
-void Lingo::b_eraseCast(int nargs) {
- g_lingo->printStubWithArglist("b_eraseCast", nargs);
+void Lingo::b_erase(int nargs) {
+ g_lingo->printSTUBWithArglist("b_erase", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_findEmpty(int nargs) {
+ g_lingo->printSTUBWithArglist("b_findEmpty", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_importFileInto(int nargs) {
+ g_lingo->printSTUBWithArglist("b_importFileInto", nargs);
g_lingo->dropStack(nargs);
}
@@ -909,15 +1156,27 @@ void Lingo::b_marker(int nargs) {
g_lingo->push(marker);
}
+void Lingo::b_move(int nargs) {
+ g_lingo->printSTUBWithArglist("b_move", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_moveableSprite(int nargs) {
Datum d = g_lingo->pop();
warning("STUB: b_moveableSprite(%d)", d.u.i);
}
+void Lingo::b_pasteClipBoardInto(int nargs) {
+ g_lingo->printSTUBWithArglist("b_pasteClipBoardInto", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
void Lingo::b_puppetPalette(int nargs) {
g_lingo->convertVOIDtoString(0, nargs);
- g_lingo->printStubWithArglist("b_puppetPalette", nargs);
+ g_lingo->printSTUBWithArglist("b_puppetPalette", nargs);
g_lingo->dropStack(nargs);
}
@@ -925,13 +1184,13 @@ void Lingo::b_puppetPalette(int nargs) {
void Lingo::b_puppetSound(int nargs) {
g_lingo->convertVOIDtoString(0, nargs);
- g_lingo->printStubWithArglist("b_puppetSound", nargs);
+ g_lingo->printSTUBWithArglist("b_puppetSound", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_puppetSprite(int nargs) {
- g_lingo->printStubWithArglist("b_puppetSprite", nargs);
+ g_lingo->printSTUBWithArglist("b_puppetSprite", nargs);
g_lingo->dropStack(nargs);
}
@@ -942,26 +1201,45 @@ void Lingo::b_puppetTempo(int nargs) {
}
void Lingo::b_puppetTransition(int nargs) {
- g_lingo->printStubWithArglist("b_puppetTransition", nargs);
+ g_lingo->printSTUBWithArglist("b_puppetTransition", nargs);
g_lingo->dropStack(nargs);
}
+void Lingo::b_ramNeeded(int nargs) {
+ Datum d = g_lingo->pop();
+ warning("STUB: b_ramNeeded(%d)", d.u.i);
+
+ g_lingo->push(Datum(0));
+}
+
void Lingo::b_rollOver(int nargs) {
Datum d = g_lingo->pop();
- warning("STUB: b_puppetTempo(%d)", d.u.i);
+ warning("STUB: b_rollOver(%d)", d.u.i);
g_lingo->push(Datum(0));
}
void Lingo::b_spriteBox(int nargs) {
- g_lingo->printStubWithArglist("b_spriteBox", nargs);
+ g_lingo->printSTUBWithArglist("b_spriteBox", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_unLoad(int nargs) {
+ g_lingo->printSTUBWithArglist("b_unLoad", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_unLoadCast(int nargs) {
+ g_lingo->printSTUBWithArglist("b_unLoadCast", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_zoomBox(int nargs) {
- g_lingo->printStubWithArglist("b_zoomBox", nargs);
+ g_lingo->printSTUBWithArglist("b_zoomBox", nargs);
g_lingo->dropStack(nargs);
}
@@ -971,6 +1249,35 @@ void Lingo::b_updateStage(int nargs) {
}
+///////////////////
+// Window
+///////////////////
+
+void Lingo::b_close(int nargs) {
+ g_lingo->printSTUBWithArglist("b_close", nargs);
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_forget(int nargs) {
+ g_lingo->printSTUBWithArglist("b_forget", nargs);
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_inflate(int nargs) {
+ g_lingo->printSTUBWithArglist("b_inflate", nargs);
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_moveToBack(int nargs) {
+ g_lingo->printSTUBWithArglist("b_moveToBack", nargs);
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_moveToFront(int nargs) {
+ g_lingo->printSTUBWithArglist("b_moveToFront", nargs);
+ g_lingo->dropStack(nargs);
+}
+
///////////////////
// Point
@@ -992,6 +1299,55 @@ void Lingo::b_point(int nargs) {
g_lingo->push(d);
}
+void Lingo::b_rect(int nargs) {
+ g_lingo->printSTUBWithArglist("b_rect", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+
+void Lingo::b_intersect(int nargs) {
+ g_lingo->printSTUBWithArglist("b_intersect", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_inside(int nargs) {
+ g_lingo->printSTUBWithArglist("b_inside", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_map(int nargs) {
+ g_lingo->printSTUBWithArglist("b_map", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_offsetRect(int nargs) {
+ g_lingo->printSTUBWithArglist("b_offsetRect", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
+void Lingo::b_union(int nargs) {
+ g_lingo->printSTUBWithArglist("b_union", nargs);
+
+ g_lingo->dropStack(nargs);
+
+ g_lingo->push(Datum(0));
+}
+
///////////////////
// Sound
@@ -1018,31 +1374,37 @@ void Lingo::b_mciwait(int nargs) {
}
void Lingo::b_soundBusy(int nargs) {
- g_lingo->printStubWithArglist("b_soundBusy", nargs);
+ g_lingo->printSTUBWithArglist("b_soundBusy", nargs);
+
+ g_lingo->dropStack(nargs);
+}
+
+void Lingo::b_soundClose(int nargs) {
+ g_lingo->printSTUBWithArglist("b_soundClose", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_soundFadeIn(int nargs) {
- g_lingo->printStubWithArglist("b_soundFadeIn", nargs);
+ g_lingo->printSTUBWithArglist("b_soundFadeIn", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_soundFadeOut(int nargs) {
- g_lingo->printStubWithArglist("b_soundFadeOut", nargs);
+ g_lingo->printSTUBWithArglist("b_soundFadeOut", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_soundPlayFile(int nargs) {
- g_lingo->printStubWithArglist("b_soundPlayFile", nargs);
+ g_lingo->printSTUBWithArglist("b_soundPlayFile", nargs);
g_lingo->dropStack(nargs);
}
void Lingo::b_soundStop(int nargs) {
- g_lingo->printStubWithArglist("b_soundStop", nargs);
+ g_lingo->printSTUBWithArglist("b_soundStop", nargs);
g_lingo->dropStack(nargs);
}
@@ -1050,6 +1412,11 @@ void Lingo::b_soundStop(int nargs) {
///////////////////
// Constants
///////////////////
+void Lingo::b_ancestor(int nargs) {
+ warning("STUB: b_ancestor");
+ g_lingo->push(Datum(0));
+}
+
void Lingo::b_backspace(int nargs) {
g_lingo->push(Datum(new Common::String("\b")));
}
@@ -1093,20 +1460,6 @@ void Lingo::b_factory(int nargs) {
// This is intentionally empty
}
-// TODO:
-// List of predefined methods in D3
-// mAtFrame
-// mDescribe
-// mDispose
-// mGet
-// mInstanceRespondsTo
-// mMessageList
-// mName
-// mNew
-// mPerform
-// mPut
-// mRespondsTo
-
void Lingo::factoryCall(Common::String &name, int nargs) {
Common::String s("factoryCall: ");
@@ -1114,7 +1467,7 @@ void Lingo::factoryCall(Common::String &name, int nargs) {
convertVOIDtoString(0, nargs);
- printStubWithArglist(s.c_str(), nargs);
+ printSTUBWithArglist(s.c_str(), nargs);
Datum method = _stack[_stack.size() - nargs + 0];
@@ -1139,15 +1492,65 @@ void Lingo::factoryCall(Common::String &name, int nargs) {
///////////////////
// References
///////////////////
+void Lingo::b_cast(int nargs) {
+ Datum d = g_lingo->pop();
+
+ warning("STUB: b_cast");
+
+ d.type = REFERENCE;
+
+ g_lingo->push(d);
+}
+
void Lingo::b_field(int nargs) {
- warning("STUB: b_field");
+ Datum d = g_lingo->pop();
+
+ int id;
+
+ if (d.type == STRING) {
+ if (g_director->getCurrentScore()->_castsNames.contains(*d.u.s))
+ id = g_director->getCurrentScore()->_castsNames[*d.u.s];
+ else
+ error("b_filed: Reference to non-existent field: %s", d.u.s->c_str());
+ } else if (d.type == INT || d.type == FLOAT) {
+ d.toInt();
+ id = d.u.i;
+ } else {
+ error("b_field: Incorrect reference type: %s", d.type2str());
+ }
+
+ d.u.i = id;
+
+ d.type = REFERENCE;
+
+ g_lingo->push(d);
}
void Lingo::b_me(int nargs) {
- g_lingo->printStubWithArglist("me", nargs);
+ g_lingo->printSTUBWithArglist("me", nargs);
g_lingo->dropStack(nargs);
}
+void Lingo::b_script(int nargs) {
+ Datum d = g_lingo->pop();
+
+ warning("STUB: b_script");
+
+ d.type = REFERENCE;
+
+ g_lingo->push(d);
+}
+
+void Lingo::b_window(int nargs) {
+ Datum d = g_lingo->pop();
+
+ warning("STUB: b_window");
+
+ d.type = REFERENCE;
+
+ g_lingo->push(d);
+}
+
} // End of namespace Director
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 1b45359ac5..48419862a6 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -43,6 +43,7 @@
// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
// THIS SOFTWARE.
+#include "director/cast.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-gr.h"
@@ -104,6 +105,7 @@ static struct FuncDescr {
{ Lingo::c_repeatwithcode,"c_repeatwithcode","ooooos" },
{ Lingo::c_exitRepeat, "c_exitRepeat", "" },
{ Lingo::c_ifcode, "c_ifcode", "oooi" },
+ { Lingo::c_tellcode, "c_tellcode", "o" },
{ Lingo::c_whencode, "c_whencode", "os" },
{ Lingo::c_goto, "c_goto", "" },
{ Lingo::c_gotoloop, "c_gotoloop", "" },
@@ -114,6 +116,7 @@ static struct FuncDescr {
{ Lingo::c_call, "c_call", "si" },
{ Lingo::c_procret, "c_procret", "" },
{ Lingo::c_global, "c_global", "s" },
+ { Lingo::c_property, "c_property", "s" },
{ Lingo::c_instance, "c_instance", "s" },
{ Lingo::c_open, "c_open", "" },
{ 0, 0, 0 }
@@ -140,7 +143,7 @@ void Lingo::pushVoid() {
Datum Lingo::pop(void) {
if (_stack.size() == 0)
- error("stack underflow");
+ assert(0);
Datum ret = _stack.back();
_stack.pop_back();
@@ -169,8 +172,8 @@ void Lingo::c_printtop(void) {
if (!d.u.sym) {
warning("Inconsistent stack: var, val: %d", d.u.i);
} else {
- if (d.u.sym->name)
- warning("var: %s", d.u.sym->name);
+ if (!d.u.sym->name.empty())
+ warning("var: %s", d.u.sym->name.c_str());
else
warning("Nameless var. val: %d", d.u.sym->u.i);
}
@@ -210,7 +213,7 @@ void Lingo::c_voidpush() {
void Lingo::c_fconstpush() {
Datum d;
inst i = (*g_lingo->_currentScript)[g_lingo->_pc];
- d.u.i = READ_UINT32(&i); // d.u.f value will be read
+ d.u.f = *(double *)(&i);
d.type = FLOAT;
g_lingo->_pc += g_lingo->calcCodeAlignment(sizeof(double));
@@ -297,14 +300,27 @@ void Lingo::c_assign() {
d1 = g_lingo->pop();
d2 = g_lingo->pop();
- if (d1.type != VAR) {
+ if (d1.type != VAR && d1.type != REFERENCE) {
warning("assignment to non-variable");
return;
}
+ if (d1.type == REFERENCE) {
+ if (!g_director->getCurrentScore()->_castsInfo.contains(d1.u.i)) {
+ warning("c_assign: Unknown REFERENCE %d", d1.u.i);
+ g_lingo->pushVoid();
+ return;
+ }
+
+ warning("STUB: c_assing REFERENCE");
+
+ g_lingo->push(d1);
+ return;
+ }
+
if (d1.u.sym->type != INT && d1.u.sym->type != VOID &&
d1.u.sym->type != FLOAT && d1.u.sym->type != STRING) {
- warning("assignment to non-variable '%s'", d1.u.sym->name);
+ warning("assignment to non-variable '%s'", d1.u.sym->name.c_str());
return;
}
@@ -339,14 +355,14 @@ void Lingo::c_assign() {
}
bool Lingo::verify(Symbol *s) {
- if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT) {
- warning("attempt to evaluate non-variable '%s'", s->name);
+ if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT && s->type != SYMBOL) {
+ warning("attempt to evaluate non-variable '%s'", s->name.c_str());
return false;
}
if (s->type == VOID)
- warning("Variable used before assigning a value '%s'", s->name);
+ warning("Variable used before assigning a value '%s'", s->name.c_str());
return true;
}
@@ -413,8 +429,6 @@ void Lingo::c_theentityassign() {
Datum d = g_lingo->pop();
g_lingo->setTheEntity(entity, id, field, d);
-
- g_lingo->push(d); // Dummy value
}
void Lingo::c_swap() {
@@ -824,7 +838,7 @@ void Lingo::c_repeatwhilecode(void) {
d.toInt();
while (d.u.i) {
- g_lingo->execute(body); /* body */
+ g_lingo->execute(body + savepc - 1); /* body */
if (g_lingo->_returning)
break;
@@ -839,7 +853,7 @@ void Lingo::c_repeatwhilecode(void) {
}
if (!g_lingo->_returning)
- g_lingo->_pc = end; /* next stmt */
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
}
void Lingo::c_repeatwithcode(void) {
@@ -858,14 +872,14 @@ void Lingo::c_repeatwithcode(void) {
error("Cast ref used as index: %s", countername.c_str());
}
- g_lingo->execute(init); /* condition */
+ g_lingo->execute(init + savepc - 1); /* condition */
d = g_lingo->pop();
d.toInt();
counter->u.i = d.u.i;
counter->type = INT;
while (true) {
- g_lingo->execute(body); /* body */
+ g_lingo->execute(body + savepc - 1); /* body */
if (g_lingo->_returning)
break;
@@ -875,7 +889,7 @@ void Lingo::c_repeatwithcode(void) {
}
counter->u.i += inc;
- g_lingo->execute(finish); /* condition */
+ g_lingo->execute(finish + savepc - 1); /* condition */
d = g_lingo->pop();
d.toInt();
@@ -884,9 +898,7 @@ void Lingo::c_repeatwithcode(void) {
}
if (!g_lingo->_returning)
- g_lingo->_pc = end; /* next stmt */
-
- delete counter;
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
}
void Lingo::c_exitRepeat(void) {
@@ -909,14 +921,14 @@ void Lingo::c_ifcode() {
if (d.toInt()) {
debugC(8, kDebugLingoExec, "executing then");
- g_lingo->execute(then);
+ g_lingo->execute(then + savepc - 1);
} else if (elsep) { /* else part? */
debugC(8, kDebugLingoExec, "executing else");
- g_lingo->execute(elsep);
+ g_lingo->execute(elsep + savepc - 1);
}
if (!g_lingo->_returning && !skipEnd) {
- g_lingo->_pc = end; /* next stmt */
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
debugC(8, kDebugLingoExec, "executing end");
} else {
debugC(8, kDebugLingoExec, "Skipped end");
@@ -926,15 +938,20 @@ void Lingo::c_ifcode() {
void Lingo::c_whencode() {
Datum d;
uint start = g_lingo->_pc;
- uint end = READ_UINT32(&(*g_lingo->_currentScript)[start]);
+ uint end = READ_UINT32(&(*g_lingo->_currentScript)[start]) + start - 1;
Common::String eventname((char *)&(*g_lingo->_currentScript)[start + 1]);
start += g_lingo->calcStringAlignment(eventname.c_str()) + 1;
debugC(3, kDebugLingoExec, "c_whencode([%5d][%5d], %s)", start, end, eventname.c_str());
+ int entity = g_lingo->_currentEntityId;
+ g_lingo->_currentEntityId = 0;
+
g_lingo->define(eventname, start, 0, NULL, end);
+ g_lingo->_currentEntityId = entity;
+
if (debugChannelSet(3, kDebugLingoExec)) {
uint pc = start;
while (pc <= end) {
@@ -946,6 +963,11 @@ void Lingo::c_whencode() {
g_lingo->_pc = end;
}
+void Lingo::c_tellcode() {
+ warning("STUB: c_tellcode");
+}
+
+
//************************
// Built-in functions
//************************
@@ -1030,7 +1052,8 @@ void Lingo::call(Common::String name, int nargs) {
warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs);
dropArgs = true;
} else {
- if (sym->type == BLTIN && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) {
+ if ((sym->type == BLTIN || sym->type == FBLTIN || sym->type == RBLTIN)
+ && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) {
if (sym->nargs == sym->maxArgs)
warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs);
else
@@ -1057,12 +1080,25 @@ void Lingo::call(Common::String name, int nargs) {
g_lingo->pop();
}
- if (sym->type == BLTIN) {
- if (sym->u.bltin == b_factory)
+ if (sym->type == BLTIN || sym->type == FBLTIN || sym->type == RBLTIN) {
+ if (sym->u.bltin == b_factory) {
g_lingo->factoryCall(name, nargs);
- else
+ } else {
+ int stackSize = _stack.size() - nargs;
+
(*sym->u.bltin)(nargs);
+ int stackNewSize = _stack.size();
+
+ if (sym->type == FBLTIN || sym->type == RBLTIN) {
+ if (stackNewSize - stackSize != 1)
+ warning("built-in function %s did not return value", name.c_str());
+ } else {
+ if (stackNewSize - stackSize != 0)
+ warning("built-in procedure %s returned extra %d values", name.c_str(), stackNewSize - stackSize);
+ }
+ }
+
return;
}
@@ -1095,7 +1131,7 @@ void Lingo::call(Common::String name, int nargs) {
void Lingo::c_procret() {
if (!g_lingo->_callstack.size()) {
- warning("Call stack underflow");
+ warning("c_procret: Call stack underflow");
g_lingo->_returning = true;
return;
}
@@ -1130,8 +1166,14 @@ void Lingo::c_global() {
s->global = true;
g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str());
+}
+
+void Lingo::c_property() {
+ Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]);
+
+ g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str());
- delete s;
+ warning("STUB: c_property()");
}
void Lingo::c_instance() {
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 32d0bbbc11..8347d934b1 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -103,7 +103,7 @@ Common::String Lingo::decodeInstruction(uint pc, uint *newPc) {
{
Datum d;
i = (*_currentScript)[pc++];
- d.u.i = READ_UINT32(&i);
+ d.u.f = *(double *)(&i);
res += Common::String::format(" %f", d.u.f);
break;
@@ -142,7 +142,7 @@ Common::String Lingo::decodeInstruction(uint pc, uint *newPc) {
}
Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) {
- Symbol *sym;
+ Symbol *sym = nullptr;
// Looking for the cast member constants
if (_vm->getVersion() < 4) { // TODO: There could be a flag 'Allow Outdated Lingo' in Movie Info in D4
@@ -165,17 +165,21 @@ Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) {
}
}
- if (!_localvars->contains(name)) { // Create variable if it was not defined
+ if (!_localvars || !_localvars->contains(name)) { // Create variable if it was not defined
+ // Check if it is a global symbol
+ if (_globalvars.contains(name) && _globalvars[name]->type == SYMBOL)
+ return _globalvars[name];
+
if (!create)
return NULL;
sym = new Symbol;
- sym->name = (char *)calloc(strlen(name) + 1, 1);
- Common::strlcpy(sym->name, name, strlen(name) + 1);
+ sym->name = name;
sym->type = VOID;
sym->u.i = 0;
- (*_localvars)[name] = sym;
+ if (_localvars)
+ (*_localvars)[name] = sym;
if (putInGlobalList) {
sym->global = true;
@@ -197,9 +201,7 @@ void Lingo::cleanLocalVars() {
for (SymbolHash::const_iterator h = _localvars->begin(); h != _localvars->end(); ++h) {
if (!h->_value->global) {
- Symbol *sym = h->_value;
- free(sym->name);
- delete sym;
+ delete h->_value;
}
}
@@ -218,14 +220,17 @@ void Lingo::define(Common::String &name, int start, int nargs, Common::String *p
if (sym == NULL) { // Create variable if it was not defined
sym = new Symbol;
- sym->name = (char *)calloc(name.size() + 1, 1);
- Common::strlcpy(sym->name, name.c_str(), name.size() + 1);
+ sym->name = name;
sym->type = HANDLER;
- _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym;
+ if (!_eventHandlerTypeIds.contains(name)) {
+ _builtins[name] = sym;
+ } else {
+ _handlers[ENTITY_INDEX(_eventHandlerTypeIds[name.c_str()], _currentEntityId)] = sym;
+ }
} else {
- //we don't want to be here. The getHandler call should have used the EntityId and the result
- //should have been unique!
+ // we don't want to be here. The getHandler call should have used the EntityId and the result
+ // should have been unique!
warning("Redefining handler '%s'", name.c_str());
delete sym->u.defn;
}
@@ -375,6 +380,9 @@ void Lingo::processIf(int elselabel, int endlabel) {
if (!label)
break;
+ if (else1)
+ else1 = else1 - label;
+
WRITE_UINT32(&ielse1, else1);
(*_currentScript)[label + 2] = ielse1; /* elsepart */
(*_currentScript)[label + 3] = iend; /* end, if cond fails */
@@ -388,8 +396,7 @@ void Lingo::codeFactory(Common::String &name) {
Symbol *sym = new Symbol;
- sym->name = (char *)calloc(name.size() + 1, 1);
- Common::strlcpy(sym->name, name.c_str(), name.size());
+ sym->name = name;
sym->type = BLTIN;
sym->nargs = -1;
sym->maxArgs = 0;
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index 140549be8b..ddc51f4149 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -20,13 +20,16 @@
*
*/
-#include "director/lingo/lingo.h"
-#include "common/file.h"
#include "audio/decoders/wave.h"
+#include "common/file.h"
+#include "common/macresman.h"
#include "common/util.h"
+
+#include "graphics/macgui/macwindowmanager.h"
+
+#include "director/lingo/lingo.h"
#include "director/lingo/lingo-gr.h"
#include "director/sound.h"
-#include "graphics/macgui/macwindowmanager.h"
namespace Director {
@@ -169,73 +172,105 @@ void Lingo::func_mciwait(Common::String &s) {
}
void Lingo::func_goto(Datum &frame, Datum &movie) {
+ g_director->_playbackPaused = false;
+
+ if (!_vm->getCurrentScore())
+ return;
+
if (movie.type != VOID) {
movie.toString();
- Common::File file;
+ bool fileExists = false;
+
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ Common::MacResManager resMan;
+ if (resMan.open(*movie.u.s)) {
+ fileExists = true;
+ }
+ } else {
+ Common::File file;
+ if (file.open(*movie.u.s)) {
+ fileExists = true;
+ }
+ }
- if (!file.open(*movie.u.s)) {
+ if (!fileExists) {
warning("Movie %s does not exist", movie.u.s->c_str());
return;
}
- restartLingo();
+ _vm->_nextMovie = *movie.u.s;
+ _vm->getCurrentScore()->_stopPlay = true;
- delete _vm->_currentScore;
+ _vm->_nextMovieFrameS.clear();
+ _vm->_nextMovieFrameI = -1;
- Archive *mov = _vm->openMainArchive(*movie.u.s);
+ if (frame.type == VOID)
+ return;
- _vm->_currentScore = new Score(_vm, mov);
- debug(0, "Score name %s", _vm->_currentScore->getMacName().c_str());
- _vm->_currentScore->loadArchive();
- }
+ if (frame.type == STRING) {
+ _vm->_nextMovieFrameS = *frame.u.s;
+ return;
+ }
+
+ frame.toInt();
+
+ _vm->_nextMovieFrameI = frame.u.i;
- if (!_vm->_currentScore) {
- warning("func_goto: No score is loaded");
return;
}
if (frame.type == VOID)
return;
+ _vm->_skipFrameAdvance = true;
+
if (frame.type == STRING) {
- _vm->_currentScore->setStartToLabel(*frame.u.s);
+ if (_vm->getCurrentScore())
+ _vm->getCurrentScore()->setStartToLabel(*frame.u.s);
return;
}
frame.toInt();
- _vm->_currentScore->setCurrentFrame(frame.u.i);
+ if (_vm->getCurrentScore())
+ _vm->getCurrentScore()->setCurrentFrame(frame.u.i);
}
void Lingo::func_gotoloop() {
- if (!_vm->_currentScore)
+ if (!_vm->getCurrentScore())
return;
- _vm->_currentScore->gotoLoop();
+ _vm->getCurrentScore()->gotoLoop();
+
+ g_director->_skipFrameAdvance = true;
}
void Lingo::func_gotonext() {
- if (!_vm->_currentScore)
+ if (!_vm->getCurrentScore())
return;
- _vm->_currentScore->gotoNext();
+ _vm->getCurrentScore()->gotoNext();
+
+ g_director->_skipFrameAdvance = true;
}
-
+
void Lingo::func_gotoprevious() {
- if (!_vm->_currentScore)
+ if (!_vm->getCurrentScore())
return;
- _vm->_currentScore->gotoPrevious();
+ _vm->getCurrentScore()->gotoPrevious();
+
+ g_director->_skipFrameAdvance = true;
}
void Lingo::func_cursor(int c) {
if (_cursorOnStack) {
- //pop cursor
+ // pop cursor
_vm->getMacWindowManager()->popCursor();
}
- //and then push cursor.
+ // and then push cursor.
switch (c) {
case 0:
case -1:
@@ -266,6 +301,9 @@ void Lingo::func_beep(int repeats) {
}
int Lingo::func_marker(int m) {
+ if (!_vm->getCurrentScore())
+ return 0;
+
int labelNumber = _vm->getCurrentScore()->getCurrentLabelNumber();
if (m != 0) {
if (m < 0) {
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 3e01ed0680..da928f7c09 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -74,76 +74,85 @@
RECT = 263,
ARRAY = 264,
OBJECT = 265,
- INT = 266,
- THEENTITY = 267,
- THEENTITYWITHID = 268,
- FLOAT = 269,
- BLTIN = 270,
- BLTINNOARGS = 271,
- BLTINNOARGSORONE = 272,
- BLTINONEARG = 273,
- BLTINARGLIST = 274,
- TWOWORDBUILTIN = 275,
- ID = 276,
- STRING = 277,
- HANDLER = 278,
- SYMBOL = 279,
- ENDCLAUSE = 280,
- tPLAYACCEL = 281,
- tDOWN = 282,
- tELSE = 283,
- tNLELSIF = 284,
- tEXIT = 285,
- tFRAME = 286,
- tGLOBAL = 287,
- tGO = 288,
- tIF = 289,
- tINTO = 290,
- tLOOP = 291,
- tMACRO = 292,
- tMOVIE = 293,
- tNEXT = 294,
- tOF = 295,
- tPREVIOUS = 296,
- tPUT = 297,
- tREPEAT = 298,
- tSET = 299,
- tTHEN = 300,
- tTO = 301,
- tWHEN = 302,
- tWITH = 303,
- tWHILE = 304,
- tNLELSE = 305,
- tFACTORY = 306,
- tMETHOD = 307,
- tOPEN = 308,
- tPLAY = 309,
- tDONE = 310,
- tINSTANCE = 311,
- tGE = 312,
- tLE = 313,
- tGT = 314,
- tLT = 315,
- tEQ = 316,
- tNEQ = 317,
- tAND = 318,
- tOR = 319,
- tNOT = 320,
- tMOD = 321,
- tAFTER = 322,
- tBEFORE = 323,
- tCONCAT = 324,
- tCONTAINS = 325,
- tSTARTS = 326,
- tCHAR = 327,
- tITEM = 328,
- tLINE = 329,
- tWORD = 330,
- tSPRITE = 331,
- tINTERSECTS = 332,
- tWITHIN = 333,
- tON = 334,
- tME = 335
+ REFERENCE = 266,
+ INT = 267,
+ THEENTITY = 268,
+ THEENTITYWITHID = 269,
+ FLOAT = 270,
+ BLTIN = 271,
+ BLTINNOARGS = 272,
+ BLTINNOARGSORONE = 273,
+ BLTINONEARG = 274,
+ BLTINARGLIST = 275,
+ TWOWORDBUILTIN = 276,
+ FBLTIN = 277,
+ FBLTINNOARGS = 278,
+ FBLTINONEARG = 279,
+ FBLTINARGLIST = 280,
+ RBLTIN = 281,
+ RBLTINONEARG = 282,
+ ID = 283,
+ STRING = 284,
+ HANDLER = 285,
+ SYMBOL = 286,
+ ENDCLAUSE = 287,
+ tPLAYACCEL = 288,
+ tDOWN = 289,
+ tELSE = 290,
+ tNLELSIF = 291,
+ tEXIT = 292,
+ tFRAME = 293,
+ tGLOBAL = 294,
+ tGO = 295,
+ tIF = 296,
+ tINTO = 297,
+ tLOOP = 298,
+ tMACRO = 299,
+ tMOVIE = 300,
+ tNEXT = 301,
+ tOF = 302,
+ tPREVIOUS = 303,
+ tPUT = 304,
+ tREPEAT = 305,
+ tSET = 306,
+ tTHEN = 307,
+ tTO = 308,
+ tWHEN = 309,
+ tWITH = 310,
+ tWHILE = 311,
+ tNLELSE = 312,
+ tFACTORY = 313,
+ tMETHOD = 314,
+ tOPEN = 315,
+ tPLAY = 316,
+ tDONE = 317,
+ tINSTANCE = 318,
+ tGE = 319,
+ tLE = 320,
+ tGT = 321,
+ tLT = 322,
+ tEQ = 323,
+ tNEQ = 324,
+ tAND = 325,
+ tOR = 326,
+ tNOT = 327,
+ tMOD = 328,
+ tAFTER = 329,
+ tBEFORE = 330,
+ tCONCAT = 331,
+ tCONTAINS = 332,
+ tSTARTS = 333,
+ tCHAR = 334,
+ tITEM = 335,
+ tLINE = 336,
+ tWORD = 337,
+ tSPRITE = 338,
+ tINTERSECTS = 339,
+ tWITHIN = 340,
+ tTELL = 341,
+ tPROPERTY = 342,
+ tON = 343,
+ tME = 344
};
#endif
/* Tokens. */
@@ -155,76 +164,85 @@
#define RECT 263
#define ARRAY 264
#define OBJECT 265
-#define INT 266
-#define THEENTITY 267
-#define THEENTITYWITHID 268
-#define FLOAT 269
-#define BLTIN 270
-#define BLTINNOARGS 271
-#define BLTINNOARGSORONE 272
-#define BLTINONEARG 273
-#define BLTINARGLIST 274
-#define TWOWORDBUILTIN 275
-#define ID 276
-#define STRING 277
-#define HANDLER 278
-#define SYMBOL 279
-#define ENDCLAUSE 280
-#define tPLAYACCEL 281
-#define tDOWN 282
-#define tELSE 283
-#define tNLELSIF 284
-#define tEXIT 285
-#define tFRAME 286
-#define tGLOBAL 287
-#define tGO 288
-#define tIF 289
-#define tINTO 290
-#define tLOOP 291
-#define tMACRO 292
-#define tMOVIE 293
-#define tNEXT 294
-#define tOF 295
-#define tPREVIOUS 296
-#define tPUT 297
-#define tREPEAT 298
-#define tSET 299
-#define tTHEN 300
-#define tTO 301
-#define tWHEN 302
-#define tWITH 303
-#define tWHILE 304
-#define tNLELSE 305
-#define tFACTORY 306
-#define tMETHOD 307
-#define tOPEN 308
-#define tPLAY 309
-#define tDONE 310
-#define tINSTANCE 311
-#define tGE 312
-#define tLE 313
-#define tGT 314
-#define tLT 315
-#define tEQ 316
-#define tNEQ 317
-#define tAND 318
-#define tOR 319
-#define tNOT 320
-#define tMOD 321
-#define tAFTER 322
-#define tBEFORE 323
-#define tCONCAT 324
-#define tCONTAINS 325
-#define tSTARTS 326
-#define tCHAR 327
-#define tITEM 328
-#define tLINE 329
-#define tWORD 330
-#define tSPRITE 331
-#define tINTERSECTS 332
-#define tWITHIN 333
-#define tON 334
-#define tME 335
+#define REFERENCE 266
+#define INT 267
+#define THEENTITY 268
+#define THEENTITYWITHID 269
+#define FLOAT 270
+#define BLTIN 271
+#define BLTINNOARGS 272
+#define BLTINNOARGSORONE 273
+#define BLTINONEARG 274
+#define BLTINARGLIST 275
+#define TWOWORDBUILTIN 276
+#define FBLTIN 277
+#define FBLTINNOARGS 278
+#define FBLTINONEARG 279
+#define FBLTINARGLIST 280
+#define RBLTIN 281
+#define RBLTINONEARG 282
+#define ID 283
+#define STRING 284
+#define HANDLER 285
+#define SYMBOL 286
+#define ENDCLAUSE 287
+#define tPLAYACCEL 288
+#define tDOWN 289
+#define tELSE 290
+#define tNLELSIF 291
+#define tEXIT 292
+#define tFRAME 293
+#define tGLOBAL 294
+#define tGO 295
+#define tIF 296
+#define tINTO 297
+#define tLOOP 298
+#define tMACRO 299
+#define tMOVIE 300
+#define tNEXT 301
+#define tOF 302
+#define tPREVIOUS 303
+#define tPUT 304
+#define tREPEAT 305
+#define tSET 306
+#define tTHEN 307
+#define tTO 308
+#define tWHEN 309
+#define tWITH 310
+#define tWHILE 311
+#define tNLELSE 312
+#define tFACTORY 313
+#define tMETHOD 314
+#define tOPEN 315
+#define tPLAY 316
+#define tDONE 317
+#define tINSTANCE 318
+#define tGE 319
+#define tLE 320
+#define tGT 321
+#define tLT 322
+#define tEQ 323
+#define tNEQ 324
+#define tAND 325
+#define tOR 326
+#define tNOT 327
+#define tMOD 328
+#define tAFTER 329
+#define tBEFORE 330
+#define tCONCAT 331
+#define tCONTAINS 332
+#define tSTARTS 333
+#define tCHAR 334
+#define tITEM 335
+#define tLINE 336
+#define tWORD 337
+#define tSPRITE 338
+#define tINTERSECTS 339
+#define tWITHIN 340
+#define tTELL 341
+#define tPROPERTY 342
+#define tON 343
+#define tME 344
@@ -292,7 +310,7 @@ typedef union YYSTYPE
Common::Array<double> *arr;
}
/* Line 193 of yacc.c. */
-#line 296 "engines/director/lingo/lingo-gr.cpp"
+#line 314 "engines/director/lingo/lingo-gr.cpp"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -305,7 +323,7 @@ typedef union YYSTYPE
/* Line 216 of yacc.c. */
-#line 309 "engines/director/lingo/lingo-gr.cpp"
+#line 327 "engines/director/lingo/lingo-gr.cpp"
#ifdef short
# undef short
@@ -518,22 +536,22 @@ union yyalloc
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 113
+#define YYFINAL 123
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 1633
+#define YYLAST 1879
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 96
+#define YYNTOKENS 105
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 41
+#define YYNNTS 44
/* YYNRULES -- Number of rules. */
-#define YYNRULES 151
+#define YYNRULES 163
/* YYNRULES -- Number of states. */
-#define YYNSTATES 333
+#define YYNSTATES 358
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 335
+#define YYMAXUTOK 344
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -542,15 +560,15 @@ union yyalloc
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 88, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 97, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 87, 82, 2,
- 89, 90, 85, 83, 95, 84, 2, 86, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 96, 91, 2,
+ 98, 99, 94, 92, 104, 93, 2, 95, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 92, 81, 91, 2, 2, 2, 2, 2, 2, 2,
+ 101, 90, 100, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 93, 2, 94, 2, 2, 2, 2, 2, 2,
+ 2, 102, 2, 103, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -574,7 +592,8 @@ static const yytype_uint8 yytranslate[] =
45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89
};
#if YYDEBUG
@@ -583,106 +602,112 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 7, 9, 12, 14, 15, 17, 19,
- 21, 26, 31, 36, 41, 46, 52, 57, 62, 68,
- 70, 72, 74, 76, 84, 95, 107, 111, 119, 130,
- 141, 148, 159, 170, 171, 175, 178, 180, 183, 185,
- 192, 194, 201, 203, 207, 211, 214, 218, 220, 222,
- 223, 224, 225, 228, 231, 235, 237, 239, 241, 243,
- 245, 250, 252, 254, 257, 259, 263, 267, 271, 275,
- 279, 283, 287, 291, 295, 299, 303, 307, 310, 314,
- 318, 322, 326, 329, 332, 336, 340, 345, 350, 355,
- 362, 367, 374, 379, 386, 391, 398, 401, 403, 405,
- 408, 410, 413, 416, 419, 422, 424, 429, 432, 437,
- 444, 449, 452, 456, 458, 462, 464, 468, 471, 474,
- 477, 480, 484, 487, 490, 492, 496, 499, 502, 505,
- 509, 512, 513, 517, 518, 527, 530, 531, 540, 541,
- 542, 553, 554, 556, 560, 565, 566, 569, 570, 572,
- 576, 578
+ 21, 26, 31, 36, 41, 46, 51, 57, 62, 67,
+ 73, 75, 77, 79, 81, 89, 100, 112, 116, 123,
+ 128, 136, 147, 158, 165, 176, 187, 188, 192, 195,
+ 197, 200, 202, 209, 211, 218, 220, 224, 228, 231,
+ 235, 237, 239, 240, 241, 242, 245, 248, 252, 254,
+ 256, 258, 260, 262, 264, 267, 270, 275, 280, 282,
+ 284, 287, 289, 293, 297, 301, 305, 309, 313, 317,
+ 321, 325, 329, 333, 337, 340, 344, 348, 352, 356,
+ 359, 362, 366, 370, 375, 380, 385, 392, 397, 404,
+ 409, 416, 421, 428, 431, 434, 436, 438, 441, 443,
+ 446, 449, 452, 454, 457, 460, 462, 465, 470, 475,
+ 482, 487, 490, 494, 496, 500, 502, 506, 508, 512,
+ 515, 518, 521, 524, 528, 531, 534, 536, 540, 543,
+ 546, 549, 553, 556, 557, 561, 562, 571, 574, 575,
+ 584, 585, 586, 597, 598, 600, 604, 609, 610, 613,
+ 614, 616, 620, 622
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int16 yyrhs[] =
{
- 97, 0, -1, 97, 98, 99, -1, 99, -1, 1,
- 98, -1, 88, -1, -1, 127, -1, 134, -1, 102,
- -1, 42, 118, 35, 21, -1, 42, 118, 67, 118,
- -1, 42, 118, 68, 118, -1, 44, 21, 81, 118,
- -1, 44, 12, 81, 118, -1, 44, 13, 118, 81,
- 118, -1, 44, 21, 46, 118, -1, 44, 12, 46,
- 118, -1, 44, 13, 118, 46, 118, -1, 118, -1,
- 119, -1, 101, -1, 103, -1, 110, 89, 109, 90,
- 116, 115, 25, -1, 111, 81, 118, 115, 46, 118,
- 115, 116, 115, 25, -1, 111, 81, 118, 115, 27,
- 46, 118, 115, 116, 115, 25, -1, 117, 118, 115,
- -1, 112, 109, 45, 98, 116, 115, 25, -1, 112,
- 109, 45, 98, 116, 115, 50, 116, 115, 25, -1,
- 112, 109, 45, 98, 116, 115, 114, 105, 115, 25,
- -1, 112, 109, 45, 114, 101, 115, -1, 112, 109,
- 45, 114, 101, 115, 50, 114, 101, 115, -1, 112,
- 109, 45, 114, 101, 115, 106, 115, 104, 115, -1,
- -1, 50, 114, 101, -1, 105, 108, -1, 108, -1,
- 106, 107, -1, 107, -1, 113, 109, 45, 114, 102,
- 115, -1, 106, -1, 113, 109, 45, 114, 116, 115,
- -1, 118, -1, 118, 81, 118, -1, 89, 109, 90,
- -1, 43, 49, -1, 43, 48, 21, -1, 34, -1,
- 29, -1, -1, -1, -1, 116, 98, -1, 116, 102,
- -1, 47, 21, 45, -1, 11, -1, 14, -1, 24,
- -1, 22, -1, 16, -1, 21, 89, 135, 90, -1,
- 21, -1, 12, -1, 13, 118, -1, 100, -1, 118,
- 83, 118, -1, 118, 84, 118, -1, 118, 85, 118,
- -1, 118, 86, 118, -1, 118, 66, 118, -1, 118,
- 91, 118, -1, 118, 92, 118, -1, 118, 62, 118,
- -1, 118, 57, 118, -1, 118, 58, 118, -1, 118,
- 63, 118, -1, 118, 64, 118, -1, 65, 118, -1,
- 118, 82, 118, -1, 118, 69, 118, -1, 118, 70,
- 118, -1, 118, 71, 118, -1, 83, 118, -1, 84,
- 118, -1, 89, 118, 90, -1, 93, 135, 94, -1,
- 76, 118, 77, 118, -1, 76, 118, 78, 118, -1,
- 72, 118, 40, 118, -1, 72, 118, 46, 118, 40,
- 118, -1, 73, 118, 40, 118, -1, 73, 118, 46,
- 118, 40, 118, -1, 74, 118, 40, 118, -1, 74,
- 118, 46, 118, 40, 118, -1, 75, 118, 40, 118,
- -1, 75, 118, 46, 118, 40, 118, -1, 42, 118,
- -1, 122, -1, 125, -1, 30, 43, -1, 30, -1,
- 32, 120, -1, 56, 121, -1, 18, 118, -1, 17,
- 118, -1, 17, -1, 19, 89, 135, 90, -1, 19,
- 135, -1, 80, 89, 21, 90, -1, 80, 89, 21,
- 95, 135, 90, -1, 53, 118, 48, 118, -1, 53,
- 118, -1, 20, 21, 135, -1, 21, -1, 120, 95,
- 21, -1, 21, -1, 121, 95, 21, -1, 33, 36,
- -1, 33, 39, -1, 33, 41, -1, 33, 123, -1,
- 33, 123, 124, -1, 33, 124, -1, 31, 118, -1,
- 118, -1, 40, 38, 118, -1, 38, 118, -1, 54,
- 55, -1, 54, 123, -1, 54, 123, 124, -1, 54,
- 124, -1, -1, 26, 126, 135, -1, -1, 37, 21,
- 128, 114, 132, 98, 133, 116, -1, 51, 21, -1,
- -1, 52, 21, 129, 114, 132, 98, 133, 116, -1,
- -1, -1, 79, 21, 130, 114, 131, 132, 98, 133,
- 116, 25, -1, -1, 21, -1, 132, 95, 21, -1,
- 132, 98, 95, 21, -1, -1, 21, 136, -1, -1,
- 118, -1, 135, 95, 118, -1, 118, -1, 135, 95,
- 118, -1
+ 106, 0, -1, 106, 107, 108, -1, 108, -1, 1,
+ 107, -1, 97, -1, -1, 139, -1, 146, -1, 111,
+ -1, 49, 128, 42, 28, -1, 49, 128, 42, 129,
+ -1, 49, 128, 74, 128, -1, 49, 128, 75, 128,
+ -1, 51, 28, 90, 128, -1, 51, 13, 90, 128,
+ -1, 51, 14, 128, 90, 128, -1, 51, 28, 53,
+ 128, -1, 51, 13, 53, 128, -1, 51, 14, 128,
+ 53, 128, -1, 128, -1, 130, -1, 110, -1, 112,
+ -1, 119, 98, 118, 99, 125, 124, 32, -1, 120,
+ 90, 128, 124, 53, 128, 124, 125, 124, 32, -1,
+ 120, 90, 128, 124, 34, 53, 128, 124, 125, 124,
+ 32, -1, 126, 110, 124, -1, 127, 128, 107, 125,
+ 124, 32, -1, 127, 128, 53, 128, -1, 121, 118,
+ 52, 107, 125, 124, 32, -1, 121, 118, 52, 107,
+ 125, 124, 57, 125, 124, 32, -1, 121, 118, 52,
+ 107, 125, 124, 123, 114, 124, 32, -1, 121, 118,
+ 52, 123, 110, 124, -1, 121, 118, 52, 123, 110,
+ 124, 57, 123, 110, 124, -1, 121, 118, 52, 123,
+ 110, 124, 115, 124, 113, 124, -1, -1, 57, 123,
+ 110, -1, 114, 117, -1, 117, -1, 115, 116, -1,
+ 116, -1, 122, 118, 52, 123, 111, 124, -1, 115,
+ -1, 122, 118, 52, 123, 125, 124, -1, 128, -1,
+ 128, 90, 128, -1, 98, 118, 99, -1, 50, 56,
+ -1, 50, 55, 28, -1, 41, -1, 36, -1, -1,
+ -1, -1, 125, 107, -1, 125, 111, -1, 54, 28,
+ 52, -1, 86, -1, 12, -1, 15, -1, 31, -1,
+ 29, -1, 23, -1, 24, 128, -1, 25, 148, -1,
+ 25, 98, 148, 99, -1, 28, 98, 147, 99, -1,
+ 28, -1, 13, -1, 14, 128, -1, 109, -1, 128,
+ 92, 128, -1, 128, 93, 128, -1, 128, 94, 128,
+ -1, 128, 95, 128, -1, 128, 73, 128, -1, 128,
+ 100, 128, -1, 128, 101, 128, -1, 128, 69, 128,
+ -1, 128, 64, 128, -1, 128, 65, 128, -1, 128,
+ 70, 128, -1, 128, 71, 128, -1, 72, 128, -1,
+ 128, 91, 128, -1, 128, 76, 128, -1, 128, 77,
+ 128, -1, 128, 78, 128, -1, 92, 128, -1, 93,
+ 128, -1, 98, 128, 99, -1, 102, 147, 103, -1,
+ 83, 128, 84, 128, -1, 83, 128, 85, 128, -1,
+ 79, 128, 47, 128, -1, 79, 128, 53, 128, 47,
+ 128, -1, 80, 128, 47, 128, -1, 80, 128, 53,
+ 128, 47, 128, -1, 81, 128, 47, 128, -1, 81,
+ 128, 53, 128, 47, 128, -1, 82, 128, 47, 128,
+ -1, 82, 128, 53, 128, 47, 128, -1, 27, 128,
+ -1, 49, 128, -1, 134, -1, 137, -1, 37, 50,
+ -1, 37, -1, 39, 131, -1, 87, 132, -1, 63,
+ 133, -1, 17, -1, 19, 128, -1, 18, 128, -1,
+ 18, -1, 20, 148, -1, 20, 98, 148, 99, -1,
+ 89, 98, 28, 99, -1, 89, 98, 28, 104, 147,
+ 99, -1, 60, 128, 55, 128, -1, 60, 128, -1,
+ 21, 28, 147, -1, 28, -1, 131, 104, 28, -1,
+ 28, -1, 132, 104, 28, -1, 28, -1, 133, 104,
+ 28, -1, 40, 43, -1, 40, 46, -1, 40, 48,
+ -1, 40, 135, -1, 40, 135, 136, -1, 40, 136,
+ -1, 38, 128, -1, 128, -1, 47, 45, 128, -1,
+ 45, 128, -1, 61, 62, -1, 61, 135, -1, 61,
+ 135, 136, -1, 61, 136, -1, -1, 33, 138, 147,
+ -1, -1, 44, 28, 140, 123, 144, 107, 145, 125,
+ -1, 58, 28, -1, -1, 59, 28, 141, 123, 144,
+ 107, 145, 125, -1, -1, -1, 88, 28, 142, 123,
+ 143, 144, 107, 145, 125, 32, -1, -1, 28, -1,
+ 144, 104, 28, -1, 144, 107, 104, 28, -1, -1,
+ 28, 148, -1, -1, 128, -1, 147, 104, 128, -1,
+ 128, -1, 148, 104, 128, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 117, 117, 118, 119, 122, 127, 128, 129, 130,
- 133, 139, 140, 141, 147, 155, 163, 169, 177, 187,
- 188, 191, 192, 197, 210, 228, 242, 250, 260, 272,
- 284, 294, 304, 316, 317, 320, 321, 324, 325, 328,
- 336, 337, 345, 346, 347, 350, 353, 360, 367, 375,
- 378, 381, 382, 383, 386, 392, 393, 396, 399, 402,
- 405, 408, 412, 419, 425, 426, 427, 428, 429, 430,
- 431, 432, 433, 434, 435, 436, 437, 438, 439, 440,
- 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
- 451, 452, 453, 454, 455, 456, 459, 460, 461, 462,
- 463, 465, 466, 467, 470, 473, 476, 477, 478, 479,
- 480, 481, 482, 485, 486, 489, 490, 501, 502, 503,
- 504, 507, 510, 515, 516, 519, 520, 523, 524, 527,
- 530, 533, 533, 563, 563, 569, 572, 572, 577, 578,
- 577, 588, 589, 590, 591, 594, 598, 606, 607, 608,
- 611, 612
+ 0, 118, 118, 119, 120, 123, 128, 129, 130, 131,
+ 134, 140, 143, 144, 145, 151, 159, 167, 173, 181,
+ 191, 192, 195, 196, 201, 214, 232, 246, 252, 255,
+ 260, 270, 282, 294, 304, 314, 326, 327, 330, 331,
+ 334, 335, 338, 346, 347, 355, 356, 357, 360, 363,
+ 370, 377, 385, 388, 391, 392, 393, 396, 402, 406,
+ 407, 410, 413, 416, 419, 422, 423, 424, 427, 431,
+ 438, 444, 445, 446, 447, 448, 449, 450, 451, 452,
+ 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
+ 463, 464, 465, 466, 467, 468, 469, 470, 471, 472,
+ 473, 474, 475, 478, 483, 484, 485, 486, 487, 488,
+ 489, 490, 491, 494, 497, 500, 504, 505, 506, 507,
+ 508, 509, 510, 513, 514, 517, 518, 521, 522, 533,
+ 534, 535, 536, 539, 542, 547, 548, 551, 552, 555,
+ 556, 559, 562, 565, 565, 595, 595, 600, 603, 603,
+ 608, 609, 608, 618, 619, 620, 621, 624, 628, 636,
+ 637, 638, 641, 642
};
#endif
@@ -692,26 +717,28 @@ static const yytype_uint16 yyrline[] =
static const char *const yytname[] =
{
"$end", "error", "$undefined", "UNARY", "CASTREF", "VOID", "VAR",
- "POINT", "RECT", "ARRAY", "OBJECT", "INT", "THEENTITY",
+ "POINT", "RECT", "ARRAY", "OBJECT", "REFERENCE", "INT", "THEENTITY",
"THEENTITYWITHID", "FLOAT", "BLTIN", "BLTINNOARGS", "BLTINNOARGSORONE",
- "BLTINONEARG", "BLTINARGLIST", "TWOWORDBUILTIN", "ID", "STRING",
- "HANDLER", "SYMBOL", "ENDCLAUSE", "tPLAYACCEL", "tDOWN", "tELSE",
- "tNLELSIF", "tEXIT", "tFRAME", "tGLOBAL", "tGO", "tIF", "tINTO", "tLOOP",
- "tMACRO", "tMOVIE", "tNEXT", "tOF", "tPREVIOUS", "tPUT", "tREPEAT",
- "tSET", "tTHEN", "tTO", "tWHEN", "tWITH", "tWHILE", "tNLELSE",
- "tFACTORY", "tMETHOD", "tOPEN", "tPLAY", "tDONE", "tINSTANCE", "tGE",
- "tLE", "tGT", "tLT", "tEQ", "tNEQ", "tAND", "tOR", "tNOT", "tMOD",
- "tAFTER", "tBEFORE", "tCONCAT", "tCONTAINS", "tSTARTS", "tCHAR", "tITEM",
- "tLINE", "tWORD", "tSPRITE", "tINTERSECTS", "tWITHIN", "tON", "tME",
- "'='", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", "'\\n'", "'('", "')'",
- "'>'", "'<'", "'['", "']'", "','", "$accept", "program", "nl",
- "programline", "asgn", "stmtoneliner", "stmt", "ifstmt",
- "elsestmtoneliner", "elseifstmt", "elseifstmtoneliner",
+ "BLTINONEARG", "BLTINARGLIST", "TWOWORDBUILTIN", "FBLTIN",
+ "FBLTINNOARGS", "FBLTINONEARG", "FBLTINARGLIST", "RBLTIN",
+ "RBLTINONEARG", "ID", "STRING", "HANDLER", "SYMBOL", "ENDCLAUSE",
+ "tPLAYACCEL", "tDOWN", "tELSE", "tNLELSIF", "tEXIT", "tFRAME", "tGLOBAL",
+ "tGO", "tIF", "tINTO", "tLOOP", "tMACRO", "tMOVIE", "tNEXT", "tOF",
+ "tPREVIOUS", "tPUT", "tREPEAT", "tSET", "tTHEN", "tTO", "tWHEN", "tWITH",
+ "tWHILE", "tNLELSE", "tFACTORY", "tMETHOD", "tOPEN", "tPLAY", "tDONE",
+ "tINSTANCE", "tGE", "tLE", "tGT", "tLT", "tEQ", "tNEQ", "tAND", "tOR",
+ "tNOT", "tMOD", "tAFTER", "tBEFORE", "tCONCAT", "tCONTAINS", "tSTARTS",
+ "tCHAR", "tITEM", "tLINE", "tWORD", "tSPRITE", "tINTERSECTS", "tWITHIN",
+ "tTELL", "tPROPERTY", "tON", "tME", "'='", "'&'", "'+'", "'-'", "'*'",
+ "'/'", "'%'", "'\\n'", "'('", "')'", "'>'", "'<'", "'['", "']'", "','",
+ "$accept", "program", "nl", "programline", "asgn", "stmtoneliner",
+ "stmt", "ifstmt", "elsestmtoneliner", "elseifstmt", "elseifstmtoneliner",
"elseifstmtoneliner1", "elseifstmt1", "cond", "repeatwhile",
- "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "expr",
- "func", "globallist", "instancelist", "gotofunc", "gotoframe",
- "gotomovie", "playfunc", "@1", "defn", "@2", "@3", "@4", "@5", "argdef",
- "argstore", "macro", "arglist", "nonemptyarglist", 0
+ "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "tell",
+ "expr", "reference", "proc", "globallist", "propertylist",
+ "instancelist", "gotofunc", "gotoframe", "gotomovie", "playfunc", "@1",
+ "defn", "@2", "@3", "@4", "@5", "argdef", "argstore", "macro", "arglist",
+ "nonemptyarglist", 0
};
#endif
@@ -728,51 +755,54 @@ static const yytype_uint16 yytoknum[] =
305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
- 335, 61, 38, 43, 45, 42, 47, 37, 10, 40,
- 41, 62, 60, 91, 93, 44
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 61, 38, 43, 45, 42, 47, 37, 10, 40, 41,
+ 62, 60, 91, 93, 44
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 96, 97, 97, 97, 98, 99, 99, 99, 99,
- 100, 100, 100, 100, 100, 100, 100, 100, 100, 101,
- 101, 102, 102, 102, 102, 102, 102, 103, 103, 103,
- 103, 103, 103, 104, 104, 105, 105, 106, 106, 107,
- 108, 108, 109, 109, 109, 110, 111, 112, 113, 114,
- 115, 116, 116, 116, 117, 118, 118, 118, 118, 118,
- 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
- 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
- 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
- 118, 118, 118, 118, 118, 118, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 120, 120, 121, 121, 122, 122, 122,
- 122, 122, 122, 123, 123, 124, 124, 125, 125, 125,
- 125, 126, 125, 128, 127, 127, 129, 127, 130, 131,
- 127, 132, 132, 132, 132, 133, 134, 135, 135, 135,
- 136, 136
+ 0, 105, 106, 106, 106, 107, 108, 108, 108, 108,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 110, 110, 111, 111, 111, 111, 111, 111, 111, 111,
+ 112, 112, 112, 112, 112, 112, 113, 113, 114, 114,
+ 115, 115, 116, 117, 117, 118, 118, 118, 119, 120,
+ 121, 122, 123, 124, 125, 125, 125, 126, 127, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 129, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 131, 131, 132, 132, 133, 133, 134,
+ 134, 134, 134, 134, 134, 135, 135, 136, 136, 137,
+ 137, 137, 137, 138, 137, 140, 139, 139, 141, 139,
+ 142, 143, 139, 144, 144, 144, 144, 145, 146, 147,
+ 147, 147, 148, 148
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 3, 1, 2, 1, 0, 1, 1, 1,
- 4, 4, 4, 4, 4, 5, 4, 4, 5, 1,
- 1, 1, 1, 7, 10, 11, 3, 7, 10, 10,
- 6, 10, 10, 0, 3, 2, 1, 2, 1, 6,
- 1, 6, 1, 3, 3, 2, 3, 1, 1, 0,
- 0, 0, 2, 2, 3, 1, 1, 1, 1, 1,
- 4, 1, 1, 2, 1, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 2, 3, 3,
- 3, 3, 2, 2, 3, 3, 4, 4, 4, 6,
- 4, 6, 4, 6, 4, 6, 2, 1, 1, 2,
- 1, 2, 2, 2, 2, 1, 4, 2, 4, 6,
- 4, 2, 3, 1, 3, 1, 3, 2, 2, 2,
- 2, 3, 2, 2, 1, 3, 2, 2, 2, 3,
- 2, 0, 3, 0, 8, 2, 0, 8, 0, 0,
- 10, 0, 1, 3, 4, 0, 2, 0, 1, 3,
- 1, 3
+ 4, 4, 4, 4, 4, 4, 5, 4, 4, 5,
+ 1, 1, 1, 1, 7, 10, 11, 3, 6, 4,
+ 7, 10, 10, 6, 10, 10, 0, 3, 2, 1,
+ 2, 1, 6, 1, 6, 1, 3, 3, 2, 3,
+ 1, 1, 0, 0, 0, 2, 2, 3, 1, 1,
+ 1, 1, 1, 1, 2, 2, 4, 4, 1, 1,
+ 2, 1, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 2, 3, 3, 3, 3, 2,
+ 2, 3, 3, 4, 4, 4, 6, 4, 6, 4,
+ 6, 4, 6, 2, 2, 1, 1, 2, 1, 2,
+ 2, 2, 1, 2, 2, 1, 2, 4, 4, 6,
+ 4, 2, 3, 1, 3, 1, 3, 1, 3, 2,
+ 2, 2, 2, 3, 2, 2, 1, 3, 2, 2,
+ 2, 3, 2, 0, 3, 0, 8, 2, 0, 8,
+ 0, 0, 10, 0, 1, 3, 4, 0, 2, 0,
+ 1, 3, 1, 3
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -780,482 +810,536 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 55, 62, 0, 56, 59, 105, 0, 147,
- 0, 61, 58, 57, 131, 100, 0, 0, 47, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 147, 0, 3, 64, 21, 9, 22, 0, 0, 0,
- 0, 19, 20, 97, 98, 7, 8, 5, 4, 61,
- 0, 63, 104, 103, 147, 148, 107, 147, 147, 150,
- 0, 146, 147, 99, 113, 101, 0, 117, 0, 118,
- 0, 119, 124, 120, 122, 133, 96, 0, 45, 0,
- 0, 0, 0, 135, 136, 111, 127, 128, 130, 115,
- 102, 77, 0, 0, 0, 0, 0, 138, 0, 82,
- 83, 0, 0, 1, 6, 0, 0, 0, 0, 42,
- 50, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 147, 0, 148,
- 0, 0, 112, 0, 0, 132, 0, 123, 126, 0,
- 121, 49, 0, 0, 0, 46, 0, 0, 0, 0,
- 0, 54, 49, 0, 129, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 84, 85,
- 2, 0, 50, 0, 0, 49, 0, 26, 73, 74,
- 72, 75, 76, 69, 79, 80, 81, 78, 65, 66,
- 67, 68, 70, 71, 106, 149, 60, 151, 114, 125,
- 141, 10, 11, 12, 17, 14, 0, 0, 16, 13,
- 141, 110, 116, 88, 0, 90, 0, 92, 0, 94,
- 0, 86, 87, 139, 108, 147, 51, 0, 44, 51,
- 0, 43, 142, 0, 18, 15, 0, 0, 0, 0,
- 0, 141, 0, 50, 0, 0, 50, 50, 0, 145,
- 145, 89, 91, 93, 95, 0, 109, 52, 53, 0,
- 0, 50, 49, 30, 143, 0, 51, 51, 145, 23,
- 50, 51, 27, 51, 0, 48, 49, 50, 38, 0,
- 144, 134, 137, 51, 51, 50, 50, 50, 40, 36,
- 0, 0, 37, 33, 0, 0, 50, 0, 0, 35,
- 0, 0, 50, 49, 50, 49, 140, 0, 24, 28,
- 29, 49, 31, 0, 32, 0, 25, 51, 34, 50,
- 50, 39, 41
+ 0, 0, 59, 69, 0, 60, 112, 115, 0, 0,
+ 0, 63, 0, 0, 68, 62, 61, 143, 108, 0,
+ 0, 50, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 58, 0,
+ 0, 0, 0, 0, 0, 159, 0, 3, 71, 22,
+ 9, 23, 0, 0, 0, 0, 0, 20, 21, 105,
+ 106, 7, 8, 5, 4, 68, 0, 70, 114, 113,
+ 0, 162, 116, 159, 64, 0, 65, 159, 158, 159,
+ 107, 123, 109, 0, 129, 0, 130, 0, 131, 136,
+ 132, 134, 145, 104, 0, 48, 0, 0, 0, 0,
+ 147, 148, 121, 139, 140, 142, 127, 111, 84, 0,
+ 0, 0, 0, 0, 125, 110, 150, 0, 89, 90,
+ 0, 160, 0, 1, 6, 0, 0, 0, 0, 45,
+ 53, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 159, 0,
+ 162, 0, 0, 122, 0, 160, 0, 144, 0, 135,
+ 138, 0, 133, 52, 0, 0, 0, 49, 0, 0,
+ 0, 0, 0, 57, 52, 0, 141, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 52,
+ 0, 91, 92, 0, 2, 0, 53, 0, 0, 52,
+ 0, 27, 0, 54, 80, 81, 79, 82, 83, 76,
+ 86, 87, 88, 85, 72, 73, 74, 75, 77, 78,
+ 117, 163, 66, 67, 124, 137, 153, 0, 10, 11,
+ 12, 13, 18, 15, 0, 0, 17, 14, 153, 120,
+ 128, 95, 0, 97, 0, 99, 0, 101, 0, 93,
+ 94, 126, 151, 118, 159, 161, 54, 0, 47, 54,
+ 0, 46, 29, 53, 154, 0, 103, 19, 16, 0,
+ 0, 0, 0, 0, 153, 0, 53, 0, 0, 53,
+ 53, 55, 56, 0, 0, 157, 157, 96, 98, 100,
+ 102, 0, 119, 0, 0, 53, 52, 33, 28, 155,
+ 0, 54, 54, 157, 24, 53, 54, 30, 54, 0,
+ 51, 52, 53, 41, 0, 156, 146, 149, 54, 54,
+ 53, 53, 53, 43, 39, 0, 0, 40, 36, 0,
+ 0, 53, 0, 0, 38, 0, 0, 53, 52, 53,
+ 52, 152, 0, 25, 31, 32, 52, 34, 0, 35,
+ 0, 26, 54, 37, 53, 53, 42, 44
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 41, 267, 42, 43, 44, 268, 46, 314, 297,
- 298, 288, 299, 118, 47, 48, 49, 289, 210, 187,
- 253, 50, 51, 52, 75, 100, 53, 83, 84, 54,
- 72, 55, 151, 162, 176, 251, 243, 276, 56, 143,
- 71
+ -1, 46, 281, 47, 48, 49, 282, 51, 339, 322,
+ 323, 313, 324, 128, 52, 53, 54, 314, 226, 201,
+ 263, 55, 56, 57, 229, 58, 82, 115, 107, 59,
+ 90, 91, 60, 79, 61, 163, 174, 189, 274, 265,
+ 301, 62, 156, 72
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -240
+#define YYPACT_NINF -271
static const yytype_int16 yypact[] =
{
- 286, -64, -240, -240, 961, -240, -240, 961, 961, 1027,
- 35, 369, -240, -240, -240, 53, 67, 860, -240, 77,
- 961, -26, 45, 80, 81, 82, 961, 926, 83, 961,
- 961, 961, 961, 961, 961, 84, 18, 961, 961, 961,
- 961, 2, -240, -240, -240, -240, -240, 19, 25, 1052,
- 961, 1541, -240, -240, -240, -240, -240, -240, -240, 22,
- 961, 1541, 1541, 1541, 961, 1541, 20, 961, 961, 1345,
- 24, -240, 961, -240, -240, 26, 961, -240, 961, -240,
- 74, -240, 1541, 36, -240, -240, 142, 92, -240, -39,
- 961, -32, 75, -240, -240, 1314, -240, 36, -240, -240,
- 46, -66, 338, 1091, 1123, 1155, 1417, -240, 119, -66,
- -66, 1479, -9, -240, 454, 1052, 961, 1052, 99, 1510,
- 1541, 961, 961, 961, 961, 961, 961, 961, 961, 961,
- 961, 961, 961, 961, 961, 961, 961, 961, 142, 1479,
- -12, 961, 20, -8, 961, 20, 125, 1541, 1541, 961,
- -240, -240, 126, 961, 961, -240, 961, 961, 763, 961,
- 961, -240, -240, 961, -240, 128, 961, 961, 961, 961,
- 961, 961, 961, 961, 961, 961, -240, -1, -240, -240,
- -240, 61, 1541, 62, 1448, -64, 961, -240, 823, 823,
- 823, -66, -66, -66, 1541, 823, 823, 1021, 129, 129,
- -66, -66, 1541, 1541, -240, 1541, -240, 1381, -240, 1541,
- 135, -240, 1541, 1541, 1541, 1541, 961, 961, 1541, 1541,
- 135, 1541, -240, 1541, 1187, 1541, 1219, 1541, 1251, 1541,
- 1283, 1541, 1541, -240, -240, 961, -240, 17, -240, -240,
- 786, 1541, -240, -24, 1541, 1541, -24, 961, 961, 961,
- 961, 135, 5, 620, 113, 961, 620, -240, 141, 68,
- 68, 1541, 1541, 1541, 1541, -24, -240, -240, -240, 140,
- 961, 1541, -5, -13, -240, 145, -240, -240, 68, -240,
- 1541, -240, -240, -240, 150, -240, -240, 150, -240, 1052,
- -240, 620, 620, -240, -240, 620, 620, 150, 150, -240,
- 1052, 786, -240, 131, 138, 537, 620, 159, 160, -240,
- 161, 146, -240, -240, -240, -240, -240, 165, -240, -240,
- -240, -240, -240, 786, -240, 703, -240, 703, -240, -240,
- 620, -240, -240
+ 341, -56, -271, -271, 990, -271, -271, 990, 990, 1062,
+ 23, -271, 990, 1102, 1174, -271, -271, -271, 3, 36,
+ 878, -271, 42, 990, 46, 81, 44, 51, 53, 990,
+ 950, 61, 990, 990, 990, 990, 990, 990, -271, 65,
+ 69, 7, 990, 990, 990, 990, 2, -271, -271, -271,
+ -271, -271, 13, 33, 1214, 796, 990, 1778, -271, -271,
+ -271, -271, -271, -271, -271, 20, 990, 1778, 1778, 1778,
+ 990, 1778, 25, 990, 1778, 990, 25, 990, 25, 990,
+ -271, -271, 47, 990, -271, 990, -271, 107, -271, 1778,
+ -18, -271, -271, 1249, 127, -271, -36, 990, -30, 104,
+ -271, -271, 1613, -271, -18, -271, -271, 54, -75, 1282,
+ 1315, 1348, 1381, 1646, -271, 55, -271, 129, -75, -75,
+ 1712, 1778, 28, -271, 432, 1214, 990, 1214, 108, 1745,
+ -271, 1546, 990, 990, 990, 990, 990, 990, 990, 990,
+ 990, 990, 990, 990, 990, 990, 990, 990, 990, 1249,
+ 1712, -12, 990, 57, -8, 1712, 15, 57, 135, 1778,
+ 1778, 990, -271, -271, 88, 990, 990, -271, 990, 990,
+ 1580, 990, 990, -271, -271, 990, -271, 136, 990, 990,
+ 990, 990, 990, 990, 990, 990, 990, 990, 137, -271,
+ 18, -271, -271, 990, -271, 72, 1778, 75, 1679, -56,
+ 990, -271, 990, -271, 238, 238, 238, -75, -75, -75,
+ 1778, 238, 238, 770, 12, 12, -75, -75, 1778, 1778,
+ -271, 1778, -271, -271, -271, 1778, 140, 990, -271, -271,
+ 1778, 1778, 1778, 1778, 990, 990, 1778, 1778, 140, 1778,
+ -271, 1778, 1414, 1778, 1447, 1778, 1480, 1778, 1513, 1778,
+ 1778, -271, -271, -271, 990, 1778, -271, -6, -271, -271,
+ 796, 1778, 1778, 614, -271, -35, 1778, 1778, 1778, -35,
+ 990, 990, 990, 990, 140, 26, 614, 122, 990, 614,
+ -271, -271, -271, 146, 161, 86, 86, 1778, 1778, 1778,
+ 1778, -35, -271, 159, 990, 1778, -25, -17, -271, -271,
+ 164, -271, -271, 86, -271, 1778, -271, -271, -271, 157,
+ -271, -271, 157, -271, 1214, -271, 614, 614, -271, -271,
+ 614, 614, 157, 157, -271, 1214, 796, -271, 138, 144,
+ 523, 614, 166, 167, -271, 168, 150, -271, -271, -271,
+ -271, -271, 172, -271, -271, -271, -271, -271, 796, -271,
+ 705, -271, 705, -271, -271, 614, -271, -271
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -240, -240, 12, 87, -240, -239, 0, -240, -240, -240,
- -79, -228, -101, -111, -240, -240, -240, -237, -133, -34,
- -184, -240, 1, -240, -240, -240, -240, 175, -16, -240,
- -240, -240, -240, -240, -240, -240, -205, -224, -240, 8,
- -240
+ -271, -271, 19, 82, -271, -51, 0, -271, -271, -271,
+ -90, -264, -114, -109, -271, -271, -271, -270, -99, -19,
+ -198, -271, -271, 1, -271, -271, -271, -271, -271, -271,
+ 180, -27, -271, -271, -271, -271, -271, -271, -271, -232,
+ -237, -271, -23, -2
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -150
+#define YYTABLE_NINF -7
static const yytype_int16 yytable[] =
{
- 45, 257, 113, 127, 181, 61, 183, 156, 62, 63,
- 65, 98, 69, 58, 159, 246, 285, 66, 82, 70,
- 282, 86, 87, 88, 57, 135, 136, 95, 82, 220,
- 101, 102, 103, 104, 105, 106, 277, 286, 109, 110,
- 111, 65, 157, 233, 254, 283, 265, 300, 112, 160,
- 119, 120, 240, 114, 293, 256, 67, 89, 90, 302,
- 300, 138, 312, 255, 57, 139, 91, 150, 65, 139,
- 302, 258, 140, 65, 78, 142, 80, 147, 204, 148,
- 145, 164, 206, 141, 328, 179, 141, 141, 74, 234,
- 57, 158, 291, 292, 235, 266, 73, 295, 85, 296,
- 141, 92, 93, 94, 99, 107, 116, 108, 115, 305,
- 306, 137, 149, 155, 45, 141, 119, 182, 184, 144,
- 161, 146, 188, 189, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 199, 200, 201, 202, 203, 65, 284,
- 177, 165, 205, 330, 185, 207, 208, 211, 237, 222,
- 209, 236, 238, 301, 212, 213, 242, 214, 215, 270,
- 218, 219, 274, 275, 221, 279, 290, 223, 224, 225,
- 226, 227, 228, 229, 230, 231, 232, 152, 304, 285,
- 323, 313, 325, 315, 318, 319, 320, 241, 327, 311,
- 326, 321, 124, 125, 287, 126, 309, 239, 127, 121,
- 122, 180, 97, 0, 123, 124, 125, 0, 126, 153,
- 154, 127, 128, 129, 133, 134, 0, 244, 245, 269,
- 135, 136, 272, 273, 130, 131, 132, 133, 134, 0,
- 0, 0, 0, 135, 136, 0, 65, 281, 0, 0,
- 0, 0, 0, 252, 0, 0, 294, 0, 261, 262,
- 263, 264, 0, 303, 0, 259, 271, 0, 260, 0,
- 0, 307, 308, 310, 0, 0, 0, 0, 0, 0,
- 0, 280, 317, 0, 0, 0, 0, 278, 322, 0,
- 324, 0, 0, 0, 0, 0, -6, 1, 0, 0,
- 119, 0, 0, 0, 0, 331, 332, 2, 3, 4,
- 5, 119, 6, 7, 8, 9, 10, 11, 12, 0,
- 13, 0, 14, 0, 0, 0, 15, 0, 16, 17,
- 18, 0, 0, 19, 0, 329, 0, 329, 20, 21,
- 22, 0, 0, 23, 0, 0, 0, 24, 25, 26,
- 27, 0, 28, 0, 0, 0, 0, 0, 0, 0,
- 0, 29, 0, 0, 0, 0, 0, 0, 30, 31,
- 32, 33, 34, 0, 0, 35, 36, 0, 0, 37,
- 38, 0, 0, 0, -6, 39, 0, 0, 166, 40,
- 2, 3, 4, 5, 167, 6, 0, 0, 0, 0,
- 59, 12, 0, 13, 0, 121, 122, 0, 0, 0,
- 123, 124, 125, 0, 126, 0, 0, 127, 128, 129,
- 0, 60, 0, 22, 0, 0, 0, 0, 0, 0,
- 130, 131, 132, 133, 134, 0, 0, 0, 0, 135,
- 136, 0, 0, 0, 29, 0, 0, 0, 0, 0,
- 0, 30, 31, 32, 33, 34, 0, 0, 0, 0,
- 0, 0, 37, 38, 0, 0, 0, 0, 68, 0,
- 0, 0, 40, 0, -147, 2, 3, 4, 5, 0,
- 6, 7, 8, 9, 10, 11, 12, 0, 13, 0,
- 14, 0, 0, 0, 15, 0, 16, 17, 18, 0,
- 0, 19, 0, 0, 0, 0, 20, 21, 22, 0,
- 0, 23, 0, 0, 0, 24, 25, 26, 27, 0,
- 28, 0, 0, 0, 0, 0, 0, 0, 0, 29,
- 0, 0, 0, 0, 0, 0, 30, 31, 32, 33,
- 34, 0, 0, 35, 36, 0, 0, 37, 38, 0,
- 0, 0, 0, 39, 0, 0, 0, 40, 2, 3,
- 4, 5, 0, 6, 7, 8, 9, 10, 59, 12,
- 0, 13, 316, 14, 0, 0, 0, 15, 0, 16,
- 17, 18, 0, 0, 0, 0, 0, 0, 0, 20,
- 21, 22, 0, 0, 23, 0, 0, 0, 0, 0,
- 26, 27, 0, 28, 0, 0, 0, 0, 0, 0,
- 0, 0, 29, 0, 0, 0, 0, 0, 0, 30,
- 31, 32, 33, 34, 0, 0, 0, 36, 0, 0,
- 37, 38, 0, 0, 0, 57, 39, 0, 0, 0,
- 40, 2, 3, 4, 5, 0, 6, 7, 8, 9,
- 10, 59, 12, 0, 13, 0, 14, 0, 0, 0,
- 15, 0, 16, 17, 18, 0, 0, 0, 0, 0,
- 0, 0, 20, 21, 22, 0, 0, 23, 0, 0,
- 0, 0, 0, 26, 27, 0, 28, 0, 0, 0,
- 0, 0, 0, 0, 0, 29, 0, 0, 0, 0,
- 0, 0, 30, 31, 32, 33, 34, 0, 0, 0,
- 36, 0, 0, 37, 38, 0, 0, 0, 57, 39,
- 0, 0, 0, 40, 2, 3, 4, 5, 0, 6,
- 7, 8, 9, 10, 59, 12, 0, 13, 0, 14,
- 0, 0, 0, 15, 0, 16, 17, 18, 0, 0,
- 0, 0, 0, 0, 0, 20, 21, 22, 0, 0,
- 23, 0, 0, 0, 0, 0, 26, 27, 0, 28,
- 0, 0, 0, 0, 0, 0, 0, 0, 29, 0,
- 0, 0, 0, 0, 0, 30, 31, 32, 33, 34,
- 0, 0, 0, 36, 0, 0, 37, 38, 0, 0,
- 0, 0, 39, 0, 0, 0, 40, 2, 3, 4,
- 5, 0, 6, 7, 8, 9, 10, 59, 12, 216,
- 13, 0, 14, 0, 0, 0, 15, 0, 16, 17,
- 121, 122, 0, 0, 0, 123, 124, 125, 20, 126,
- 22, 0, 127, 128, 129, 0, 0, 0, 0, 26,
- 27, 0, 28, 0, 217, 130, 131, 132, 133, 134,
- 0, 29, 0, 0, 135, 136, 0, 0, 30, 31,
- 32, 33, 34, 0, 0, 0, 36, 0, 0, 37,
- 38, 2, 3, 4, 5, 39, 6, 0, 0, 40,
- 0, 59, 12, 0, 13, 0, 124, 125, 0, 126,
- 0, 76, 127, 0, 0, 0, 77, 0, 78, 79,
- 80, 81, 60, 0, 22, 130, 131, 132, 133, 134,
- 0, 0, 0, 0, 135, 136, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 29, 0, 0, 0, 0,
- 0, 0, 30, 31, 32, 33, 34, 2, 3, 4,
- 5, 0, 6, 37, 38, 0, 0, 59, 12, 39,
- 13, 0, 0, 40, 0, 0, 0, 76, 0, 0,
- 0, 0, 0, 0, 78, 0, 80, 0, 60, 0,
- 22, 0, 2, 3, 4, 5, 0, 6, 0, 0,
- 0, 96, 59, 12, 0, 13, 0, 0, 0, 0,
- 0, 29, 0, 0, 0, 0, 0, 0, 30, 31,
- 32, 33, 34, 60, 0, 22, 0, 0, 0, 37,
- 38, 0, 0, 0, 0, 39, 0, 0, 0, 40,
- 0, 0, 0, 0, 0, 0, 29, 0, 0, 0,
- 0, 0, 0, 30, 31, 32, 33, 34, 2, 3,
- 4, 5, 0, 6, 37, 38, 0, 0, 59, 12,
- 39, 13, 0, 0, 40, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 3, 4, 5, 0, 6, 60,
- 0, 22, 0, 59, 12, 0, 13, 0, 0, 0,
- 0, 0, 0, 0, 124, 125, 0, 126, 0, 0,
- 127, 0, 29, 0, 60, 0, 22, 0, 0, 30,
- 31, 32, 33, 34, 131, 132, 133, 134, 0, 0,
- 37, 38, 135, 136, 0, 0, 64, 29, 0, 0,
- 40, 0, 0, 0, 30, 31, 32, 33, 34, 0,
- 0, 168, 0, 0, 0, 37, 38, 169, 0, 0,
- 0, 117, 0, 0, 0, 40, 0, 0, 121, 122,
- 0, 0, 0, 123, 124, 125, 0, 126, 0, 0,
- 127, 128, 129, 170, 0, 0, 0, 0, 0, 171,
- 0, 0, 0, 130, 131, 132, 133, 134, 0, 0,
- 121, 122, 135, 136, 0, 123, 124, 125, 0, 126,
- 0, 0, 127, 128, 129, 172, 0, 0, 0, 0,
- 0, 173, 0, 0, 0, 130, 131, 132, 133, 134,
- 0, 0, 121, 122, 135, 136, 0, 123, 124, 125,
- 0, 126, 0, 0, 127, 128, 129, 247, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 130, 131, 132,
- 133, 134, 0, 0, 121, 122, 135, 136, 0, 123,
- 124, 125, 0, 126, 0, 0, 127, 128, 129, 248,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 130,
- 131, 132, 133, 134, 0, 0, 121, 122, 135, 136,
- 0, 123, 124, 125, 0, 126, 0, 0, 127, 128,
- 129, 249, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 130, 131, 132, 133, 134, 0, 0, 121, 122,
- 135, 136, 0, 123, 124, 125, 0, 126, 0, 0,
- 127, 128, 129, 250, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 130, 131, 132, 133, 134, 0, 0,
- 121, 122, 135, 136, 0, 123, 124, 125, 0, 126,
- 0, 0, 127, 128, 129, 0, 0, 0, 0, 0,
- 0, 0, 163, 0, 0, 130, 131, 132, 133, 134,
- 0, 121, 122, 0, 135, 136, 123, 124, 125, 0,
- 126, 0, 0, 127, 128, 129, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 130, 131, 132, 133,
- 134, 0, 121, 122, 0, 135, 136, 123, 124, 125,
- 0, 126, 0, 0, 127, 128, 129, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 130, 131, 132,
- 133, 134, 0, 0, 0, 0, 135, 136, 121, 122,
- -148, 0, 0, 123, 124, 125, 0, 126, 0, 0,
- 127, 128, 129, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 130, 131, 132, 133, 134, 0, 0,
- 0, 0, 135, 136, 121, 122, -149, 0, 0, 123,
- 124, 125, 0, 126, 0, 0, 127, 128, 129, 0,
- 0, 0, 0, 0, 174, 175, 0, 0, 0, 130,
- 131, 132, 133, 134, 0, 121, 122, 0, 135, 136,
- 123, 124, 125, 0, 126, 0, 0, 127, 128, 129,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 186,
- 130, 131, 132, 133, 134, 0, 121, 122, 178, 135,
- 136, 123, 124, 125, 0, 126, 0, 0, 127, 128,
- 129, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 130, 131, 132, 133, 134, 0, 121, 122, 178,
- 135, 136, 123, 124, 125, 0, 126, 0, 0, 127,
- 128, 129, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 186, 130, 131, 132, 133, 134, 0, 121, 122,
- 0, 135, 136, 123, 124, 125, 0, 126, 0, 0,
- 127, 128, 129, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 130, 131, 132, 133, 134, 0, 0,
- 0, 0, 135, 136
+ 50, 138, 123, 105, 130, 67, 269, 307, 68, 69,
+ 71, 76, 78, 74, 71, 71, 195, 168, 197, 310,
+ 64, 89, 122, 171, 93, 146, 147, 85, 277, 87,
+ 102, 89, 308, 108, 109, 110, 111, 112, 113, 325,
+ 311, 63, 291, 118, 119, 120, 121, 278, 327, 302,
+ 153, 73, 325, 80, 169, 129, 157, 131, 276, 327,
+ 172, 279, 63, 162, 81, 124, 318, 149, 151, 284,
+ 92, 150, 99, 154, 121, 238, 150, 176, 155, 100,
+ 121, 101, 135, 136, 159, 137, 160, 220, 138, 106,
+ 252, 222, 152, 114, 96, 97, 152, 116, 170, 63,
+ 260, 94, 95, 316, 317, 117, 144, 145, 320, 98,
+ 321, 125, 146, 147, 223, 227, 228, 253, 148, 193,
+ 330, 331, 254, 126, 50, 292, 129, 196, 198, 152,
+ 193, 192, 193, 204, 205, 206, 207, 208, 209, 210,
+ 211, 212, 213, 214, 215, 216, 217, 218, 219, 121,
+ 203, 158, 161, 221, 355, 167, 173, 190, 177, 188,
+ 199, 193, 225, 224, 240, 251, 230, 231, 264, 232,
+ 233, 256, 236, 237, 258, 294, 239, 257, 298, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 299,
+ 300, 304, 315, 310, 255, 338, 340, 309, 343, 344,
+ 345, 261, 346, 262, 351, 329, 194, 312, 334, 280,
+ 104, 0, 326, 0, 0, 0, 336, 0, 259, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 266, 0,
+ 0, 275, 0, 0, 0, 267, 268, 0, 0, 348,
+ 0, 350, 0, 0, 283, 0, 0, 352, 0, 0,
+ 0, 0, 0, 0, 0, 121, 0, 293, 0, 0,
+ 296, 297, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 287, 288, 289, 290, 337, 306, 0, 0, 295,
+ 0, 0, 0, 0, 285, 0, 319, 0, 286, 0,
+ 0, 0, 0, 328, 0, 305, 0, 353, 0, 0,
+ 0, 332, 333, 335, 0, 0, 0, 0, 135, 136,
+ 303, 137, 342, 0, 138, 129, 0, 0, 347, 0,
+ 349, 0, 0, 0, 0, 0, 129, 0, 0, 141,
+ 142, 143, 144, 145, 0, 356, 357, 0, 146, 147,
+ 0, -6, 1, 0, 0, 0, 0, 0, 0, 0,
+ 354, 0, 354, 2, 3, 4, 5, 0, 6, 7,
+ 8, 9, 10, 0, 11, 12, 13, 0, 0, 14,
+ 15, 0, 16, 0, 17, 0, 0, 0, 18, 0,
+ 19, 20, 21, 0, 0, 22, 0, 0, 0, 0,
+ 23, 24, 25, 0, 0, 26, 0, 0, 0, 27,
+ 28, 29, 30, 0, 31, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 33, 34, 35, 36, 37, 0, 0, 38, 39, 40,
+ 41, 0, 0, 42, 43, 0, 0, 0, -6, 44,
+ 0, 0, 0, 45, 2, 3, 4, 5, 0, 6,
+ 7, 8, 9, 10, 0, 11, 12, 13, 0, 0,
+ 14, 15, 0, 16, 0, 17, 0, 0, 0, 18,
+ 0, 19, 20, 21, 0, 0, 22, 0, 0, 0,
+ 0, 23, 24, 25, 0, 0, 26, 0, 0, 0,
+ 27, 28, 29, 30, 0, 31, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,
+ 0, 33, 34, 35, 36, 37, 0, 0, 38, 39,
+ 40, 41, 0, 0, 42, 43, 0, 0, 0, 0,
+ 44, 0, 0, 0, 45, 2, 3, 4, 5, 0,
+ 6, 7, 8, 9, 10, 0, 11, 12, 13, 0,
+ 0, 65, 15, 0, 16, 341, 17, 0, 0, 0,
+ 18, 0, 19, 20, 21, 0, 0, 0, 0, 0,
+ 0, 0, 23, 24, 25, 0, 0, 26, 0, 0,
+ 0, 0, 0, 29, 30, 0, 31, 0, 0, 0,
+ 0, 0, 0, 0, 0, 32, 0, 0, 0, 0,
+ 0, 0, 33, 34, 35, 36, 37, 0, 0, 38,
+ 39, 0, 41, 0, 0, 42, 43, 0, 0, 0,
+ 63, 44, 0, 0, 0, 45, 2, 3, 4, 5,
+ 0, 6, 7, 8, 9, 10, 0, 11, 12, 13,
+ 0, 0, 65, 15, 0, 16, 0, 17, 0, 0,
+ 0, 18, 0, 19, 20, 21, 0, 0, 0, 0,
+ 0, 0, 0, 23, 24, 25, 0, 0, 26, 0,
+ 0, 0, 0, 0, 29, 30, 0, 31, 0, 0,
+ 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 33, 34, 35, 36, 37, 0, 0,
+ 38, 39, 0, 41, 0, 0, 42, 43, 0, 0,
+ 0, 63, 44, 0, 0, 0, 45, 2, 3, 4,
+ 5, 0, 6, 7, 8, 9, 10, 0, 11, 12,
+ 13, 0, 0, 65, 15, 0, 16, 0, 17, 0,
+ 0, 0, 18, 0, 19, 20, 21, 0, 0, 0,
+ 0, 0, 0, 0, 23, 24, 25, 0, 0, 26,
+ 0, 0, 0, 0, 0, 29, 30, 0, 31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 32, 0, 0,
+ 0, 0, 0, 0, 33, 34, 35, 36, 37, 0,
+ 0, 38, 39, 0, 41, 0, 0, 42, 43, 0,
+ 0, 0, 0, 44, 0, 0, 0, 45, 2, 3,
+ 4, 5, 0, 6, 7, 8, 9, 10, 0, 11,
+ 12, 13, 0, 0, 65, 15, 0, 16, 0, 17,
+ 0, 0, 0, 18, 0, 19, 20, 0, 0, 0,
+ 135, 136, 0, 137, 0, 23, 138, 25, 0, 0,
+ 0, 0, 0, 0, 0, 0, 29, 30, 0, 31,
+ 0, 0, 142, 143, 144, 145, 0, 0, 32, 0,
+ 146, 147, 0, 0, 0, 33, 34, 35, 36, 37,
+ 0, 0, 0, 39, 0, 41, 0, 0, 42, 43,
+ 2, 3, 4, 5, 44, 0, 0, 0, 45, 0,
+ 0, 11, 12, 13, 0, 0, 65, 15, 0, 16,
+ 0, 0, 0, 0, 0, 0, 83, 0, 0, 0,
+ 0, 84, 0, 85, 86, 87, 88, 66, 0, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 33, 34, 35,
+ 36, 37, 2, 3, 4, 5, 0, 0, 0, 0,
+ 42, 43, 0, 11, 12, 13, 44, 0, 65, 15,
+ 45, 16, 0, 0, 0, 0, 0, 0, 83, 0,
+ 0, 0, 0, 0, 0, 85, 0, 87, 0, 66,
+ 0, 25, 2, 3, 4, 5, 0, 0, 0, 0,
+ 0, 0, 103, 11, 12, 13, 0, 0, 65, 15,
+ 0, 16, 32, 0, 0, 0, 0, 0, 0, 33,
+ 34, 35, 36, 37, 0, 0, 0, 0, 0, 66,
+ 0, 25, 42, 43, 0, 0, 0, 0, 44, 0,
+ 0, 0, 45, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 32, 0, 0, 0, 0, 0, 0, 33,
+ 34, 35, 36, 37, 2, 3, 4, 5, 0, 0,
+ 0, 0, 42, 43, 0, 11, 12, 13, 44, 0,
+ 65, 15, 45, 16, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 66, 0, 25, 2, 3, 4, 5, 0, 0,
+ 0, 0, 0, 0, 0, 11, 12, 13, 0, 0,
+ 65, 15, 0, 16, 32, 0, 0, 0, 0, 0,
+ 0, 33, 34, 35, 36, 37, 0, 0, 0, 0,
+ 0, 66, 0, 25, 42, 43, 0, 0, 0, 0,
+ 70, 0, 0, 0, 45, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,
+ 0, 33, 34, 35, 36, 37, 2, 3, 4, 5,
+ 0, 0, 0, 0, 42, 43, 0, 11, 12, 13,
+ 75, 0, 65, 15, 45, 16, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66, 0, 25, 2, 3, 4, 5,
+ 0, 0, 0, 0, 0, 0, 0, 11, 12, 13,
+ 0, 0, 65, 15, 0, 16, 32, 0, 0, 0,
+ 0, 0, 0, 33, 34, 35, 36, 37, 0, 0,
+ 0, 0, 0, 66, 0, 25, 42, 43, 0, 0,
+ 0, 0, 77, 0, 0, 0, 45, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 0, 164, 0, 33, 34, 35, 36, 37, 0, 0,
+ 0, 0, 0, 0, 0, 0, 42, 43, 0, 0,
+ 0, 0, 127, 132, 133, 0, 45, 0, 134, 135,
+ 136, 0, 137, 165, 166, 138, 139, 140, 0, 178,
+ 0, 0, 0, 0, 0, 179, 0, 0, 0, 0,
+ 141, 142, 143, 144, 145, 0, 132, 133, 0, 146,
+ 147, 134, 135, 136, 0, 137, 0, 0, 138, 139,
+ 140, 0, 180, 0, 0, 0, 0, 0, 181, 0,
+ 0, 0, 0, 141, 142, 143, 144, 145, 0, 132,
+ 133, 0, 146, 147, 134, 135, 136, 0, 137, 0,
+ 0, 138, 139, 140, 0, 182, 0, 0, 0, 0,
+ 0, 183, 0, 0, 0, 0, 141, 142, 143, 144,
+ 145, 0, 132, 133, 0, 146, 147, 134, 135, 136,
+ 0, 137, 0, 0, 138, 139, 140, 0, 184, 0,
+ 0, 0, 0, 0, 185, 0, 0, 0, 0, 141,
+ 142, 143, 144, 145, 0, 132, 133, 0, 146, 147,
+ 134, 135, 136, 0, 137, 0, 0, 138, 139, 140,
+ 0, 270, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 141, 142, 143, 144, 145, 0, 132, 133,
+ 0, 146, 147, 134, 135, 136, 0, 137, 0, 0,
+ 138, 139, 140, 0, 271, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 141, 142, 143, 144, 145,
+ 0, 132, 133, 0, 146, 147, 134, 135, 136, 0,
+ 137, 0, 0, 138, 139, 140, 0, 272, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 141, 142,
+ 143, 144, 145, 0, 132, 133, 0, 146, 147, 134,
+ 135, 136, 0, 137, 0, 0, 138, 139, 140, 0,
+ 273, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 141, 142, 143, 144, 145, 0, 132, 133, 0,
+ 146, 147, 134, 135, 136, 0, 137, 0, 0, 138,
+ 139, 140, 0, 0, 0, 0, 0, 0, 0, 202,
+ 0, 0, 0, 0, 141, 142, 143, 144, 145, 0,
+ 132, 133, 0, 146, 147, 134, 135, 136, 0, 137,
+ 0, 0, 138, 139, 140, 0, 0, 0, 0, 0,
+ 0, 0, 0, 234, 0, 0, 0, 141, 142, 143,
+ 144, 145, 0, 63, 132, 133, 146, 147, 0, 134,
+ 135, 136, 0, 137, 0, 0, 138, 139, 140, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 175, 0,
+ 235, 141, 142, 143, 144, 145, 0, 132, 133, 0,
+ 146, 147, 134, 135, 136, 0, 137, 0, 0, 138,
+ 139, 140, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 141, 142, 143, 144, 145, 0,
+ 132, 133, 0, 146, 147, 134, 135, 136, 0, 137,
+ 0, 0, 138, 139, 140, 0, 0, 0, 0, 0,
+ 186, 187, 0, 0, 0, 0, 0, 141, 142, 143,
+ 144, 145, 0, 132, 133, 0, 146, 147, 134, 135,
+ 136, 0, 137, 0, 0, 138, 139, 140, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 200,
+ 141, 142, 143, 144, 145, 0, 132, 133, 191, 146,
+ 147, 134, 135, 136, 0, 137, 0, 0, 138, 139,
+ 140, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 141, 142, 143, 144, 145, 0, 132,
+ 133, 191, 146, 147, 134, 135, 136, 0, 137, 0,
+ 0, 138, 139, 140, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 200, 141, 142, 143, 144,
+ 145, 0, 132, 133, 0, 146, 147, 134, 135, 136,
+ 0, 137, 0, 0, 138, 139, 140, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 141,
+ 142, 143, 144, 145, 0, 0, 0, 0, 146, 147
};
static const yytype_int16 yycheck[] =
{
- 0, 240, 0, 69, 115, 4, 117, 46, 7, 8,
- 9, 27, 11, 1, 46, 220, 29, 9, 17, 11,
- 25, 20, 48, 49, 88, 91, 92, 26, 27, 162,
- 29, 30, 31, 32, 33, 34, 260, 50, 37, 38,
- 39, 40, 81, 176, 27, 50, 251, 284, 40, 81,
- 49, 50, 185, 41, 278, 239, 21, 12, 13, 287,
- 297, 60, 301, 46, 88, 64, 21, 83, 67, 68,
- 298, 95, 64, 72, 38, 67, 40, 76, 90, 78,
- 72, 97, 90, 95, 323, 94, 95, 95, 21, 90,
- 88, 90, 276, 277, 95, 90, 43, 281, 21, 283,
- 95, 21, 21, 21, 21, 21, 81, 89, 89, 293,
- 294, 89, 38, 21, 114, 95, 115, 116, 117, 95,
- 45, 95, 121, 122, 123, 124, 125, 126, 127, 128,
- 129, 130, 131, 132, 133, 134, 135, 136, 137, 272,
- 21, 95, 141, 327, 45, 144, 21, 21, 182, 21,
- 149, 90, 90, 286, 153, 154, 21, 156, 157, 46,
- 159, 160, 21, 95, 163, 25, 21, 166, 167, 168,
- 169, 170, 171, 172, 173, 174, 175, 35, 289, 29,
- 313, 50, 315, 45, 25, 25, 25, 186, 321, 300,
- 25, 45, 63, 64, 273, 66, 297, 185, 69, 57,
- 58, 114, 27, -1, 62, 63, 64, -1, 66, 67,
- 68, 69, 70, 71, 85, 86, -1, 216, 217, 253,
- 91, 92, 256, 257, 82, 83, 84, 85, 86, -1,
- -1, -1, -1, 91, 92, -1, 235, 271, -1, -1,
- -1, -1, -1, 235, -1, -1, 280, -1, 247, 248,
- 249, 250, -1, 287, -1, 243, 255, -1, 246, -1,
- -1, 295, 296, 297, -1, -1, -1, -1, -1, -1,
- -1, 270, 306, -1, -1, -1, -1, 265, 312, -1,
- 314, -1, -1, -1, -1, -1, 0, 1, -1, -1,
- 289, -1, -1, -1, -1, 329, 330, 11, 12, 13,
- 14, 300, 16, 17, 18, 19, 20, 21, 22, -1,
- 24, -1, 26, -1, -1, -1, 30, -1, 32, 33,
- 34, -1, -1, 37, -1, 325, -1, 327, 42, 43,
- 44, -1, -1, 47, -1, -1, -1, 51, 52, 53,
- 54, -1, 56, -1, -1, -1, -1, -1, -1, -1,
- -1, 65, -1, -1, -1, -1, -1, -1, 72, 73,
- 74, 75, 76, -1, -1, 79, 80, -1, -1, 83,
- 84, -1, -1, -1, 88, 89, -1, -1, 40, 93,
- 11, 12, 13, 14, 46, 16, -1, -1, -1, -1,
- 21, 22, -1, 24, -1, 57, 58, -1, -1, -1,
- 62, 63, 64, -1, 66, -1, -1, 69, 70, 71,
- -1, 42, -1, 44, -1, -1, -1, -1, -1, -1,
- 82, 83, 84, 85, 86, -1, -1, -1, -1, 91,
- 92, -1, -1, -1, 65, -1, -1, -1, -1, -1,
- -1, 72, 73, 74, 75, 76, -1, -1, -1, -1,
- -1, -1, 83, 84, -1, -1, -1, -1, 89, -1,
- -1, -1, 93, -1, 95, 11, 12, 13, 14, -1,
- 16, 17, 18, 19, 20, 21, 22, -1, 24, -1,
- 26, -1, -1, -1, 30, -1, 32, 33, 34, -1,
- -1, 37, -1, -1, -1, -1, 42, 43, 44, -1,
- -1, 47, -1, -1, -1, 51, 52, 53, 54, -1,
- 56, -1, -1, -1, -1, -1, -1, -1, -1, 65,
- -1, -1, -1, -1, -1, -1, 72, 73, 74, 75,
- 76, -1, -1, 79, 80, -1, -1, 83, 84, -1,
- -1, -1, -1, 89, -1, -1, -1, 93, 11, 12,
- 13, 14, -1, 16, 17, 18, 19, 20, 21, 22,
- -1, 24, 25, 26, -1, -1, -1, 30, -1, 32,
- 33, 34, -1, -1, -1, -1, -1, -1, -1, 42,
- 43, 44, -1, -1, 47, -1, -1, -1, -1, -1,
- 53, 54, -1, 56, -1, -1, -1, -1, -1, -1,
- -1, -1, 65, -1, -1, -1, -1, -1, -1, 72,
- 73, 74, 75, 76, -1, -1, -1, 80, -1, -1,
- 83, 84, -1, -1, -1, 88, 89, -1, -1, -1,
- 93, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, -1, 24, -1, 26, -1, -1, -1,
- 30, -1, 32, 33, 34, -1, -1, -1, -1, -1,
- -1, -1, 42, 43, 44, -1, -1, 47, -1, -1,
- -1, -1, -1, 53, 54, -1, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, 65, -1, -1, -1, -1,
- -1, -1, 72, 73, 74, 75, 76, -1, -1, -1,
- 80, -1, -1, 83, 84, -1, -1, -1, 88, 89,
- -1, -1, -1, 93, 11, 12, 13, 14, -1, 16,
- 17, 18, 19, 20, 21, 22, -1, 24, -1, 26,
- -1, -1, -1, 30, -1, 32, 33, 34, -1, -1,
- -1, -1, -1, -1, -1, 42, 43, 44, -1, -1,
- 47, -1, -1, -1, -1, -1, 53, 54, -1, 56,
- -1, -1, -1, -1, -1, -1, -1, -1, 65, -1,
- -1, -1, -1, -1, -1, 72, 73, 74, 75, 76,
- -1, -1, -1, 80, -1, -1, 83, 84, -1, -1,
- -1, -1, 89, -1, -1, -1, 93, 11, 12, 13,
- 14, -1, 16, 17, 18, 19, 20, 21, 22, 46,
- 24, -1, 26, -1, -1, -1, 30, -1, 32, 33,
- 57, 58, -1, -1, -1, 62, 63, 64, 42, 66,
- 44, -1, 69, 70, 71, -1, -1, -1, -1, 53,
- 54, -1, 56, -1, 81, 82, 83, 84, 85, 86,
- -1, 65, -1, -1, 91, 92, -1, -1, 72, 73,
- 74, 75, 76, -1, -1, -1, 80, -1, -1, 83,
- 84, 11, 12, 13, 14, 89, 16, -1, -1, 93,
- -1, 21, 22, -1, 24, -1, 63, 64, -1, 66,
- -1, 31, 69, -1, -1, -1, 36, -1, 38, 39,
- 40, 41, 42, -1, 44, 82, 83, 84, 85, 86,
- -1, -1, -1, -1, 91, 92, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 65, -1, -1, -1, -1,
- -1, -1, 72, 73, 74, 75, 76, 11, 12, 13,
- 14, -1, 16, 83, 84, -1, -1, 21, 22, 89,
- 24, -1, -1, 93, -1, -1, -1, 31, -1, -1,
- -1, -1, -1, -1, 38, -1, 40, -1, 42, -1,
- 44, -1, 11, 12, 13, 14, -1, 16, -1, -1,
- -1, 55, 21, 22, -1, 24, -1, -1, -1, -1,
- -1, 65, -1, -1, -1, -1, -1, -1, 72, 73,
- 74, 75, 76, 42, -1, 44, -1, -1, -1, 83,
- 84, -1, -1, -1, -1, 89, -1, -1, -1, 93,
- -1, -1, -1, -1, -1, -1, 65, -1, -1, -1,
- -1, -1, -1, 72, 73, 74, 75, 76, 11, 12,
- 13, 14, -1, 16, 83, 84, -1, -1, 21, 22,
- 89, 24, -1, -1, 93, -1, -1, -1, -1, -1,
- -1, -1, -1, 11, 12, 13, 14, -1, 16, 42,
- -1, 44, -1, 21, 22, -1, 24, -1, -1, -1,
- -1, -1, -1, -1, 63, 64, -1, 66, -1, -1,
- 69, -1, 65, -1, 42, -1, 44, -1, -1, 72,
- 73, 74, 75, 76, 83, 84, 85, 86, -1, -1,
- 83, 84, 91, 92, -1, -1, 89, 65, -1, -1,
- 93, -1, -1, -1, 72, 73, 74, 75, 76, -1,
- -1, 40, -1, -1, -1, 83, 84, 46, -1, -1,
- -1, 89, -1, -1, -1, 93, -1, -1, 57, 58,
- -1, -1, -1, 62, 63, 64, -1, 66, -1, -1,
- 69, 70, 71, 40, -1, -1, -1, -1, -1, 46,
- -1, -1, -1, 82, 83, 84, 85, 86, -1, -1,
- 57, 58, 91, 92, -1, 62, 63, 64, -1, 66,
- -1, -1, 69, 70, 71, 40, -1, -1, -1, -1,
- -1, 46, -1, -1, -1, 82, 83, 84, 85, 86,
- -1, -1, 57, 58, 91, 92, -1, 62, 63, 64,
- -1, 66, -1, -1, 69, 70, 71, 40, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 82, 83, 84,
- 85, 86, -1, -1, 57, 58, 91, 92, -1, 62,
- 63, 64, -1, 66, -1, -1, 69, 70, 71, 40,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 82,
- 83, 84, 85, 86, -1, -1, 57, 58, 91, 92,
- -1, 62, 63, 64, -1, 66, -1, -1, 69, 70,
- 71, 40, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 82, 83, 84, 85, 86, -1, -1, 57, 58,
- 91, 92, -1, 62, 63, 64, -1, 66, -1, -1,
- 69, 70, 71, 40, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 82, 83, 84, 85, 86, -1, -1,
- 57, 58, 91, 92, -1, 62, 63, 64, -1, 66,
- -1, -1, 69, 70, 71, -1, -1, -1, -1, -1,
- -1, -1, 48, -1, -1, 82, 83, 84, 85, 86,
- -1, 57, 58, -1, 91, 92, 62, 63, 64, -1,
- 66, -1, -1, 69, 70, 71, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 82, 83, 84, 85,
- 86, -1, 57, 58, -1, 91, 92, 62, 63, 64,
- -1, 66, -1, -1, 69, 70, 71, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 82, 83, 84,
- 85, 86, -1, -1, -1, -1, 91, 92, 57, 58,
- 95, -1, -1, 62, 63, 64, -1, 66, -1, -1,
- 69, 70, 71, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 82, 83, 84, 85, 86, -1, -1,
- -1, -1, 91, 92, 57, 58, 95, -1, -1, 62,
- 63, 64, -1, 66, -1, -1, 69, 70, 71, -1,
- -1, -1, -1, -1, 77, 78, -1, -1, -1, 82,
- 83, 84, 85, 86, -1, 57, 58, -1, 91, 92,
- 62, 63, 64, -1, 66, -1, -1, 69, 70, 71,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 81,
- 82, 83, 84, 85, 86, -1, 57, 58, 90, 91,
- 92, 62, 63, 64, -1, 66, -1, -1, 69, 70,
- 71, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 82, 83, 84, 85, 86, -1, 57, 58, 90,
- 91, 92, 62, 63, 64, -1, 66, -1, -1, 69,
- 70, 71, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 81, 82, 83, 84, 85, 86, -1, 57, 58,
- -1, 91, 92, 62, 63, 64, -1, 66, -1, -1,
- 69, 70, 71, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 82, 83, 84, 85, 86, -1, -1,
- -1, -1, 91, 92
+ 0, 76, 0, 30, 55, 4, 238, 32, 7, 8,
+ 9, 13, 14, 12, 13, 14, 125, 53, 127, 36,
+ 1, 20, 45, 53, 23, 100, 101, 45, 34, 47,
+ 29, 30, 57, 32, 33, 34, 35, 36, 37, 309,
+ 57, 97, 274, 42, 43, 44, 45, 53, 312, 286,
+ 73, 28, 322, 50, 90, 54, 79, 56, 256, 323,
+ 90, 259, 97, 90, 28, 46, 303, 66, 70, 104,
+ 28, 70, 28, 75, 73, 174, 75, 104, 77, 28,
+ 79, 28, 70, 71, 83, 73, 85, 99, 76, 28,
+ 189, 99, 104, 28, 13, 14, 104, 28, 97, 97,
+ 199, 55, 56, 301, 302, 98, 94, 95, 306, 28,
+ 308, 98, 100, 101, 99, 27, 28, 99, 98, 104,
+ 318, 319, 104, 90, 124, 99, 125, 126, 127, 104,
+ 104, 103, 104, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 131, 104, 45, 152, 352, 28, 52, 28, 104, 104,
+ 52, 104, 161, 28, 28, 28, 165, 166, 28, 168,
+ 169, 99, 171, 172, 99, 53, 175, 196, 32, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 28,
+ 104, 32, 28, 36, 193, 57, 52, 296, 32, 32,
+ 32, 200, 52, 202, 32, 314, 124, 297, 322, 260,
+ 30, -1, 311, -1, -1, -1, 325, -1, 199, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 227, -1,
+ -1, 254, -1, -1, -1, 234, 235, -1, -1, 338,
+ -1, 340, -1, -1, 263, -1, -1, 346, -1, -1,
+ -1, -1, -1, -1, -1, 254, -1, 276, -1, -1,
+ 279, 280, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 270, 271, 272, 273, 326, 295, -1, -1, 278,
+ -1, -1, -1, -1, 265, -1, 305, -1, 269, -1,
+ -1, -1, -1, 312, -1, 294, -1, 348, -1, -1,
+ -1, 320, 321, 322, -1, -1, -1, -1, 70, 71,
+ 291, 73, 331, -1, 76, 314, -1, -1, 337, -1,
+ 339, -1, -1, -1, -1, -1, 325, -1, -1, 91,
+ 92, 93, 94, 95, -1, 354, 355, -1, 100, 101,
+ -1, 0, 1, -1, -1, -1, -1, -1, -1, -1,
+ 350, -1, 352, 12, 13, 14, 15, -1, 17, 18,
+ 19, 20, 21, -1, 23, 24, 25, -1, -1, 28,
+ 29, -1, 31, -1, 33, -1, -1, -1, 37, -1,
+ 39, 40, 41, -1, -1, 44, -1, -1, -1, -1,
+ 49, 50, 51, -1, -1, 54, -1, -1, -1, 58,
+ 59, 60, 61, -1, 63, -1, -1, -1, -1, -1,
+ -1, -1, -1, 72, -1, -1, -1, -1, -1, -1,
+ 79, 80, 81, 82, 83, -1, -1, 86, 87, 88,
+ 89, -1, -1, 92, 93, -1, -1, -1, 97, 98,
+ -1, -1, -1, 102, 12, 13, 14, 15, -1, 17,
+ 18, 19, 20, 21, -1, 23, 24, 25, -1, -1,
+ 28, 29, -1, 31, -1, 33, -1, -1, -1, 37,
+ -1, 39, 40, 41, -1, -1, 44, -1, -1, -1,
+ -1, 49, 50, 51, -1, -1, 54, -1, -1, -1,
+ 58, 59, 60, 61, -1, 63, -1, -1, -1, -1,
+ -1, -1, -1, -1, 72, -1, -1, -1, -1, -1,
+ -1, 79, 80, 81, 82, 83, -1, -1, 86, 87,
+ 88, 89, -1, -1, 92, 93, -1, -1, -1, -1,
+ 98, -1, -1, -1, 102, 12, 13, 14, 15, -1,
+ 17, 18, 19, 20, 21, -1, 23, 24, 25, -1,
+ -1, 28, 29, -1, 31, 32, 33, -1, -1, -1,
+ 37, -1, 39, 40, 41, -1, -1, -1, -1, -1,
+ -1, -1, 49, 50, 51, -1, -1, 54, -1, -1,
+ -1, -1, -1, 60, 61, -1, 63, -1, -1, -1,
+ -1, -1, -1, -1, -1, 72, -1, -1, -1, -1,
+ -1, -1, 79, 80, 81, 82, 83, -1, -1, 86,
+ 87, -1, 89, -1, -1, 92, 93, -1, -1, -1,
+ 97, 98, -1, -1, -1, 102, 12, 13, 14, 15,
+ -1, 17, 18, 19, 20, 21, -1, 23, 24, 25,
+ -1, -1, 28, 29, -1, 31, -1, 33, -1, -1,
+ -1, 37, -1, 39, 40, 41, -1, -1, -1, -1,
+ -1, -1, -1, 49, 50, 51, -1, -1, 54, -1,
+ -1, -1, -1, -1, 60, 61, -1, 63, -1, -1,
+ -1, -1, -1, -1, -1, -1, 72, -1, -1, -1,
+ -1, -1, -1, 79, 80, 81, 82, 83, -1, -1,
+ 86, 87, -1, 89, -1, -1, 92, 93, -1, -1,
+ -1, 97, 98, -1, -1, -1, 102, 12, 13, 14,
+ 15, -1, 17, 18, 19, 20, 21, -1, 23, 24,
+ 25, -1, -1, 28, 29, -1, 31, -1, 33, -1,
+ -1, -1, 37, -1, 39, 40, 41, -1, -1, -1,
+ -1, -1, -1, -1, 49, 50, 51, -1, -1, 54,
+ -1, -1, -1, -1, -1, 60, 61, -1, 63, -1,
+ -1, -1, -1, -1, -1, -1, -1, 72, -1, -1,
+ -1, -1, -1, -1, 79, 80, 81, 82, 83, -1,
+ -1, 86, 87, -1, 89, -1, -1, 92, 93, -1,
+ -1, -1, -1, 98, -1, -1, -1, 102, 12, 13,
+ 14, 15, -1, 17, 18, 19, 20, 21, -1, 23,
+ 24, 25, -1, -1, 28, 29, -1, 31, -1, 33,
+ -1, -1, -1, 37, -1, 39, 40, -1, -1, -1,
+ 70, 71, -1, 73, -1, 49, 76, 51, -1, -1,
+ -1, -1, -1, -1, -1, -1, 60, 61, -1, 63,
+ -1, -1, 92, 93, 94, 95, -1, -1, 72, -1,
+ 100, 101, -1, -1, -1, 79, 80, 81, 82, 83,
+ -1, -1, -1, 87, -1, 89, -1, -1, 92, 93,
+ 12, 13, 14, 15, 98, -1, -1, -1, 102, -1,
+ -1, 23, 24, 25, -1, -1, 28, 29, -1, 31,
+ -1, -1, -1, -1, -1, -1, 38, -1, -1, -1,
+ -1, 43, -1, 45, 46, 47, 48, 49, -1, 51,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 72, -1, -1, -1, -1, -1, -1, 79, 80, 81,
+ 82, 83, 12, 13, 14, 15, -1, -1, -1, -1,
+ 92, 93, -1, 23, 24, 25, 98, -1, 28, 29,
+ 102, 31, -1, -1, -1, -1, -1, -1, 38, -1,
+ -1, -1, -1, -1, -1, 45, -1, 47, -1, 49,
+ -1, 51, 12, 13, 14, 15, -1, -1, -1, -1,
+ -1, -1, 62, 23, 24, 25, -1, -1, 28, 29,
+ -1, 31, 72, -1, -1, -1, -1, -1, -1, 79,
+ 80, 81, 82, 83, -1, -1, -1, -1, -1, 49,
+ -1, 51, 92, 93, -1, -1, -1, -1, 98, -1,
+ -1, -1, 102, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 72, -1, -1, -1, -1, -1, -1, 79,
+ 80, 81, 82, 83, 12, 13, 14, 15, -1, -1,
+ -1, -1, 92, 93, -1, 23, 24, 25, 98, -1,
+ 28, 29, 102, 31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 49, -1, 51, 12, 13, 14, 15, -1, -1,
+ -1, -1, -1, -1, -1, 23, 24, 25, -1, -1,
+ 28, 29, -1, 31, 72, -1, -1, -1, -1, -1,
+ -1, 79, 80, 81, 82, 83, -1, -1, -1, -1,
+ -1, 49, -1, 51, 92, 93, -1, -1, -1, -1,
+ 98, -1, -1, -1, 102, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 72, -1, -1, -1, -1, -1,
+ -1, 79, 80, 81, 82, 83, 12, 13, 14, 15,
+ -1, -1, -1, -1, 92, 93, -1, 23, 24, 25,
+ 98, -1, 28, 29, 102, 31, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 49, -1, 51, 12, 13, 14, 15,
+ -1, -1, -1, -1, -1, -1, -1, 23, 24, 25,
+ -1, -1, 28, 29, -1, 31, 72, -1, -1, -1,
+ -1, -1, -1, 79, 80, 81, 82, 83, -1, -1,
+ -1, -1, -1, 49, -1, 51, 92, 93, -1, -1,
+ -1, -1, 98, -1, -1, -1, 102, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 72, -1, -1, -1,
+ -1, 42, -1, 79, 80, 81, 82, 83, -1, -1,
+ -1, -1, -1, -1, -1, -1, 92, 93, -1, -1,
+ -1, -1, 98, 64, 65, -1, 102, -1, 69, 70,
+ 71, -1, 73, 74, 75, 76, 77, 78, -1, 47,
+ -1, -1, -1, -1, -1, 53, -1, -1, -1, -1,
+ 91, 92, 93, 94, 95, -1, 64, 65, -1, 100,
+ 101, 69, 70, 71, -1, 73, -1, -1, 76, 77,
+ 78, -1, 47, -1, -1, -1, -1, -1, 53, -1,
+ -1, -1, -1, 91, 92, 93, 94, 95, -1, 64,
+ 65, -1, 100, 101, 69, 70, 71, -1, 73, -1,
+ -1, 76, 77, 78, -1, 47, -1, -1, -1, -1,
+ -1, 53, -1, -1, -1, -1, 91, 92, 93, 94,
+ 95, -1, 64, 65, -1, 100, 101, 69, 70, 71,
+ -1, 73, -1, -1, 76, 77, 78, -1, 47, -1,
+ -1, -1, -1, -1, 53, -1, -1, -1, -1, 91,
+ 92, 93, 94, 95, -1, 64, 65, -1, 100, 101,
+ 69, 70, 71, -1, 73, -1, -1, 76, 77, 78,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 91, 92, 93, 94, 95, -1, 64, 65,
+ -1, 100, 101, 69, 70, 71, -1, 73, -1, -1,
+ 76, 77, 78, -1, 47, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 91, 92, 93, 94, 95,
+ -1, 64, 65, -1, 100, 101, 69, 70, 71, -1,
+ 73, -1, -1, 76, 77, 78, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 91, 92,
+ 93, 94, 95, -1, 64, 65, -1, 100, 101, 69,
+ 70, 71, -1, 73, -1, -1, 76, 77, 78, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 91, 92, 93, 94, 95, -1, 64, 65, -1,
+ 100, 101, 69, 70, 71, -1, 73, -1, -1, 76,
+ 77, 78, -1, -1, -1, -1, -1, -1, -1, 53,
+ -1, -1, -1, -1, 91, 92, 93, 94, 95, -1,
+ 64, 65, -1, 100, 101, 69, 70, 71, -1, 73,
+ -1, -1, 76, 77, 78, -1, -1, -1, -1, -1,
+ -1, -1, -1, 53, -1, -1, -1, 91, 92, 93,
+ 94, 95, -1, 97, 64, 65, 100, 101, -1, 69,
+ 70, 71, -1, 73, -1, -1, 76, 77, 78, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 55, -1,
+ 90, 91, 92, 93, 94, 95, -1, 64, 65, -1,
+ 100, 101, 69, 70, 71, -1, 73, -1, -1, 76,
+ 77, 78, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 91, 92, 93, 94, 95, -1,
+ 64, 65, -1, 100, 101, 69, 70, 71, -1, 73,
+ -1, -1, 76, 77, 78, -1, -1, -1, -1, -1,
+ 84, 85, -1, -1, -1, -1, -1, 91, 92, 93,
+ 94, 95, -1, 64, 65, -1, 100, 101, 69, 70,
+ 71, -1, 73, -1, -1, 76, 77, 78, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 90,
+ 91, 92, 93, 94, 95, -1, 64, 65, 99, 100,
+ 101, 69, 70, 71, -1, 73, -1, -1, 76, 77,
+ 78, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 91, 92, 93, 94, 95, -1, 64,
+ 65, 99, 100, 101, 69, 70, 71, -1, 73, -1,
+ -1, 76, 77, 78, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 90, 91, 92, 93, 94,
+ 95, -1, 64, 65, -1, 100, 101, 69, 70, 71,
+ -1, 73, -1, -1, 76, 77, 78, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 91,
+ 92, 93, 94, 95, -1, -1, -1, -1, 100, 101
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 1, 11, 12, 13, 14, 16, 17, 18, 19,
- 20, 21, 22, 24, 26, 30, 32, 33, 34, 37,
- 42, 43, 44, 47, 51, 52, 53, 54, 56, 65,
- 72, 73, 74, 75, 76, 79, 80, 83, 84, 89,
- 93, 97, 99, 100, 101, 102, 103, 110, 111, 112,
- 117, 118, 119, 122, 125, 127, 134, 88, 98, 21,
- 42, 118, 118, 118, 89, 118, 135, 21, 89, 118,
- 135, 136, 126, 43, 21, 120, 31, 36, 38, 39,
- 40, 41, 118, 123, 124, 21, 118, 48, 49, 12,
- 13, 21, 21, 21, 21, 118, 55, 123, 124, 21,
- 121, 118, 118, 118, 118, 118, 118, 21, 89, 118,
- 118, 118, 135, 0, 98, 89, 81, 89, 109, 118,
- 118, 57, 58, 62, 63, 64, 66, 69, 70, 71,
- 82, 83, 84, 85, 86, 91, 92, 89, 118, 118,
- 135, 95, 135, 135, 95, 135, 95, 118, 118, 38,
- 124, 128, 35, 67, 68, 21, 46, 81, 118, 46,
- 81, 45, 129, 48, 124, 95, 40, 46, 40, 46,
- 40, 46, 40, 46, 77, 78, 130, 21, 90, 94,
- 99, 109, 118, 109, 118, 45, 81, 115, 118, 118,
- 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
- 118, 118, 118, 118, 90, 118, 90, 118, 21, 118,
- 114, 21, 118, 118, 118, 118, 46, 81, 118, 118,
- 114, 118, 21, 118, 118, 118, 118, 118, 118, 118,
- 118, 118, 118, 114, 90, 95, 90, 115, 90, 98,
- 114, 118, 21, 132, 118, 118, 132, 40, 40, 40,
- 40, 131, 135, 116, 27, 46, 116, 101, 95, 98,
- 98, 118, 118, 118, 118, 132, 90, 98, 102, 115,
- 46, 118, 115, 115, 21, 95, 133, 133, 98, 25,
- 118, 115, 25, 50, 114, 29, 50, 106, 107, 113,
- 21, 116, 116, 133, 115, 116, 116, 105, 106, 108,
- 113, 114, 107, 115, 109, 116, 116, 115, 115, 108,
- 115, 109, 101, 50, 104, 45, 25, 115, 25, 25,
- 25, 45, 115, 114, 115, 114, 25, 114, 101, 102,
- 116, 115, 115
+ 0, 1, 12, 13, 14, 15, 17, 18, 19, 20,
+ 21, 23, 24, 25, 28, 29, 31, 33, 37, 39,
+ 40, 41, 44, 49, 50, 51, 54, 58, 59, 60,
+ 61, 63, 72, 79, 80, 81, 82, 83, 86, 87,
+ 88, 89, 92, 93, 98, 102, 106, 108, 109, 110,
+ 111, 112, 119, 120, 121, 126, 127, 128, 130, 134,
+ 137, 139, 146, 97, 107, 28, 49, 128, 128, 128,
+ 98, 128, 148, 28, 128, 98, 148, 98, 148, 138,
+ 50, 28, 131, 38, 43, 45, 46, 47, 48, 128,
+ 135, 136, 28, 128, 55, 56, 13, 14, 28, 28,
+ 28, 28, 128, 62, 135, 136, 28, 133, 128, 128,
+ 128, 128, 128, 128, 28, 132, 28, 98, 128, 128,
+ 128, 128, 147, 0, 107, 98, 90, 98, 118, 128,
+ 110, 128, 64, 65, 69, 70, 71, 73, 76, 77,
+ 78, 91, 92, 93, 94, 95, 100, 101, 98, 128,
+ 128, 148, 104, 147, 148, 128, 147, 147, 104, 128,
+ 128, 45, 136, 140, 42, 74, 75, 28, 53, 90,
+ 128, 53, 90, 52, 141, 55, 136, 104, 47, 53,
+ 47, 53, 47, 53, 47, 53, 84, 85, 104, 142,
+ 28, 99, 103, 104, 108, 118, 128, 118, 128, 52,
+ 90, 124, 53, 107, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 99, 128, 99, 99, 28, 128, 123, 27, 28, 129,
+ 128, 128, 128, 128, 53, 90, 128, 128, 123, 128,
+ 28, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 28, 123, 99, 104, 128, 99, 124, 99, 107,
+ 123, 128, 128, 125, 28, 144, 128, 128, 128, 144,
+ 47, 47, 47, 47, 143, 147, 125, 34, 53, 125,
+ 110, 107, 111, 124, 104, 107, 107, 128, 128, 128,
+ 128, 144, 99, 124, 53, 128, 124, 124, 32, 28,
+ 104, 145, 145, 107, 32, 128, 124, 32, 57, 123,
+ 36, 57, 115, 116, 122, 28, 125, 125, 145, 124,
+ 125, 125, 114, 115, 117, 122, 123, 116, 124, 118,
+ 125, 125, 124, 124, 117, 124, 118, 110, 57, 113,
+ 52, 32, 124, 32, 32, 32, 52, 124, 123, 124,
+ 123, 32, 123, 110, 111, 125, 124, 124
};
#define yyerrok (yyerrstatus = 0)
@@ -2070,12 +2154,12 @@ yyreduce:
switch (yyn)
{
case 4:
-#line 119 "engines/director/lingo/lingo-gr.y"
+#line 120 "engines/director/lingo/lingo-gr.y"
{ yyerrok; ;}
break;
case 5:
-#line 122 "engines/director/lingo/lingo-gr.y"
+#line 123 "engines/director/lingo/lingo-gr.y"
{
g_lingo->_linenumber++;
g_lingo->_colnumber = 1;
@@ -2083,7 +2167,7 @@ yyreduce:
break;
case 10:
-#line 133 "engines/director/lingo/lingo-gr.y"
+#line 134 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_varpush);
g_lingo->codeString((yyvsp[(4) - (4)].s)->c_str());
@@ -2093,17 +2177,24 @@ yyreduce:
break;
case 11:
-#line 139 "engines/director/lingo/lingo-gr.y"
- { (yyval.code) = g_lingo->code1(g_lingo->c_after); ;}
+#line 140 "engines/director/lingo/lingo-gr.y"
+ {
+ g_lingo->code1(g_lingo->c_assign);
+ (yyval.code) = (yyvsp[(2) - (4)].code); ;}
break;
case 12:
-#line 140 "engines/director/lingo/lingo-gr.y"
- { (yyval.code) = g_lingo->code1(g_lingo->c_before); ;}
+#line 143 "engines/director/lingo/lingo-gr.y"
+ { (yyval.code) = g_lingo->code1(g_lingo->c_after); ;}
break;
case 13:
-#line 141 "engines/director/lingo/lingo-gr.y"
+#line 144 "engines/director/lingo/lingo-gr.y"
+ { (yyval.code) = g_lingo->code1(g_lingo->c_before); ;}
+ break;
+
+ case 14:
+#line 145 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_varpush);
g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str());
@@ -2112,8 +2203,8 @@ yyreduce:
delete (yyvsp[(2) - (4)].s); ;}
break;
- case 14:
-#line 147 "engines/director/lingo/lingo-gr.y"
+ case 15:
+#line 151 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(0); // Put dummy id
g_lingo->code1(g_lingo->c_theentityassign);
@@ -2124,8 +2215,8 @@ yyreduce:
(yyval.code) = (yyvsp[(4) - (4)].code); ;}
break;
- case 15:
-#line 155 "engines/director/lingo/lingo-gr.y"
+ case 16:
+#line 159 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_swap);
g_lingo->code1(g_lingo->c_theentityassign);
@@ -2136,8 +2227,8 @@ yyreduce:
(yyval.code) = (yyvsp[(5) - (5)].code); ;}
break;
- case 16:
-#line 163 "engines/director/lingo/lingo-gr.y"
+ case 17:
+#line 167 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_varpush);
g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str());
@@ -2146,8 +2237,8 @@ yyreduce:
delete (yyvsp[(2) - (4)].s); ;}
break;
- case 17:
-#line 169 "engines/director/lingo/lingo-gr.y"
+ case 18:
+#line 173 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(0); // Put dummy id
g_lingo->code1(g_lingo->c_theentityassign);
@@ -2158,8 +2249,8 @@ yyreduce:
(yyval.code) = (yyvsp[(4) - (4)].code); ;}
break;
- case 18:
-#line 177 "engines/director/lingo/lingo-gr.y"
+ case 19:
+#line 181 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_swap);
g_lingo->code1(g_lingo->c_theentityassign);
@@ -2170,31 +2261,26 @@ yyreduce:
(yyval.code) = (yyvsp[(5) - (5)].code); ;}
break;
- case 19:
-#line 187 "engines/director/lingo/lingo-gr.y"
- { g_lingo->code1(g_lingo->c_xpop); ;}
- break;
-
- case 23:
-#line 197 "engines/director/lingo/lingo-gr.y"
+ case 24:
+#line 201 "engines/director/lingo/lingo-gr.y"
{
inst body = 0, end = 0;
- WRITE_UINT32(&body, (yyvsp[(5) - (7)].code));
- WRITE_UINT32(&end, (yyvsp[(6) - (7)].code));
+ WRITE_UINT32(&body, (yyvsp[(5) - (7)].code) - (yyvsp[(1) - (7)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (7)].code) - (yyvsp[(1) - (7)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 1] = body; /* body of loop */
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 2] = end; /* end, if cond fails */
checkEnd((yyvsp[(7) - (7)].s), "repeat", true); ;}
break;
- case 24:
-#line 210 "engines/director/lingo/lingo-gr.y"
+ case 25:
+#line 214 "engines/director/lingo/lingo-gr.y"
{
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, (yyvsp[(3) - (10)].code));
- WRITE_UINT32(&finish, (yyvsp[(6) - (10)].code));
- WRITE_UINT32(&body, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&init, (yyvsp[(3) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&finish, (yyvsp[(6) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&body, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
WRITE_UINT32(&inc, 1);
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = finish;/* final count value */
@@ -2205,14 +2291,14 @@ yyreduce:
checkEnd((yyvsp[(10) - (10)].s), "repeat", true); ;}
break;
- case 25:
-#line 228 "engines/director/lingo/lingo-gr.y"
+ case 26:
+#line 232 "engines/director/lingo/lingo-gr.y"
{
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, (yyvsp[(3) - (11)].code));
- WRITE_UINT32(&finish, (yyvsp[(7) - (11)].code));
- WRITE_UINT32(&body, (yyvsp[(9) - (11)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (11)].code));
+ WRITE_UINT32(&init, (yyvsp[(3) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&finish, (yyvsp[(7) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&body, (yyvsp[(9) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (11)].code) - (yyvsp[(1) - (11)].code));
WRITE_UINT32(&inc, -1);
(*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 2] = finish;/* final count value */
@@ -2223,22 +2309,36 @@ yyreduce:
checkEnd((yyvsp[(11) - (11)].s), "repeat", true); ;}
break;
- case 26:
-#line 242 "engines/director/lingo/lingo-gr.y"
+ case 27:
+#line 246 "engines/director/lingo/lingo-gr.y"
{
inst end = 0;
- WRITE_UINT32(&end, (yyvsp[(3) - (3)].code));
+ WRITE_UINT32(&end, (yyvsp[(3) - (3)].code) - (yyvsp[(1) - (3)].code));
g_lingo->code1(STOP);
(*g_lingo->_currentScript)[(yyvsp[(1) - (3)].code) + 1] = end;
;}
break;
- case 27:
-#line 250 "engines/director/lingo/lingo-gr.y"
+ case 28:
+#line 252 "engines/director/lingo/lingo-gr.y"
+ {
+ warning("STUB: TELL is not implemented");
+ checkEnd((yyvsp[(6) - (6)].s), "tell", true); ;}
+ break;
+
+ case 29:
+#line 255 "engines/director/lingo/lingo-gr.y"
+ {
+ warning("STUB: TELL is not implemented");
+ ;}
+ break;
+
+ case 30:
+#line 260 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (7)].code));
- WRITE_UINT32(&end, (yyvsp[(6) - (7)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (7)].code) - (yyvsp[(1) - (7)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (7)].code) - (yyvsp[(1) - (7)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 3] = end; /* end, if cond fails */
@@ -2247,13 +2347,13 @@ yyreduce:
g_lingo->processIf(0, 0); ;}
break;
- case 28:
-#line 260 "engines/director/lingo/lingo-gr.y"
+ case 31:
+#line 270 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
@@ -2263,29 +2363,29 @@ yyreduce:
g_lingo->processIf(0, 0); ;}
break;
- case 29:
-#line 272 "engines/director/lingo/lingo-gr.y"
+ case 32:
+#line 282 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(7) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(7) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
checkEnd((yyvsp[(10) - (10)].s), "if", true);
- g_lingo->processIf(0, (yyvsp[(9) - (10)].code)); ;}
+ g_lingo->processIf(0, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code)); ;}
break;
- case 30:
-#line 284 "engines/director/lingo/lingo-gr.y"
+ case 33:
+#line 294 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (6)].code) - (yyvsp[(1) - (6)].code));
WRITE_UINT32(&else1, 0);
- WRITE_UINT32(&end, (yyvsp[(6) - (6)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 3] = end; /* end, if cond fails */
@@ -2293,13 +2393,13 @@ yyreduce:
g_lingo->processIf(0, 0); ;}
break;
- case 31:
-#line 294 "engines/director/lingo/lingo-gr.y"
+ case 34:
+#line 304 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
@@ -2307,67 +2407,67 @@ yyreduce:
g_lingo->processIf(0, 0); ;}
break;
- case 32:
-#line 304 "engines/director/lingo/lingo-gr.y"
+ case 35:
+#line 314 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(6) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(6) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
- g_lingo->processIf(0, (yyvsp[(10) - (10)].code)); ;}
+ g_lingo->processIf(0, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code)); ;}
break;
- case 33:
-#line 316 "engines/director/lingo/lingo-gr.y"
+ case 36:
+#line 326 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = 0; ;}
break;
- case 34:
-#line 317 "engines/director/lingo/lingo-gr.y"
+ case 37:
+#line 327 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = (yyvsp[(2) - (3)].code); ;}
break;
- case 39:
-#line 328 "engines/director/lingo/lingo-gr.y"
+ case 42:
+#line 338 "engines/director/lingo/lingo-gr.y"
{
inst then = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;}
break;
- case 41:
-#line 337 "engines/director/lingo/lingo-gr.y"
+ case 44:
+#line 347 "engines/director/lingo/lingo-gr.y"
{
inst then = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;}
break;
- case 42:
-#line 345 "engines/director/lingo/lingo-gr.y"
+ case 45:
+#line 355 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(STOP); ;}
break;
- case 43:
-#line 346 "engines/director/lingo/lingo-gr.y"
+ case 46:
+#line 356 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code2(g_lingo->c_eq, STOP); ;}
break;
- case 45:
-#line 350 "engines/director/lingo/lingo-gr.y"
+ case 48:
+#line 360 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = g_lingo->code3(g_lingo->c_repeatwhilecode, STOP, STOP); ;}
break;
- case 46:
-#line 353 "engines/director/lingo/lingo-gr.y"
+ case 49:
+#line 363 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code3(g_lingo->c_repeatwithcode, STOP, STOP);
g_lingo->code3(STOP, STOP, STOP);
@@ -2375,8 +2475,8 @@ yyreduce:
delete (yyvsp[(3) - (3)].s); ;}
break;
- case 47:
-#line 360 "engines/director/lingo/lingo-gr.y"
+ case 50:
+#line 370 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_ifcode);
g_lingo->code3(STOP, STOP, STOP);
@@ -2384,8 +2484,8 @@ yyreduce:
g_lingo->codeLabel(0); ;}
break;
- case 48:
-#line 367 "engines/director/lingo/lingo-gr.y"
+ case 51:
+#line 377 "engines/director/lingo/lingo-gr.y"
{
inst skipEnd;
WRITE_UINT32(&skipEnd, 1); // We have to skip end to avoid multiple executions
@@ -2394,23 +2494,23 @@ yyreduce:
g_lingo->code1(skipEnd); ;}
break;
- case 49:
-#line 375 "engines/director/lingo/lingo-gr.y"
+ case 52:
+#line 385 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = g_lingo->_currentScript->size(); ;}
break;
- case 50:
-#line 378 "engines/director/lingo/lingo-gr.y"
+ case 53:
+#line 388 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(STOP); (yyval.code) = g_lingo->_currentScript->size(); ;}
break;
- case 51:
-#line 381 "engines/director/lingo/lingo-gr.y"
+ case 54:
+#line 391 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = g_lingo->_currentScript->size(); ;}
break;
- case 54:
-#line 386 "engines/director/lingo/lingo-gr.y"
+ case 57:
+#line 396 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_whencode);
g_lingo->code1(STOP);
@@ -2418,56 +2518,80 @@ yyreduce:
delete (yyvsp[(2) - (3)].s); ;}
break;
- case 55:
-#line 392 "engines/director/lingo/lingo-gr.y"
+ case 58:
+#line 402 "engines/director/lingo/lingo-gr.y"
+ {
+ (yyval.code) = g_lingo->code1(g_lingo->c_tellcode);
+ g_lingo->code1(STOP); ;}
+ break;
+
+ case 59:
+#line 406 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = g_lingo->codeConst((yyvsp[(1) - (1)].i)); ;}
break;
- case 56:
-#line 393 "engines/director/lingo/lingo-gr.y"
+ case 60:
+#line 407 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_fconstpush);
g_lingo->codeFloat((yyvsp[(1) - (1)].f)); ;}
break;
- case 57:
-#line 396 "engines/director/lingo/lingo-gr.y"
+ case 61:
+#line 410 "engines/director/lingo/lingo-gr.y"
{ // D3
(yyval.code) = g_lingo->code1(g_lingo->c_symbolpush);
g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); ;}
break;
- case 58:
-#line 399 "engines/director/lingo/lingo-gr.y"
+ case 62:
+#line 413 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_stringpush);
g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); ;}
break;
- case 59:
-#line 402 "engines/director/lingo/lingo-gr.y"
+ case 63:
+#line 416 "engines/director/lingo/lingo-gr.y"
{
- (yyval.code) = g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func);
+ g_lingo->codeFunc((yyvsp[(1) - (1)].s), 0);
delete (yyvsp[(1) - (1)].s); ;}
break;
- case 60:
-#line 405 "engines/director/lingo/lingo-gr.y"
+ case 64:
+#line 419 "engines/director/lingo/lingo-gr.y"
+ {
+ g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
+ delete (yyvsp[(1) - (2)].s); ;}
+ break;
+
+ case 65:
+#line 422 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;}
+ break;
+
+ case 66:
+#line 423 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;}
+ break;
+
+ case 67:
+#line 424 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg));
delete (yyvsp[(1) - (4)].s); ;}
break;
- case 61:
-#line 408 "engines/director/lingo/lingo-gr.y"
+ case 68:
+#line 427 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_eval);
g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str());
delete (yyvsp[(1) - (1)].s); ;}
break;
- case 62:
-#line 412 "engines/director/lingo/lingo-gr.y"
+ case 69:
+#line 431 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->codeConst(0); // Put dummy id
g_lingo->code1(g_lingo->c_theentitypush);
@@ -2477,8 +2601,8 @@ yyreduce:
g_lingo->code2(e, f); ;}
break;
- case 63:
-#line 419 "engines/director/lingo/lingo-gr.y"
+ case 70:
+#line 438 "engines/director/lingo/lingo-gr.y"
{
(yyval.code) = g_lingo->code1(g_lingo->c_theentitypush);
inst e = 0, f = 0;
@@ -2487,375 +2611,397 @@ yyreduce:
g_lingo->code2(e, f); ;}
break;
- case 65:
-#line 426 "engines/director/lingo/lingo-gr.y"
+ case 72:
+#line 445 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_add); ;}
break;
- case 66:
-#line 427 "engines/director/lingo/lingo-gr.y"
+ case 73:
+#line 446 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_sub); ;}
break;
- case 67:
-#line 428 "engines/director/lingo/lingo-gr.y"
+ case 74:
+#line 447 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_mul); ;}
break;
- case 68:
-#line 429 "engines/director/lingo/lingo-gr.y"
+ case 75:
+#line 448 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_div); ;}
break;
- case 69:
-#line 430 "engines/director/lingo/lingo-gr.y"
+ case 76:
+#line 449 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_mod); ;}
break;
- case 70:
-#line 431 "engines/director/lingo/lingo-gr.y"
+ case 77:
+#line 450 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gt); ;}
break;
- case 71:
-#line 432 "engines/director/lingo/lingo-gr.y"
+ case 78:
+#line 451 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_lt); ;}
break;
- case 72:
-#line 433 "engines/director/lingo/lingo-gr.y"
+ case 79:
+#line 452 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_neq); ;}
break;
- case 73:
-#line 434 "engines/director/lingo/lingo-gr.y"
+ case 80:
+#line 453 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_ge); ;}
break;
- case 74:
-#line 435 "engines/director/lingo/lingo-gr.y"
+ case 81:
+#line 454 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_le); ;}
break;
- case 75:
-#line 436 "engines/director/lingo/lingo-gr.y"
+ case 82:
+#line 455 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_and); ;}
break;
- case 76:
-#line 437 "engines/director/lingo/lingo-gr.y"
+ case 83:
+#line 456 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_or); ;}
break;
- case 77:
-#line 438 "engines/director/lingo/lingo-gr.y"
+ case 84:
+#line 457 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_not); ;}
break;
- case 78:
-#line 439 "engines/director/lingo/lingo-gr.y"
+ case 85:
+#line 458 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_ampersand); ;}
break;
- case 79:
-#line 440 "engines/director/lingo/lingo-gr.y"
+ case 86:
+#line 459 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_concat); ;}
break;
- case 80:
-#line 441 "engines/director/lingo/lingo-gr.y"
+ case 87:
+#line 460 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_contains); ;}
break;
- case 81:
-#line 442 "engines/director/lingo/lingo-gr.y"
+ case 88:
+#line 461 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_starts); ;}
break;
- case 82:
-#line 443 "engines/director/lingo/lingo-gr.y"
+ case 89:
+#line 462 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = (yyvsp[(2) - (2)].code); ;}
break;
- case 83:
-#line 444 "engines/director/lingo/lingo-gr.y"
+ case 90:
+#line 463 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = (yyvsp[(2) - (2)].code); g_lingo->code1(g_lingo->c_negate); ;}
break;
- case 84:
-#line 445 "engines/director/lingo/lingo-gr.y"
+ case 91:
+#line 464 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = (yyvsp[(2) - (3)].code); ;}
break;
- case 85:
-#line 446 "engines/director/lingo/lingo-gr.y"
+ case 92:
+#line 465 "engines/director/lingo/lingo-gr.y"
{ (yyval.code) = g_lingo->codeArray((yyvsp[(2) - (3)].narg)); ;}
break;
- case 86:
-#line 447 "engines/director/lingo/lingo-gr.y"
+ case 93:
+#line 466 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_intersects); ;}
break;
- case 87:
-#line 448 "engines/director/lingo/lingo-gr.y"
+ case 94:
+#line 467 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_within); ;}
break;
- case 88:
-#line 449 "engines/director/lingo/lingo-gr.y"
+ case 95:
+#line 468 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_charOf); ;}
break;
- case 89:
-#line 450 "engines/director/lingo/lingo-gr.y"
+ case 96:
+#line 469 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_charToOf); ;}
break;
- case 90:
-#line 451 "engines/director/lingo/lingo-gr.y"
+ case 97:
+#line 470 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_itemOf); ;}
break;
- case 91:
-#line 452 "engines/director/lingo/lingo-gr.y"
+ case 98:
+#line 471 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_itemToOf); ;}
break;
- case 92:
-#line 453 "engines/director/lingo/lingo-gr.y"
+ case 99:
+#line 472 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_lineOf); ;}
break;
- case 93:
-#line 454 "engines/director/lingo/lingo-gr.y"
+ case 100:
+#line 473 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_lineToOf); ;}
break;
- case 94:
-#line 455 "engines/director/lingo/lingo-gr.y"
+ case 101:
+#line 474 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_wordOf); ;}
break;
- case 95:
-#line 456 "engines/director/lingo/lingo-gr.y"
+ case 102:
+#line 475 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_wordToOf); ;}
break;
- case 96:
-#line 459 "engines/director/lingo/lingo-gr.y"
+ case 103:
+#line 478 "engines/director/lingo/lingo-gr.y"
+ {
+ g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
+ delete (yyvsp[(1) - (2)].s); ;}
+ break;
+
+ case 104:
+#line 483 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_printtop); ;}
break;
- case 99:
-#line 462 "engines/director/lingo/lingo-gr.y"
+ case 107:
+#line 486 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_exitRepeat); ;}
break;
- case 100:
-#line 463 "engines/director/lingo/lingo-gr.y"
- { g_lingo->codeConst(0); // Push fake value on stack
- g_lingo->code1(g_lingo->c_procret); ;}
+ case 108:
+#line 487 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->code1(g_lingo->c_procret); ;}
break;
- case 103:
-#line 467 "engines/director/lingo/lingo-gr.y"
+ case 112:
+#line 491 "engines/director/lingo/lingo-gr.y"
+ {
+ g_lingo->codeFunc((yyvsp[(1) - (1)].s), 0);
+ delete (yyvsp[(1) - (1)].s); ;}
+ break;
+
+ case 113:
+#line 494 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func);
+ g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
delete (yyvsp[(1) - (2)].s); ;}
break;
- case 104:
-#line 470 "engines/director/lingo/lingo-gr.y"
+ case 114:
+#line 497 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code1(g_lingo->_builtins[*(yyvsp[(1) - (2)].s)]->u.func);
+ g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
delete (yyvsp[(1) - (2)].s); ;}
break;
- case 105:
-#line 473 "engines/director/lingo/lingo-gr.y"
+ case 115:
+#line 500 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*(yyvsp[(1) - (1)].s)]->u.func);
+ g_lingo->code1(g_lingo->c_voidpush);
+ g_lingo->codeFunc((yyvsp[(1) - (1)].s), 1);
delete (yyvsp[(1) - (1)].s); ;}
break;
- case 106:
-#line 476 "engines/director/lingo/lingo-gr.y"
- { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;}
+ case 116:
+#line 504 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;}
break;
- case 107:
-#line 477 "engines/director/lingo/lingo-gr.y"
- { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;}
+ case 117:
+#line 505 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;}
break;
- case 108:
-#line 478 "engines/director/lingo/lingo-gr.y"
+ case 118:
+#line 506 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeMe((yyvsp[(3) - (4)].s), 0); ;}
break;
- case 109:
-#line 479 "engines/director/lingo/lingo-gr.y"
+ case 119:
+#line 507 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeMe((yyvsp[(3) - (6)].s), (yyvsp[(5) - (6)].narg)); ;}
break;
- case 110:
-#line 480 "engines/director/lingo/lingo-gr.y"
+ case 120:
+#line 508 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_open); ;}
break;
- case 111:
-#line 481 "engines/director/lingo/lingo-gr.y"
+ case 121:
+#line 509 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); ;}
break;
- case 112:
-#line 482 "engines/director/lingo/lingo-gr.y"
+ case 122:
+#line 510 "engines/director/lingo/lingo-gr.y"
{ Common::String s(*(yyvsp[(1) - (3)].s)); s += '-'; s += *(yyvsp[(2) - (3)].s); g_lingo->codeFunc(&s, (yyvsp[(3) - (3)].narg)); ;}
break;
- case 113:
-#line 485 "engines/director/lingo/lingo-gr.y"
+ case 123:
+#line 513 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
- case 114:
-#line 486 "engines/director/lingo/lingo-gr.y"
+ case 124:
+#line 514 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
- case 115:
-#line 489 "engines/director/lingo/lingo-gr.y"
+ case 125:
+#line 517 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
+ break;
+
+ case 126:
+#line 518 "engines/director/lingo/lingo-gr.y"
+ { g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
+ break;
+
+ case 127:
+#line 521 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
- case 116:
-#line 490 "engines/director/lingo/lingo-gr.y"
+ case 128:
+#line 522 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
- case 117:
-#line 501 "engines/director/lingo/lingo-gr.y"
+ case 129:
+#line 533 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoloop); ;}
break;
- case 118:
-#line 502 "engines/director/lingo/lingo-gr.y"
+ case 130:
+#line 534 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotonext); ;}
break;
- case 119:
-#line 503 "engines/director/lingo/lingo-gr.y"
+ case 131:
+#line 535 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoprevious); ;}
break;
- case 120:
-#line 504 "engines/director/lingo/lingo-gr.y"
+ case 132:
+#line 536 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(1);
g_lingo->code1(g_lingo->c_goto); ;}
break;
- case 121:
-#line 507 "engines/director/lingo/lingo-gr.y"
+ case 133:
+#line 539 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(3);
g_lingo->code1(g_lingo->c_goto); ;}
break;
- case 122:
-#line 510 "engines/director/lingo/lingo-gr.y"
+ case 134:
+#line 542 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(2);
g_lingo->code1(g_lingo->c_goto); ;}
break;
- case 127:
-#line 523 "engines/director/lingo/lingo-gr.y"
+ case 139:
+#line 555 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_playdone); ;}
break;
- case 128:
-#line 524 "engines/director/lingo/lingo-gr.y"
+ case 140:
+#line 556 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(1);
g_lingo->code1(g_lingo->c_play); ;}
break;
- case 129:
-#line 527 "engines/director/lingo/lingo-gr.y"
+ case 141:
+#line 559 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(3);
g_lingo->code1(g_lingo->c_play); ;}
break;
- case 130:
-#line 530 "engines/director/lingo/lingo-gr.y"
+ case 142:
+#line 562 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(2);
g_lingo->code1(g_lingo->c_play); ;}
break;
- case 131:
-#line 533 "engines/director/lingo/lingo-gr.y"
+ case 143:
+#line 565 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeSetImmediate(true); ;}
break;
- case 132:
-#line 533 "engines/director/lingo/lingo-gr.y"
+ case 144:
+#line 565 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeSetImmediate(false);
g_lingo->codeFunc((yyvsp[(1) - (3)].s), (yyvsp[(3) - (3)].narg)); ;}
break;
- case 133:
-#line 563 "engines/director/lingo/lingo-gr.y"
+ case 145:
+#line 595 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;}
break;
- case 134:
-#line 564 "engines/director/lingo/lingo-gr.y"
+ case 146:
+#line 596 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg));
g_lingo->_indef = false; ;}
break;
- case 135:
-#line 569 "engines/director/lingo/lingo-gr.y"
+ case 147:
+#line 600 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeFactory(*(yyvsp[(2) - (2)].s));
;}
break;
- case 136:
-#line 572 "engines/director/lingo/lingo-gr.y"
+ case 148:
+#line 603 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; ;}
break;
- case 137:
-#line 573 "engines/director/lingo/lingo-gr.y"
+ case 149:
+#line 604 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg) + 1, &g_lingo->_currentFactory);
g_lingo->_indef = false; ;}
break;
- case 138:
-#line 577 "engines/director/lingo/lingo-gr.y"
+ case 150:
+#line 608 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;}
break;
- case 139:
-#line 578 "engines/director/lingo/lingo-gr.y"
+ case 151:
+#line 609 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_ignoreMe = true; ;}
break;
- case 140:
-#line 578 "engines/director/lingo/lingo-gr.y"
+ case 152:
+#line 609 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (10)].s), (yyvsp[(4) - (10)].code), (yyvsp[(6) - (10)].narg));
g_lingo->_indef = false;
@@ -2865,33 +3011,33 @@ yyreduce:
;}
break;
- case 141:
-#line 588 "engines/director/lingo/lingo-gr.y"
+ case 153:
+#line 618 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
- case 142:
-#line 589 "engines/director/lingo/lingo-gr.y"
+ case 154:
+#line 619 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;}
break;
- case 143:
-#line 590 "engines/director/lingo/lingo-gr.y"
+ case 155:
+#line 620 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
- case 144:
-#line 591 "engines/director/lingo/lingo-gr.y"
+ case 156:
+#line 621 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;}
break;
- case 145:
-#line 594 "engines/director/lingo/lingo-gr.y"
+ case 157:
+#line 624 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArgStore(); ;}
break;
- case 146:
-#line 598 "engines/director/lingo/lingo-gr.y"
+ case 158:
+#line 628 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_call);
g_lingo->codeString((yyvsp[(1) - (2)].s)->c_str());
@@ -2900,34 +3046,34 @@ yyreduce:
g_lingo->code1(numpar); ;}
break;
- case 147:
-#line 606 "engines/director/lingo/lingo-gr.y"
+ case 159:
+#line 636 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
- case 148:
-#line 607 "engines/director/lingo/lingo-gr.y"
+ case 160:
+#line 637 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 1; ;}
break;
- case 149:
-#line 608 "engines/director/lingo/lingo-gr.y"
+ case 161:
+#line 638 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
- case 150:
-#line 611 "engines/director/lingo/lingo-gr.y"
+ case 162:
+#line 641 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 1; ;}
break;
- case 151:
-#line 612 "engines/director/lingo/lingo-gr.y"
+ case 163:
+#line 642 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
/* Line 1267 of yacc.c. */
-#line 2931 "engines/director/lingo/lingo-gr.cpp"
+#line 3077 "engines/director/lingo/lingo-gr.cpp"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3141,6 +3287,6 @@ yyreturn:
}
-#line 615 "engines/director/lingo/lingo-gr.y"
+#line 645 "engines/director/lingo/lingo-gr.y"
diff --git a/engines/director/lingo/lingo-gr.h b/engines/director/lingo/lingo-gr.h
index 5f9a89477e..fc2959872c 100644
--- a/engines/director/lingo/lingo-gr.h
+++ b/engines/director/lingo/lingo-gr.h
@@ -47,76 +47,85 @@
RECT = 263,
ARRAY = 264,
OBJECT = 265,
- INT = 266,
- THEENTITY = 267,
- THEENTITYWITHID = 268,
- FLOAT = 269,
- BLTIN = 270,
- BLTINNOARGS = 271,
- BLTINNOARGSORONE = 272,
- BLTINONEARG = 273,
- BLTINARGLIST = 274,
- TWOWORDBUILTIN = 275,
- ID = 276,
- STRING = 277,
- HANDLER = 278,
- SYMBOL = 279,
- ENDCLAUSE = 280,
- tPLAYACCEL = 281,
- tDOWN = 282,
- tELSE = 283,
- tNLELSIF = 284,
- tEXIT = 285,
- tFRAME = 286,
- tGLOBAL = 287,
- tGO = 288,
- tIF = 289,
- tINTO = 290,
- tLOOP = 291,
- tMACRO = 292,
- tMOVIE = 293,
- tNEXT = 294,
- tOF = 295,
- tPREVIOUS = 296,
- tPUT = 297,
- tREPEAT = 298,
- tSET = 299,
- tTHEN = 300,
- tTO = 301,
- tWHEN = 302,
- tWITH = 303,
- tWHILE = 304,
- tNLELSE = 305,
- tFACTORY = 306,
- tMETHOD = 307,
- tOPEN = 308,
- tPLAY = 309,
- tDONE = 310,
- tINSTANCE = 311,
- tGE = 312,
- tLE = 313,
- tGT = 314,
- tLT = 315,
- tEQ = 316,
- tNEQ = 317,
- tAND = 318,
- tOR = 319,
- tNOT = 320,
- tMOD = 321,
- tAFTER = 322,
- tBEFORE = 323,
- tCONCAT = 324,
- tCONTAINS = 325,
- tSTARTS = 326,
- tCHAR = 327,
- tITEM = 328,
- tLINE = 329,
- tWORD = 330,
- tSPRITE = 331,
- tINTERSECTS = 332,
- tWITHIN = 333,
- tON = 334,
- tME = 335
+ REFERENCE = 266,
+ INT = 267,
+ THEENTITY = 268,
+ THEENTITYWITHID = 269,
+ FLOAT = 270,
+ BLTIN = 271,
+ BLTINNOARGS = 272,
+ BLTINNOARGSORONE = 273,
+ BLTINONEARG = 274,
+ BLTINARGLIST = 275,
+ TWOWORDBUILTIN = 276,
+ FBLTIN = 277,
+ FBLTINNOARGS = 278,
+ FBLTINONEARG = 279,
+ FBLTINARGLIST = 280,
+ RBLTIN = 281,
+ RBLTINONEARG = 282,
+ ID = 283,
+ STRING = 284,
+ HANDLER = 285,
+ SYMBOL = 286,
+ ENDCLAUSE = 287,
+ tPLAYACCEL = 288,
+ tDOWN = 289,
+ tELSE = 290,
+ tNLELSIF = 291,
+ tEXIT = 292,
+ tFRAME = 293,
+ tGLOBAL = 294,
+ tGO = 295,
+ tIF = 296,
+ tINTO = 297,
+ tLOOP = 298,
+ tMACRO = 299,
+ tMOVIE = 300,
+ tNEXT = 301,
+ tOF = 302,
+ tPREVIOUS = 303,
+ tPUT = 304,
+ tREPEAT = 305,
+ tSET = 306,
+ tTHEN = 307,
+ tTO = 308,
+ tWHEN = 309,
+ tWITH = 310,
+ tWHILE = 311,
+ tNLELSE = 312,
+ tFACTORY = 313,
+ tMETHOD = 314,
+ tOPEN = 315,
+ tPLAY = 316,
+ tDONE = 317,
+ tINSTANCE = 318,
+ tGE = 319,
+ tLE = 320,
+ tGT = 321,
+ tLT = 322,
+ tEQ = 323,
+ tNEQ = 324,
+ tAND = 325,
+ tOR = 326,
+ tNOT = 327,
+ tMOD = 328,
+ tAFTER = 329,
+ tBEFORE = 330,
+ tCONCAT = 331,
+ tCONTAINS = 332,
+ tSTARTS = 333,
+ tCHAR = 334,
+ tITEM = 335,
+ tLINE = 336,
+ tWORD = 337,
+ tSPRITE = 338,
+ tINTERSECTS = 339,
+ tWITHIN = 340,
+ tTELL = 341,
+ tPROPERTY = 342,
+ tON = 343,
+ tME = 344
};
#endif
/* Tokens. */
@@ -128,76 +137,85 @@
#define RECT 263
#define ARRAY 264
#define OBJECT 265
-#define INT 266
-#define THEENTITY 267
-#define THEENTITYWITHID 268
-#define FLOAT 269
-#define BLTIN 270
-#define BLTINNOARGS 271
-#define BLTINNOARGSORONE 272
-#define BLTINONEARG 273
-#define BLTINARGLIST 274
-#define TWOWORDBUILTIN 275
-#define ID 276
-#define STRING 277
-#define HANDLER 278
-#define SYMBOL 279
-#define ENDCLAUSE 280
-#define tPLAYACCEL 281
-#define tDOWN 282
-#define tELSE 283
-#define tNLELSIF 284
-#define tEXIT 285
-#define tFRAME 286
-#define tGLOBAL 287
-#define tGO 288
-#define tIF 289
-#define tINTO 290
-#define tLOOP 291
-#define tMACRO 292
-#define tMOVIE 293
-#define tNEXT 294
-#define tOF 295
-#define tPREVIOUS 296
-#define tPUT 297
-#define tREPEAT 298
-#define tSET 299
-#define tTHEN 300
-#define tTO 301
-#define tWHEN 302
-#define tWITH 303
-#define tWHILE 304
-#define tNLELSE 305
-#define tFACTORY 306
-#define tMETHOD 307
-#define tOPEN 308
-#define tPLAY 309
-#define tDONE 310
-#define tINSTANCE 311
-#define tGE 312
-#define tLE 313
-#define tGT 314
-#define tLT 315
-#define tEQ 316
-#define tNEQ 317
-#define tAND 318
-#define tOR 319
-#define tNOT 320
-#define tMOD 321
-#define tAFTER 322
-#define tBEFORE 323
-#define tCONCAT 324
-#define tCONTAINS 325
-#define tSTARTS 326
-#define tCHAR 327
-#define tITEM 328
-#define tLINE 329
-#define tWORD 330
-#define tSPRITE 331
-#define tINTERSECTS 332
-#define tWITHIN 333
-#define tON 334
-#define tME 335
+#define REFERENCE 266
+#define INT 267
+#define THEENTITY 268
+#define THEENTITYWITHID 269
+#define FLOAT 270
+#define BLTIN 271
+#define BLTINNOARGS 272
+#define BLTINNOARGSORONE 273
+#define BLTINONEARG 274
+#define BLTINARGLIST 275
+#define TWOWORDBUILTIN 276
+#define FBLTIN 277
+#define FBLTINNOARGS 278
+#define FBLTINONEARG 279
+#define FBLTINARGLIST 280
+#define RBLTIN 281
+#define RBLTINONEARG 282
+#define ID 283
+#define STRING 284
+#define HANDLER 285
+#define SYMBOL 286
+#define ENDCLAUSE 287
+#define tPLAYACCEL 288
+#define tDOWN 289
+#define tELSE 290
+#define tNLELSIF 291
+#define tEXIT 292
+#define tFRAME 293
+#define tGLOBAL 294
+#define tGO 295
+#define tIF 296
+#define tINTO 297
+#define tLOOP 298
+#define tMACRO 299
+#define tMOVIE 300
+#define tNEXT 301
+#define tOF 302
+#define tPREVIOUS 303
+#define tPUT 304
+#define tREPEAT 305
+#define tSET 306
+#define tTHEN 307
+#define tTO 308
+#define tWHEN 309
+#define tWITH 310
+#define tWHILE 311
+#define tNLELSE 312
+#define tFACTORY 313
+#define tMETHOD 314
+#define tOPEN 315
+#define tPLAY 316
+#define tDONE 317
+#define tINSTANCE 318
+#define tGE 319
+#define tLE 320
+#define tGT 321
+#define tLT 322
+#define tEQ 323
+#define tNEQ 324
+#define tAND 325
+#define tOR 326
+#define tNOT 327
+#define tMOD 328
+#define tAFTER 329
+#define tBEFORE 330
+#define tCONCAT 331
+#define tCONTAINS 332
+#define tSTARTS 333
+#define tCHAR 334
+#define tITEM 335
+#define tLINE 336
+#define tWORD 337
+#define tSPRITE 338
+#define tINTERSECTS 339
+#define tWITHIN 340
+#define tTELL 341
+#define tPROPERTY 342
+#define tON 343
+#define tME 344
@@ -215,7 +233,7 @@ typedef union YYSTYPE
Common::Array<double> *arr;
}
/* Line 1529 of yacc.c. */
-#line 219 "engines/director/lingo/lingo-gr.hpp"
+#line 237 "engines/director/lingo/lingo-gr.hpp"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index 2f693603f1..35290c67eb 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -87,11 +87,12 @@ void checkEnd(Common::String *token, const char *expect, bool required) {
}
%token UNARY
-%token CASTREF VOID VAR POINT RECT ARRAY OBJECT
+%token CASTREF VOID VAR POINT RECT ARRAY OBJECT REFERENCE
%token<i> INT
%token<e> THEENTITY THEENTITYWITHID
%token<f> FLOAT
%token<s> BLTIN BLTINNOARGS BLTINNOARGSORONE BLTINONEARG BLTINARGLIST TWOWORDBUILTIN
+%token<s> FBLTIN FBLTINNOARGS FBLTINONEARG FBLTINARGLIST RBLTIN RBLTINONEARG
%token<s> ID STRING HANDLER SYMBOL
%token<s> ENDCLAUSE tPLAYACCEL
%token tDOWN tELSE tNLELSIF tEXIT tFRAME tGLOBAL tGO tIF tINTO tLOOP tMACRO
@@ -99,10 +100,10 @@ void checkEnd(Common::String *token, const char *expect, bool required) {
%token tWITH tWHILE tNLELSE tFACTORY tMETHOD tOPEN tPLAY tDONE tINSTANCE
%token tGE tLE tGT tLT tEQ tNEQ tAND tOR tNOT tMOD
%token tAFTER tBEFORE tCONCAT tCONTAINS tSTARTS tCHAR tITEM tLINE tWORD
-%token tSPRITE tINTERSECTS tWITHIN
+%token tSPRITE tINTERSECTS tWITHIN tTELL tPROPERTY
%token tON tME
-%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist
+%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist tell
%type<narg> argdef arglist nonemptyarglist
%right '='
@@ -136,6 +137,9 @@ asgn: tPUT expr tINTO ID {
g_lingo->code1(g_lingo->c_assign);
$$ = $2;
delete $4; }
+ | tPUT expr tINTO reference {
+ g_lingo->code1(g_lingo->c_assign);
+ $$ = $2; }
| tPUT expr tAFTER expr { $$ = g_lingo->code1(g_lingo->c_after); } // D3
| tPUT expr tBEFORE expr { $$ = g_lingo->code1(g_lingo->c_before); } // D3
| tSET ID '=' expr {
@@ -184,8 +188,8 @@ asgn: tPUT expr tINTO ID {
$$ = $5; }
;
-stmtoneliner: expr { g_lingo->code1(g_lingo->c_xpop); }
- | func
+stmtoneliner: expr
+ | proc
;
stmt: stmtoneliner
@@ -196,8 +200,8 @@ stmt: stmtoneliner
//
| repeatwhile '(' cond ')' stmtlist end ENDCLAUSE {
inst body = 0, end = 0;
- WRITE_UINT32(&body, $5);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&body, $5 - $1);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = body; /* body of loop */
(*g_lingo->_currentScript)[$1 + 2] = end; /* end, if cond fails */
@@ -209,10 +213,10 @@ stmt: stmtoneliner
//
| repeatwith '=' expr end tTO expr end stmtlist end ENDCLAUSE {
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, $3);
- WRITE_UINT32(&finish, $6);
- WRITE_UINT32(&body, $8);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&init, $3 - $1);
+ WRITE_UINT32(&finish, $6 - $1);
+ WRITE_UINT32(&body, $8 - $1);
+ WRITE_UINT32(&end, $9 - $1);
WRITE_UINT32(&inc, 1);
(*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */
@@ -227,10 +231,10 @@ stmt: stmtoneliner
//
| repeatwith '=' expr end tDOWN tTO expr end stmtlist end ENDCLAUSE {
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, $3);
- WRITE_UINT32(&finish, $7);
- WRITE_UINT32(&body, $9);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&init, $3 - $1);
+ WRITE_UINT32(&finish, $7 - $1);
+ WRITE_UINT32(&body, $9 - $1);
+ WRITE_UINT32(&end, $10 - $1);
WRITE_UINT32(&inc, -1);
(*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */
@@ -239,18 +243,24 @@ stmt: stmtoneliner
(*g_lingo->_currentScript)[$1 + 5] = end; /* end, if cond fails */
checkEnd($11, "repeat", true); }
- | when expr end {
+ | when stmtoneliner end {
inst end = 0;
- WRITE_UINT32(&end, $3);
+ WRITE_UINT32(&end, $3 - $1);
g_lingo->code1(STOP);
(*g_lingo->_currentScript)[$1 + 1] = end;
}
+ | tell expr nl stmtlist end ENDCLAUSE {
+ warning("STUB: TELL is not implemented");
+ checkEnd($6, "tell", true); }
+ | tell expr tTO expr {
+ warning("STUB: TELL is not implemented");
+ }
;
ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
inst then = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -259,9 +269,9 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN nl stmtlist end tNLELSE stmtlist end ENDCLAUSE {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&else1, $8);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&else1, $8 - $1);
+ WRITE_UINT32(&end, $9 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -271,21 +281,21 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN nl stmtlist end begin elseifstmt end ENDCLAUSE {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&else1, $7);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&else1, $7 - $1);
+ WRITE_UINT32(&end, $9 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
checkEnd($10, "if", true);
- g_lingo->processIf(0, $9); }
+ g_lingo->processIf(0, $9 - $1); }
| if cond tTHEN begin stmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
+ WRITE_UINT32(&then, $4 - $1);
WRITE_UINT32(&else1, 0);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -293,9 +303,9 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN begin stmtoneliner end tNLELSE begin stmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
- WRITE_UINT32(&else1, $8);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&then, $4 - $1);
+ WRITE_UINT32(&else1, $8 - $1);
+ WRITE_UINT32(&end, $10 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -303,14 +313,14 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN begin stmtoneliner end elseifstmtoneliner end elsestmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
- WRITE_UINT32(&else1, $6);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&then, $4 - $1);
+ WRITE_UINT32(&else1, $6 - $1);
+ WRITE_UINT32(&end, $10 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
- g_lingo->processIf(0, $10); }
+ g_lingo->processIf(0, $10 - $1); }
;
elsestmtoneliner: /* nothing */ { $$ = 0; }
@@ -327,7 +337,7 @@ elseifstmtoneliner: elseifstmtoneliner elseifstmtoneliner1
elseifstmtoneliner1: elseif cond tTHEN begin stmt end {
inst then = 0;
- WRITE_UINT32(&then, $4);
+ WRITE_UINT32(&then, $4 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
g_lingo->codeLabel($1); }
@@ -336,7 +346,7 @@ elseifstmtoneliner1: elseif cond tTHEN begin stmt end {
elseifstmt1: elseifstmtoneliner
| elseif cond tTHEN begin stmtlist end {
inst then = 0;
- WRITE_UINT32(&then, $5);
+ WRITE_UINT32(&then, $5 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
g_lingo->codeLabel($1); }
@@ -389,6 +399,10 @@ when: tWHEN ID tTHEN {
g_lingo->codeString($2->c_str());
delete $2; }
+tell: tTELL {
+ $$ = g_lingo->code1(g_lingo->c_tellcode);
+ g_lingo->code1(STOP); }
+
expr: INT { $$ = g_lingo->codeConst($1); }
| FLOAT {
$$ = g_lingo->code1(g_lingo->c_fconstpush);
@@ -399,9 +413,14 @@ expr: INT { $$ = g_lingo->codeConst($1); }
| STRING {
$$ = g_lingo->code1(g_lingo->c_stringpush);
g_lingo->codeString($1->c_str()); }
- | BLTINNOARGS {
- $$ = g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
+ | FBLTINNOARGS {
+ g_lingo->codeFunc($1, 0);
delete $1; }
+ | FBLTINONEARG expr {
+ g_lingo->codeFunc($1, 1);
+ delete $1; }
+ | FBLTINARGLIST nonemptyarglist { g_lingo->codeFunc($1, $2); }
+ | FBLTINARGLIST '(' nonemptyarglist ')' { g_lingo->codeFunc($1, $3); }
| ID '(' arglist ')' {
$$ = g_lingo->codeFunc($1, $3);
delete $1; }
@@ -456,25 +475,34 @@ expr: INT { $$ = g_lingo->codeConst($1); }
| tWORD expr tTO expr tOF expr { g_lingo->code1(g_lingo->c_wordToOf); }
;
-func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
+reference: RBLTINONEARG expr {
+ g_lingo->codeFunc($1, 1);
+ delete $1; }
+ ;
+
+proc: tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
| gotofunc
| playfunc
| tEXIT tREPEAT { g_lingo->code1(g_lingo->c_exitRepeat); }
- | tEXIT { g_lingo->codeConst(0); // Push fake value on stack
- g_lingo->code1(g_lingo->c_procret); }
+ | tEXIT { g_lingo->code1(g_lingo->c_procret); }
| tGLOBAL globallist
+ | tPROPERTY propertylist
| tINSTANCE instancelist
+ | BLTINNOARGS {
+ g_lingo->codeFunc($1, 0);
+ delete $1; }
| BLTINONEARG expr {
- g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
+ g_lingo->codeFunc($1, 1);
delete $1; }
| BLTINNOARGSORONE expr {
- g_lingo->code1(g_lingo->_builtins[*$1]->u.func);
+ g_lingo->codeFunc($1, 1);
delete $1; }
| BLTINNOARGSORONE {
- g_lingo->code2(g_lingo->c_voidpush, g_lingo->_builtins[*$1]->u.func);
+ g_lingo->code1(g_lingo->c_voidpush);
+ g_lingo->codeFunc($1, 1);
delete $1; }
- | BLTINARGLIST '(' arglist ')' { g_lingo->codeFunc($1, $3); }
- | BLTINARGLIST arglist { g_lingo->codeFunc($1, $2); }
+ | BLTINARGLIST nonemptyarglist { g_lingo->codeFunc($1, $2); }
+ | BLTINARGLIST '(' nonemptyarglist ')' { g_lingo->codeFunc($1, $3); }
| tME '(' ID ')' { g_lingo->codeMe($3, 0); }
| tME '(' ID ',' arglist ')' { g_lingo->codeMe($3, $5); }
| tOPEN expr tWITH expr { g_lingo->code1(g_lingo->c_open); }
@@ -482,8 +510,12 @@ func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
| TWOWORDBUILTIN ID arglist { Common::String s(*$1); s += '-'; s += *$2; g_lingo->codeFunc(&s, $3); }
;
-globallist: ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($1->c_str()); delete $1; }
- | globallist ',' ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($3->c_str()); delete $3; }
+globallist: ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($1->c_str()); delete $1; }
+ | globallist ',' ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($3->c_str()); delete $3; }
+ ;
+
+propertylist: ID { g_lingo->code1(g_lingo->c_property); g_lingo->codeString($1->c_str()); delete $1; }
+ | propertylist ',' ID { g_lingo->code1(g_lingo->c_property); g_lingo->codeString($3->c_str()); delete $3; }
;
instancelist: ID { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString($1->c_str()); delete $1; }
@@ -562,7 +594,6 @@ playfunc: tPLAY tDONE { g_lingo->code1(g_lingo->c_playdone); }
// on keyword
defn: tMACRO ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); }
begin argdef nl argstore stmtlist {
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*$2, $4, $5);
g_lingo->_indef = false; }
@@ -576,7 +607,6 @@ defn: tMACRO ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); }
g_lingo->_indef = false; } ;
| tON ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); } // D3
begin { g_lingo->_ignoreMe = true; } argdef nl argstore stmtlist ENDCLAUSE {
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*$2, $4, $6);
g_lingo->_indef = false;
@@ -608,8 +638,8 @@ arglist: /* nothing */ { $$ = 0; }
| arglist ',' expr { $$ = $1 + 1; }
;
-nonemptyarglist: expr { $$ = 1; }
- | arglist ',' expr { $$ = $1 + 1; }
+nonemptyarglist: expr { $$ = 1; }
+ | nonemptyarglist ',' expr { $$ = $1 + 1; }
;
%%
diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp
index fb6c4a21e5..c931dc8a56 100644
--- a/engines/director/lingo/lingo-lex.cpp
+++ b/engines/director/lingo/lingo-lex.cpp
@@ -364,8 +364,8 @@ static void yy_fatal_error (yyconst char msg[] );
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 69
-#define YY_END_OF_BUFFER 70
+#define YY_NUM_RULES 73
+#define YY_END_OF_BUFFER 74
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -373,36 +373,38 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[253] =
+static yyconst flex_int16_t yy_accept[273] =
{ 0,
- 0, 0, 70, 68, 3, 66, 66, 68, 68, 68,
- 65, 65, 65, 64, 65, 65, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 2, 2, 3, 66, 0, 0,
- 0, 0, 0, 67, 4, 61, 1, 63, 64, 60,
- 58, 59, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 22, 12, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 35, 36, 62, 38,
- 62, 62, 62, 62, 62, 62, 62, 62, 51, 62,
- 62, 62, 2, 2, 0, 4, 1, 63, 62, 6,
-
- 62, 62, 62, 62, 62, 62, 16, 62, 62, 62,
- 62, 0, 62, 62, 62, 62, 62, 62, 62, 31,
- 62, 62, 34, 62, 62, 62, 42, 62, 44, 62,
- 62, 62, 62, 62, 62, 62, 0, 62, 62, 8,
- 62, 10, 11, 15, 0, 16, 18, 62, 62, 62,
- 0, 62, 62, 25, 26, 27, 28, 62, 62, 62,
- 33, 37, 39, 62, 62, 62, 62, 0, 50, 55,
- 62, 53, 57, 14, 5, 62, 62, 16, 16, 62,
- 19, 62, 21, 62, 62, 29, 62, 32, 62, 62,
- 62, 62, 62, 49, 49, 56, 62, 0, 7, 62,
-
- 16, 62, 20, 62, 62, 30, 62, 62, 43, 52,
- 45, 0, 0, 49, 54, 0, 62, 17, 62, 62,
- 62, 62, 0, 0, 0, 0, 49, 13, 9, 23,
- 62, 62, 41, 0, 0, 0, 49, 62, 40, 0,
- 0, 0, 0, 24, 48, 47, 48, 0, 0, 0,
- 46, 0
+ 0, 0, 74, 72, 4, 70, 70, 72, 72, 72,
+ 69, 69, 69, 68, 69, 69, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 72, 3, 3, 4, 70, 0,
+ 0, 0, 0, 0, 71, 5, 65, 2, 67, 68,
+ 64, 62, 63, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 23, 13, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 36, 37, 66,
+ 39, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 55, 66, 66, 66, 1, 3, 3, 0, 5, 2,
+
+ 67, 66, 7, 66, 66, 66, 66, 66, 66, 17,
+ 66, 66, 66, 66, 0, 66, 66, 66, 66, 66,
+ 66, 66, 32, 66, 66, 35, 66, 66, 66, 66,
+ 44, 66, 46, 66, 66, 66, 66, 66, 66, 66,
+ 66, 0, 66, 66, 9, 66, 11, 12, 16, 0,
+ 17, 19, 66, 66, 66, 0, 66, 66, 26, 27,
+ 28, 29, 66, 66, 66, 34, 38, 40, 66, 66,
+ 66, 66, 66, 48, 0, 54, 59, 66, 57, 61,
+ 15, 6, 66, 66, 17, 17, 66, 20, 66, 22,
+ 66, 66, 30, 66, 33, 66, 66, 66, 66, 66,
+
+ 66, 53, 53, 53, 60, 66, 0, 8, 66, 17,
+ 66, 21, 66, 66, 31, 66, 66, 66, 45, 56,
+ 47, 0, 0, 53, 53, 58, 0, 66, 18, 66,
+ 66, 66, 66, 66, 0, 0, 0, 0, 53, 53,
+ 14, 10, 24, 66, 66, 42, 43, 0, 0, 0,
+ 53, 53, 66, 41, 0, 0, 0, 0, 0, 25,
+ 52, 51, 52, 0, 0, 0, 0, 0, 0, 49,
+ 50, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -427,7 +429,7 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 65, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -437,7 +439,7 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[65] =
+static yyconst flex_int32_t yy_meta[66] =
{ 0,
1, 2, 3, 3, 2, 1, 1, 1, 1, 1,
1, 1, 4, 1, 1, 1, 5, 5, 5, 5,
@@ -445,76 +447,80 @@ static yyconst flex_int32_t yy_meta[65] =
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5
+ 5, 5, 5, 5, 1
} ;
-static yyconst flex_int16_t yy_base[264] =
+static yyconst flex_int16_t yy_base[284] =
{ 0,
- 0, 63, 160, 645, 67, 71, 75, 79, 140, 0,
- 645, 133, 126, 54, 70, 94, 65, 67, 65, 61,
- 71, 87, 72, 0, 103, 81, 119, 109, 135, 118,
- 82, 112, 146, 155, 194, 208, 212, 645, 216, 181,
- 220, 121, 99, 645, 0, 645, 0, 88, 95, 645,
- 645, 645, 0, 118, 96, 105, 142, 177, 197, 173,
- 183, 183, 210, 215, 204, 88, 0, 202, 217, 211,
- 213, 225, 211, 228, 208, 216, 0, 0, 228, 0,
- 235, 232, 220, 225, 227, 235, 255, 255, 0, 260,
- 248, 251, 291, 300, 253, 0, 0, 84, 267, 0,
-
- 260, 258, 263, 278, 280, 279, 314, 277, 282, 290,
- 302, 321, 293, 300, 301, 311, 300, 301, 311, 0,
- 312, 304, 0, 311, 303, 307, 0, 326, 0, 323,
- 317, 364, 322, 332, 337, 345, 349, 343, 344, 0,
- 354, 0, 0, 0, 189, 0, 0, 348, 358, 364,
- 354, 365, 352, 0, 0, 0, 0, 357, 358, 368,
- 0, 0, 374, 369, 380, 364, 368, 408, 0, 0,
- 384, 390, 0, 237, 0, 397, 395, 0, 0, 391,
- 0, 398, 645, 397, 394, 0, 401, 0, 410, 401,
- 397, 412, 401, 434, 455, 0, 408, 465, 0, 409,
-
- 0, 407, 0, 432, 432, 0, 444, 432, 0, 0,
- 0, 475, 444, 481, 0, 447, 438, 0, 452, 455,
- 454, 448, 479, 476, 475, 476, 502, 645, 0, 0,
- 473, 489, 0, 482, 519, 491, 525, 489, 0, 504,
- 526, 518, 540, 0, 645, 544, 645, 546, 522, 550,
- 551, 645, 600, 602, 605, 608, 614, 619, 624, 627,
- 632, 634, 639
+ 0, 64, 160, 702, 68, 72, 76, 80, 148, 0,
+ 702, 129, 106, 55, 71, 95, 66, 68, 66, 62,
+ 72, 88, 73, 0, 104, 82, 120, 110, 136, 119,
+ 83, 113, 154, 156, 105, 192, 209, 213, 702, 217,
+ 180, 225, 120, 100, 702, 0, 702, 0, 89, 130,
+ 702, 702, 702, 0, 114, 108, 155, 181, 178, 195,
+ 191, 189, 210, 217, 220, 202, 89, 0, 205, 220,
+ 214, 214, 226, 215, 232, 212, 219, 0, 0, 226,
+ 0, 238, 252, 224, 234, 241, 246, 267, 254, 264,
+ 0, 265, 253, 259, 702, 292, 315, 265, 0, 0,
+
+ 85, 280, 0, 274, 274, 273, 281, 284, 293, 320,
+ 286, 289, 301, 312, 333, 299, 319, 308, 320, 312,
+ 313, 320, 0, 322, 315, 0, 322, 312, 317, 325,
+ 0, 336, 0, 334, 328, 335, 385, 335, 344, 353,
+ 359, 360, 350, 356, 0, 374, 0, 0, 0, 185,
+ 0, 0, 363, 373, 379, 368, 382, 368, 0, 0,
+ 0, 0, 373, 375, 387, 0, 0, 392, 385, 390,
+ 395, 380, 383, 0, 418, 0, 0, 405, 403, 0,
+ 395, 0, 409, 406, 0, 0, 407, 0, 414, 702,
+ 414, 410, 0, 412, 0, 427, 418, 416, 415, 433,
+
+ 424, 473, 475, 479, 0, 433, 488, 0, 434, 0,
+ 430, 0, 447, 474, 0, 477, 452, 463, 0, 0,
+ 0, 495, 483, 497, 499, 0, 486, 471, 0, 493,
+ 497, 498, 476, 483, 522, 509, 514, 512, 543, 555,
+ 702, 0, 0, 508, 519, 0, 0, 515, 561, 530,
+ 567, 578, 534, 0, 538, 584, 550, 589, 593, 0,
+ 702, 595, 702, 599, 559, 603, 563, 610, 615, 616,
+ 620, 702, 657, 659, 662, 665, 671, 676, 681, 684,
+ 689, 691, 696
} ;
-static yyconst flex_int16_t yy_def[264] =
+static yyconst flex_int16_t yy_def[284] =
{ 0,
- 252, 1, 252, 252, 252, 252, 252, 252, 253, 254,
- 252, 252, 252, 252, 252, 252, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 252, 252, 252, 252, 252, 252,
- 252, 252, 253, 252, 256, 252, 257, 252, 252, 252,
- 252, 252, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 252, 252, 252, 256, 257, 252, 255, 255,
-
- 255, 255, 255, 255, 255, 255, 258, 255, 255, 255,
- 255, 252, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 252, 255, 255, 255,
- 255, 255, 255, 255, 259, 260, 255, 255, 255, 255,
- 252, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 261, 255, 255,
- 255, 255, 255, 252, 255, 255, 255, 262, 260, 255,
- 255, 255, 252, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 261, 261, 255, 255, 252, 255, 255,
-
- 262, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 252, 252, 261, 255, 252, 255, 255, 255, 255,
- 255, 255, 252, 252, 252, 252, 261, 252, 255, 255,
- 255, 255, 255, 252, 252, 252, 261, 255, 255, 252,
- 263, 252, 252, 255, 252, 263, 252, 252, 252, 252,
- 263, 0, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252
+ 272, 1, 272, 272, 272, 272, 272, 272, 273, 274,
+ 272, 272, 272, 272, 272, 272, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 273, 272, 276, 272, 277, 272, 272,
+ 272, 272, 272, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 272, 272, 272, 272, 276, 277,
+
+ 272, 275, 275, 275, 275, 275, 275, 275, 275, 278,
+ 275, 275, 275, 275, 272, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 272, 275, 275, 275, 275, 275, 275, 275, 279,
+ 280, 275, 275, 275, 275, 272, 275, 275, 275, 275,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 275, 275, 275, 281, 275, 275, 275, 275, 275,
+ 272, 275, 275, 275, 282, 280, 275, 275, 275, 272,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+
+ 275, 281, 281, 281, 275, 275, 272, 275, 275, 282,
+ 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 272, 272, 281, 281, 275, 272, 275, 275, 275,
+ 275, 275, 275, 275, 272, 272, 272, 272, 281, 281,
+ 272, 275, 275, 275, 275, 275, 275, 272, 272, 272,
+ 281, 281, 275, 275, 272, 283, 272, 272, 272, 275,
+ 272, 283, 272, 272, 272, 272, 272, 272, 272, 283,
+ 283, 0, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272
} ;
-static yyconst flex_int16_t yy_nxt[710] =
+static yyconst flex_int16_t yy_nxt[768] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 11,
13, 4, 14, 15, 11, 16, 17, 18, 19, 20,
@@ -522,81 +528,87 @@ static yyconst flex_int16_t yy_nxt[710] =
30, 24, 31, 32, 33, 24, 24, 34, 24, 24,
24, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 24, 31, 32, 33, 24,
- 24, 34, 24, 24, 35, 48, 49, 36, 37, 38,
- 38, 39, 40, 41, 41, 40, 40, 41, 41, 40,
- 39, 38, 38, 39, 50, 51, 54, 56, 57, 112,
- 59, 42, 112, 55, 58, 42, 98, 60, 65, 61,
-
- 98, 66, 84, 63, 44, 70, 48, 49, 52, 62,
- 71, 54, 56, 57, 59, 100, 42, 55, 58, 64,
- 42, 60, 65, 61, 67, 66, 101, 84, 63, 75,
- 70, 68, 85, 62, 71, 72, 47, 69, 76, 73,
- 100, 46, 86, 64, 81, 44, 87, 95, 74, 67,
- 82, 101, 99, 83, 75, 68, 77, 85, 102, 252,
- 72, 69, 76, 78, 73, 79, 86, 80, 81, 88,
- 87, 95, 74, 252, 82, 89, 99, 83, 90, 91,
- 252, 77, 40, 102, 92, 40, 252, 78, 252, 79,
- 145, 80, 252, 145, 88, 93, 38, 38, 94, 89,
-
- 252, 42, 107, 90, 91, 103, 106, 108, 92, 94,
- 38, 38, 94, 37, 38, 38, 39, 39, 38, 38,
- 39, 40, 41, 41, 40, 104, 42, 107, 109, 103,
- 106, 110, 108, 111, 105, 113, 114, 115, 198, 116,
- 42, 198, 117, 118, 252, 119, 122, 120, 124, 104,
- 123, 125, 126, 109, 127, 128, 110, 111, 105, 113,
- 114, 129, 115, 116, 121, 42, 117, 130, 118, 119,
- 122, 131, 120, 124, 123, 132, 125, 126, 127, 128,
- 133, 252, 135, 136, 134, 129, 137, 138, 121, 139,
- 140, 130, 93, 38, 38, 94, 131, 141, 142, 144,
-
- 132, 94, 38, 38, 94, 133, 135, 136, 143, 134,
- 137, 147, 138, 139, 140, 145, 148, 149, 145, 150,
- 153, 141, 112, 142, 144, 112, 53, 152, 155, 154,
- 157, 156, 143, 158, 159, 147, 160, 252, 161, 162,
- 148, 149, 163, 164, 150, 153, 165, 166, 252, 167,
- 170, 152, 155, 154, 157, 151, 156, 158, 171, 159,
- 172, 160, 161, 162, 173, 168, 163, 164, 168, 174,
- 177, 165, 166, 167, 170, 175, 176, 180, 181, 151,
- 182, 184, 171, 183, 185, 172, 186, 187, 188, 173,
- 189, 252, 169, 190, 174, 177, 191, 252, 192, 175,
-
- 176, 180, 193, 181, 196, 182, 184, 183, 185, 168,
- 186, 187, 168, 188, 197, 189, 169, 199, 190, 200,
- 206, 191, 192, 202, 203, 204, 193, 205, 207, 196,
- 208, 209, 210, 252, 211, 212, 215, 217, 212, 197,
- 252, 195, 199, 213, 200, 206, 218, 202, 203, 204,
- 219, 205, 220, 207, 208, 209, 212, 210, 211, 212,
- 215, 217, 221, 224, 213, 195, 198, 222, 228, 198,
- 218, 229, 230, 231, 232, 219, 223, 220, 226, 223,
- 223, 233, 212, 223, 252, 212, 214, 221, 224, 216,
- 213, 222, 234, 228, 224, 229, 235, 230, 231, 232,
-
- 236, 252, 226, 212, 225, 233, 212, 238, 225, 226,
- 214, 213, 252, 227, 216, 239, 240, 234, 242, 224,
- 241, 235, 244, 241, 245, 236, 243, 241, 225, 243,
- 241, 238, 225, 226, 213, 252, 237, 227, 247, 239,
- 240, 248, 242, 250, 248, 252, 244, 248, 252, 245,
- 248, 251, 251, 252, 251, 251, 252, 252, 252, 224,
- 237, 252, 252, 247, 252, 252, 252, 252, 250, 249,
- 252, 252, 252, 252, 226, 249, 252, 252, 252, 252,
- 252, 252, 252, 252, 224, 252, 252, 252, 252, 252,
- 252, 252, 252, 249, 252, 252, 252, 252, 226, 249,
-
- 43, 43, 252, 43, 43, 43, 45, 45, 53, 53,
- 53, 96, 96, 96, 97, 97, 252, 97, 97, 97,
- 146, 252, 146, 146, 146, 178, 252, 252, 178, 178,
- 179, 179, 179, 194, 252, 252, 194, 201, 201, 201,
- 246, 252, 252, 246, 3, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-
- 252, 252, 252, 252, 252, 252, 252, 252, 252
+ 24, 34, 24, 24, 35, 36, 49, 50, 37, 38,
+ 39, 39, 40, 41, 42, 42, 41, 41, 42, 42,
+ 41, 40, 39, 39, 40, 51, 52, 55, 57, 58,
+ 115, 60, 43, 115, 56, 59, 43, 101, 61, 66,
+
+ 62, 101, 67, 85, 64, 45, 71, 95, 95, 53,
+ 63, 72, 55, 57, 58, 60, 48, 43, 56, 59,
+ 65, 43, 61, 66, 62, 68, 67, 103, 85, 64,
+ 76, 71, 69, 86, 63, 72, 73, 47, 70, 77,
+ 74, 49, 50, 87, 65, 82, 98, 88, 102, 75,
+ 68, 83, 103, 45, 84, 76, 69, 78, 86, 272,
+ 272, 73, 70, 77, 79, 74, 80, 87, 81, 82,
+ 98, 88, 102, 75, 89, 83, 104, 90, 84, 92,
+ 93, 41, 78, 91, 41, 94, 150, 272, 79, 150,
+ 80, 272, 81, 96, 39, 39, 97, 105, 272, 89,
+
+ 43, 104, 90, 272, 92, 93, 106, 91, 110, 94,
+ 97, 39, 39, 97, 38, 39, 39, 40, 40, 39,
+ 39, 40, 105, 107, 109, 43, 41, 42, 42, 41,
+ 106, 114, 108, 110, 111, 112, 113, 272, 116, 117,
+ 118, 272, 119, 120, 121, 43, 127, 107, 109, 122,
+ 125, 123, 272, 126, 128, 114, 108, 272, 131, 111,
+ 112, 113, 116, 117, 132, 118, 119, 120, 124, 121,
+ 43, 127, 129, 122, 125, 133, 123, 126, 134, 128,
+ 136, 130, 131, 135, 137, 138, 272, 140, 132, 139,
+ 272, 141, 124, 96, 39, 39, 97, 129, 142, 133,
+
+ 143, 147, 134, 144, 136, 130, 145, 146, 135, 137,
+ 138, 140, 148, 149, 139, 141, 97, 39, 39, 97,
+ 152, 150, 142, 153, 150, 143, 147, 144, 154, 155,
+ 145, 146, 54, 157, 115, 160, 148, 115, 149, 158,
+ 161, 272, 162, 164, 152, 163, 165, 153, 159, 166,
+ 167, 168, 154, 169, 155, 170, 171, 157, 172, 160,
+ 173, 174, 272, 177, 158, 161, 162, 156, 164, 163,
+ 178, 165, 159, 166, 167, 168, 179, 169, 180, 170,
+ 181, 171, 182, 172, 173, 174, 175, 177, 183, 175,
+ 184, 156, 187, 188, 178, 189, 207, 190, 191, 207,
+
+ 192, 179, 193, 180, 194, 181, 182, 195, 196, 197,
+ 198, 199, 183, 176, 200, 184, 187, 201, 188, 175,
+ 189, 190, 175, 191, 192, 205, 193, 206, 194, 208,
+ 209, 215, 195, 196, 197, 198, 199, 176, 200, 211,
+ 212, 201, 213, 214, 203, 216, 272, 217, 218, 219,
+ 205, 204, 206, 220, 208, 209, 215, 221, 272, 272,
+ 272, 226, 228, 211, 212, 230, 213, 214, 203, 229,
+ 216, 217, 218, 219, 222, 204, 222, 222, 220, 222,
+ 222, 221, 223, 222, 223, 226, 228, 233, 223, 207,
+ 230, 224, 207, 229, 231, 232, 235, 234, 222, 235,
+
+ 222, 222, 236, 222, 242, 272, 223, 241, 223, 246,
+ 225, 233, 227, 243, 236, 244, 224, 238, 245, 231,
+ 232, 234, 247, 235, 237, 248, 235, 236, 242, 238,
+ 239, 240, 241, 246, 225, 249, 250, 227, 243, 236,
+ 244, 238, 253, 245, 222, 254, 247, 222, 237, 255,
+ 248, 237, 223, 238, 239, 240, 222, 257, 261, 222,
+ 249, 250, 256, 272, 223, 256, 253, 260, 258, 254,
+ 263, 258, 272, 255, 272, 237, 223, 251, 272, 259,
+ 268, 257, 259, 261, 269, 256, 272, 223, 256, 252,
+ 264, 260, 272, 264, 266, 263, 272, 266, 272, 272,
+
+ 264, 251, 272, 264, 266, 268, 272, 266, 236, 269,
+ 272, 270, 236, 252, 270, 272, 271, 270, 265, 271,
+ 270, 271, 267, 238, 271, 272, 272, 238, 265, 272,
+ 272, 272, 267, 236, 272, 272, 272, 236, 272, 272,
+ 272, 272, 265, 272, 272, 272, 267, 238, 272, 272,
+ 272, 238, 265, 272, 272, 272, 267, 44, 44, 272,
+ 44, 44, 44, 46, 46, 54, 54, 54, 99, 99,
+ 99, 100, 100, 272, 100, 100, 100, 151, 272, 151,
+ 151, 151, 185, 272, 272, 185, 185, 186, 186, 186,
+ 202, 272, 272, 202, 210, 210, 210, 262, 272, 272,
+
+ 262, 3, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272
} ;
-static yyconst flex_int16_t yy_chk[710] =
+static yyconst flex_int16_t yy_chk[768] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -604,78 +616,84 @@ static yyconst flex_int16_t yy_chk[710] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 14, 14, 2, 5, 5,
- 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
- 8, 8, 8, 8, 15, 15, 17, 18, 19, 66,
- 20, 6, 66, 17, 19, 7, 98, 21, 23, 21,
-
- 48, 23, 31, 22, 43, 26, 49, 49, 16, 21,
- 26, 17, 18, 19, 20, 55, 6, 17, 19, 22,
- 7, 21, 23, 21, 25, 23, 56, 31, 22, 28,
- 26, 25, 32, 21, 26, 27, 13, 25, 28, 27,
- 55, 12, 32, 22, 30, 9, 32, 42, 27, 25,
- 30, 56, 54, 30, 28, 25, 29, 32, 57, 3,
- 27, 25, 28, 29, 27, 29, 32, 29, 30, 33,
- 32, 42, 27, 0, 30, 33, 54, 30, 34, 34,
- 0, 29, 40, 57, 34, 40, 0, 29, 0, 29,
- 145, 29, 0, 145, 33, 35, 35, 35, 35, 33,
-
- 0, 40, 61, 34, 34, 58, 60, 62, 34, 36,
- 36, 36, 36, 37, 37, 37, 37, 39, 39, 39,
- 39, 41, 41, 41, 41, 59, 40, 61, 63, 58,
- 60, 64, 62, 65, 59, 68, 68, 69, 174, 70,
- 41, 174, 71, 72, 0, 73, 75, 74, 79, 59,
- 76, 81, 82, 63, 83, 84, 64, 65, 59, 68,
- 68, 85, 69, 70, 74, 41, 71, 86, 72, 73,
- 75, 87, 74, 79, 76, 88, 81, 82, 83, 84,
- 90, 0, 91, 92, 90, 85, 95, 99, 74, 101,
- 102, 86, 93, 93, 93, 93, 87, 103, 104, 106,
-
- 88, 94, 94, 94, 94, 90, 91, 92, 105, 90,
- 95, 108, 99, 101, 102, 107, 109, 110, 107, 111,
- 114, 103, 112, 104, 106, 112, 107, 113, 115, 114,
- 117, 116, 105, 118, 119, 108, 121, 0, 122, 124,
- 109, 110, 125, 126, 111, 114, 128, 130, 0, 131,
- 133, 113, 115, 114, 117, 112, 116, 118, 134, 119,
- 135, 121, 122, 124, 136, 132, 125, 126, 132, 137,
- 141, 128, 130, 131, 133, 138, 139, 148, 149, 112,
- 150, 152, 134, 151, 153, 135, 158, 159, 160, 136,
- 163, 0, 132, 164, 137, 141, 165, 0, 166, 138,
-
- 139, 148, 167, 149, 171, 150, 152, 151, 153, 168,
- 158, 159, 168, 160, 172, 163, 132, 176, 164, 177,
- 187, 165, 166, 180, 182, 184, 167, 185, 189, 171,
- 190, 191, 192, 0, 193, 194, 197, 200, 194, 172,
- 0, 168, 176, 194, 177, 187, 202, 180, 182, 184,
- 204, 185, 205, 189, 190, 191, 195, 192, 193, 195,
- 197, 200, 207, 213, 195, 168, 198, 208, 216, 198,
- 202, 217, 219, 220, 221, 204, 212, 205, 213, 212,
- 223, 222, 214, 223, 0, 214, 195, 207, 213, 198,
- 214, 208, 224, 216, 212, 217, 225, 219, 220, 221,
-
- 226, 0, 213, 227, 212, 222, 227, 231, 223, 212,
- 195, 227, 0, 214, 198, 232, 234, 224, 236, 212,
- 235, 225, 238, 235, 240, 226, 237, 241, 212, 237,
- 241, 231, 223, 212, 237, 0, 227, 214, 242, 232,
- 234, 243, 236, 249, 243, 246, 238, 248, 246, 240,
- 248, 250, 251, 0, 250, 251, 0, 0, 0, 243,
- 227, 0, 0, 242, 0, 0, 0, 0, 249, 243,
- 0, 0, 0, 0, 243, 248, 0, 0, 0, 0,
- 0, 0, 0, 0, 243, 0, 0, 0, 0, 0,
- 0, 0, 0, 243, 0, 0, 0, 0, 243, 248,
-
- 253, 253, 0, 253, 253, 253, 254, 254, 255, 255,
- 255, 256, 256, 256, 257, 257, 0, 257, 257, 257,
- 258, 0, 258, 258, 258, 259, 0, 0, 259, 259,
- 260, 260, 260, 261, 0, 0, 261, 262, 262, 262,
- 263, 0, 0, 263, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-
- 252, 252, 252, 252, 252, 252, 252, 252, 252
+ 1, 1, 1, 1, 1, 2, 14, 14, 2, 5,
+ 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 15, 15, 17, 18, 19,
+ 67, 20, 6, 67, 17, 19, 7, 101, 21, 23,
+
+ 21, 49, 23, 31, 22, 44, 26, 35, 35, 16,
+ 21, 26, 17, 18, 19, 20, 13, 6, 17, 19,
+ 22, 7, 21, 23, 21, 25, 23, 56, 31, 22,
+ 28, 26, 25, 32, 21, 26, 27, 12, 25, 28,
+ 27, 50, 50, 32, 22, 30, 43, 32, 55, 27,
+ 25, 30, 56, 9, 30, 28, 25, 29, 32, 3,
+ 0, 27, 25, 28, 29, 27, 29, 32, 29, 30,
+ 43, 32, 55, 27, 33, 30, 57, 33, 30, 34,
+ 34, 41, 29, 33, 41, 34, 150, 0, 29, 150,
+ 29, 0, 29, 36, 36, 36, 36, 58, 0, 33,
+
+ 41, 57, 33, 0, 34, 34, 59, 33, 62, 34,
+ 37, 37, 37, 37, 38, 38, 38, 38, 40, 40,
+ 40, 40, 58, 60, 61, 41, 42, 42, 42, 42,
+ 59, 66, 60, 62, 63, 64, 65, 0, 69, 69,
+ 70, 0, 71, 72, 73, 42, 80, 60, 61, 74,
+ 76, 75, 0, 77, 82, 66, 60, 0, 84, 63,
+ 64, 65, 69, 69, 85, 70, 71, 72, 75, 73,
+ 42, 80, 83, 74, 76, 86, 75, 77, 87, 82,
+ 89, 83, 84, 88, 90, 92, 0, 93, 85, 92,
+ 0, 94, 75, 96, 96, 96, 96, 83, 98, 86,
+
+ 102, 107, 87, 104, 89, 83, 105, 106, 88, 90,
+ 92, 93, 108, 109, 92, 94, 97, 97, 97, 97,
+ 111, 110, 98, 112, 110, 102, 107, 104, 113, 114,
+ 105, 106, 110, 116, 115, 118, 108, 115, 109, 117,
+ 119, 0, 120, 122, 111, 121, 124, 112, 117, 125,
+ 127, 128, 113, 129, 114, 130, 132, 116, 134, 118,
+ 135, 136, 0, 138, 117, 119, 120, 115, 122, 121,
+ 139, 124, 117, 125, 127, 128, 140, 129, 141, 130,
+ 142, 132, 143, 134, 135, 136, 137, 138, 144, 137,
+ 146, 115, 153, 154, 139, 155, 181, 156, 157, 181,
+
+ 158, 140, 163, 141, 164, 142, 143, 165, 168, 169,
+ 170, 171, 144, 137, 172, 146, 153, 173, 154, 175,
+ 155, 156, 175, 157, 158, 178, 163, 179, 164, 183,
+ 184, 194, 165, 168, 169, 170, 171, 137, 172, 187,
+ 189, 173, 191, 192, 175, 196, 0, 197, 198, 199,
+ 178, 175, 179, 200, 183, 184, 194, 201, 0, 0,
+ 0, 206, 209, 187, 189, 213, 191, 192, 175, 211,
+ 196, 197, 198, 199, 202, 175, 203, 202, 200, 203,
+ 204, 201, 202, 204, 203, 206, 209, 217, 204, 207,
+ 213, 203, 207, 211, 214, 216, 222, 218, 224, 222,
+
+ 225, 224, 223, 225, 228, 0, 224, 227, 225, 233,
+ 204, 217, 207, 230, 222, 231, 203, 223, 232, 214,
+ 216, 218, 234, 235, 222, 236, 235, 223, 228, 222,
+ 224, 225, 227, 233, 204, 237, 238, 207, 230, 222,
+ 231, 223, 244, 232, 239, 245, 234, 239, 222, 248,
+ 236, 235, 239, 222, 224, 225, 240, 250, 255, 240,
+ 237, 238, 249, 0, 240, 249, 244, 253, 251, 245,
+ 257, 251, 0, 248, 0, 235, 251, 239, 0, 252,
+ 265, 250, 252, 255, 267, 256, 0, 252, 256, 240,
+ 258, 253, 0, 258, 259, 257, 262, 259, 0, 262,
+
+ 264, 239, 0, 264, 266, 265, 0, 266, 258, 267,
+ 0, 268, 259, 240, 268, 0, 269, 270, 258, 269,
+ 270, 271, 259, 258, 271, 0, 0, 259, 264, 0,
+ 0, 0, 266, 258, 0, 0, 0, 259, 0, 0,
+ 0, 0, 258, 0, 0, 0, 259, 258, 0, 0,
+ 0, 259, 264, 0, 0, 0, 266, 273, 273, 0,
+ 273, 273, 273, 274, 274, 275, 275, 275, 276, 276,
+ 276, 277, 277, 0, 277, 277, 277, 278, 0, 278,
+ 278, 278, 279, 0, 0, 279, 279, 280, 280, 280,
+ 281, 0, 0, 281, 282, 282, 282, 283, 0, 0,
+
+ 283, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ 272, 272, 272, 272, 272, 272, 272
} ;
static yy_state_type yy_last_accepting_state;
@@ -728,6 +746,9 @@ using namespace Director;
int yyparse();
static void count() {
+ if (debugChannelSet(-1, kDebugLingoParse))
+ debug("LEXER: Read '%s' at %d:%d", yytext, g_lingo->_linenumber, g_lingo->_colnumber);
+
g_lingo->_colnumber += strlen(yytext);
}
@@ -760,7 +781,7 @@ static int checkImmediate(int token) {
return token;
}
-#line 764 "engines/director/lingo/lingo-lex.cpp"
+#line 785 "engines/director/lingo/lingo-lex.cpp"
#define INITIAL 0
@@ -943,10 +964,10 @@ YY_DECL
register char *yy_cp, *yy_bp;
register int yy_act;
-#line 82 "engines/director/lingo/lingo-lex.l"
+#line 85 "engines/director/lingo/lingo-lex.l"
-#line 950 "engines/director/lingo/lingo-lex.cpp"
+#line 971 "engines/director/lingo/lingo-lex.cpp"
if ( !(yy_init) )
{
@@ -1000,13 +1021,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 253 )
+ if ( yy_current_state >= 273 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 645 );
+ while ( yy_base[yy_current_state] != 702 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1031,85 +1052,91 @@ do_action: /* This label is used only to access EOF actions. */
goto yy_find_action;
case 1:
+/* rule 1 can match eol */
YY_RULE_SETUP
-#line 84 "engines/director/lingo/lingo-lex.l"
-
+#line 87 "engines/director/lingo/lingo-lex.l"
+{ g_lingo->_linenumber++; g_lingo->_colnumber = 0; }
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 85 "engines/director/lingo/lingo-lex.l"
-{ count(); }
+#line 88 "engines/director/lingo/lingo-lex.l"
+
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 86 "engines/director/lingo/lingo-lex.l"
-{ count(); return ' '; }
+#line 89 "engines/director/lingo/lingo-lex.l"
+{ count(); }
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 88 "engines/director/lingo/lingo-lex.l"
-{ count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3
+#line 90 "engines/director/lingo/lingo-lex.l"
+{ count(); return ' '; }
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 90 "engines/director/lingo/lingo-lex.l"
-{ count(); return tAFTER; } // D3
+#line 92 "engines/director/lingo/lingo-lex.l"
+{ count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 91 "engines/director/lingo/lingo-lex.l"
-{ count(); return tAND; }
+#line 94 "engines/director/lingo/lingo-lex.l"
+{ count(); return tAFTER; } // D3
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 92 "engines/director/lingo/lingo-lex.l"
-{ count(); return tBEFORE; } // D3
+#line 95 "engines/director/lingo/lingo-lex.l"
+{ count(); return tAND; }
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 93 "engines/director/lingo/lingo-lex.l"
-{ count(); return tCHAR; } // D3
+#line 96 "engines/director/lingo/lingo-lex.l"
+{ count(); return tBEFORE; } // D3
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 94 "engines/director/lingo/lingo-lex.l"
-{ count(); return tCONTAINS; }
+#line 97 "engines/director/lingo/lingo-lex.l"
+{ count(); return tCHAR; } // D3
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 95 "engines/director/lingo/lingo-lex.l"
-{ count(); return tDONE; }
+#line 98 "engines/director/lingo/lingo-lex.l"
+{ count(); return tCONTAINS; }
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 96 "engines/director/lingo/lingo-lex.l"
-{ count(); return tDOWN; }
+#line 99 "engines/director/lingo/lingo-lex.l"
+{ count(); return tDONE; }
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 97 "engines/director/lingo/lingo-lex.l"
-{ count(); return tIF; }
+#line 100 "engines/director/lingo/lingo-lex.l"
+{ count(); return tDOWN; }
YY_BREAK
case 13:
-/* rule 13 can match eol */
YY_RULE_SETUP
-#line 98 "engines/director/lingo/lingo-lex.l"
-{ countnl(); return tNLELSIF; }
+#line 101 "engines/director/lingo/lingo-lex.l"
+{ count(); return tIF; }
YY_BREAK
case 14:
/* rule 14 can match eol */
YY_RULE_SETUP
-#line 99 "engines/director/lingo/lingo-lex.l"
-{ countnl(); return tNLELSE; }
+#line 102 "engines/director/lingo/lingo-lex.l"
+{ countnl(); return tNLELSIF; }
YY_BREAK
case 15:
+/* rule 15 can match eol */
YY_RULE_SETUP
-#line 100 "engines/director/lingo/lingo-lex.l"
-{ count(); return tELSE; }
+#line 103 "engines/director/lingo/lingo-lex.l"
+{ countnl(); return tNLELSE; }
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 101 "engines/director/lingo/lingo-lex.l"
+#line 104 "engines/director/lingo/lingo-lex.l"
+{ count(); return tELSE; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 105 "engines/director/lingo/lingo-lex.l"
{
count();
@@ -1122,154 +1149,176 @@ YY_RULE_SETUP
return ENDCLAUSE;
}
YY_BREAK
-case 17:
+case 18:
YY_RULE_SETUP
-#line 112 "engines/director/lingo/lingo-lex.l"
+#line 116 "engines/director/lingo/lingo-lex.l"
{ count(); return tFACTORY; }
YY_BREAK
-case 18:
+case 19:
YY_RULE_SETUP
-#line 113 "engines/director/lingo/lingo-lex.l"
+#line 117 "engines/director/lingo/lingo-lex.l"
{ count(); return tEXIT; }
YY_BREAK
-case 19:
+case 20:
YY_RULE_SETUP
-#line 114 "engines/director/lingo/lingo-lex.l"
+#line 118 "engines/director/lingo/lingo-lex.l"
{ count(); return tFRAME; }
YY_BREAK
-case 20:
+case 21:
YY_RULE_SETUP
-#line 115 "engines/director/lingo/lingo-lex.l"
+#line 119 "engines/director/lingo/lingo-lex.l"
{ count(); return tGLOBAL; }
YY_BREAK
-case 21:
+case 22:
YY_RULE_SETUP
-#line 116 "engines/director/lingo/lingo-lex.l"
+#line 120 "engines/director/lingo/lingo-lex.l"
{ count(); return tGO; }
YY_BREAK
-case 22:
+case 23:
YY_RULE_SETUP
-#line 117 "engines/director/lingo/lingo-lex.l"
+#line 121 "engines/director/lingo/lingo-lex.l"
{ count(); return tGO; }
YY_BREAK
-case 23:
+case 24:
YY_RULE_SETUP
-#line 118 "engines/director/lingo/lingo-lex.l"
+#line 122 "engines/director/lingo/lingo-lex.l"
{ count(); return tINSTANCE; }
YY_BREAK
-case 24:
+case 25:
YY_RULE_SETUP
-#line 119 "engines/director/lingo/lingo-lex.l"
+#line 123 "engines/director/lingo/lingo-lex.l"
{ count(); return tINTERSECTS; }
YY_BREAK
-case 25:
+case 26:
YY_RULE_SETUP
-#line 120 "engines/director/lingo/lingo-lex.l"
+#line 124 "engines/director/lingo/lingo-lex.l"
{ count(); return tINTO; }
YY_BREAK
-case 26:
+case 27:
YY_RULE_SETUP
-#line 121 "engines/director/lingo/lingo-lex.l"
+#line 125 "engines/director/lingo/lingo-lex.l"
{ count(); return tITEM; }
YY_BREAK
-case 27:
+case 28:
YY_RULE_SETUP
-#line 122 "engines/director/lingo/lingo-lex.l"
+#line 126 "engines/director/lingo/lingo-lex.l"
{ count(); return tLINE; }
YY_BREAK
-case 28:
+case 29:
YY_RULE_SETUP
-#line 123 "engines/director/lingo/lingo-lex.l"
+#line 127 "engines/director/lingo/lingo-lex.l"
{ count(); return checkImmediate(tLOOP); }
YY_BREAK
-case 29:
+case 30:
YY_RULE_SETUP
-#line 124 "engines/director/lingo/lingo-lex.l"
+#line 128 "engines/director/lingo/lingo-lex.l"
{ count(); return tMACRO; }
YY_BREAK
-case 30:
+case 31:
YY_RULE_SETUP
-#line 125 "engines/director/lingo/lingo-lex.l"
+#line 129 "engines/director/lingo/lingo-lex.l"
{ count(); return tMETHOD; }
YY_BREAK
-case 31:
+case 32:
YY_RULE_SETUP
-#line 126 "engines/director/lingo/lingo-lex.l"
+#line 130 "engines/director/lingo/lingo-lex.l"
{ count(); return tMOD; }
YY_BREAK
-case 32:
+case 33:
YY_RULE_SETUP
-#line 127 "engines/director/lingo/lingo-lex.l"
+#line 131 "engines/director/lingo/lingo-lex.l"
{ count(); return tMOVIE; }
YY_BREAK
-case 33:
+case 34:
YY_RULE_SETUP
-#line 128 "engines/director/lingo/lingo-lex.l"
+#line 132 "engines/director/lingo/lingo-lex.l"
{ count(); return tNEXT; }
YY_BREAK
-case 34:
+case 35:
YY_RULE_SETUP
-#line 129 "engines/director/lingo/lingo-lex.l"
+#line 133 "engines/director/lingo/lingo-lex.l"
{ count(); return tNOT; }
YY_BREAK
-case 35:
+case 36:
YY_RULE_SETUP
-#line 130 "engines/director/lingo/lingo-lex.l"
+#line 134 "engines/director/lingo/lingo-lex.l"
{ count(); return tOF; }
YY_BREAK
-case 36:
+case 37:
YY_RULE_SETUP
-#line 131 "engines/director/lingo/lingo-lex.l"
+#line 135 "engines/director/lingo/lingo-lex.l"
{ count(); return tON; } // D3
YY_BREAK
-case 37:
+case 38:
YY_RULE_SETUP
-#line 132 "engines/director/lingo/lingo-lex.l"
+#line 136 "engines/director/lingo/lingo-lex.l"
{ count(); return tOPEN; }
YY_BREAK
-case 38:
+case 39:
YY_RULE_SETUP
-#line 133 "engines/director/lingo/lingo-lex.l"
+#line 137 "engines/director/lingo/lingo-lex.l"
{ count(); return tOR; }
YY_BREAK
-case 39:
+case 40:
YY_RULE_SETUP
-#line 134 "engines/director/lingo/lingo-lex.l"
+#line 138 "engines/director/lingo/lingo-lex.l"
{ count(); return tPLAY; }
YY_BREAK
-case 40:
+case 41:
YY_RULE_SETUP
-#line 135 "engines/director/lingo/lingo-lex.l"
+#line 139 "engines/director/lingo/lingo-lex.l"
{ count(); yylval.s = new Common::String(yytext); return tPLAYACCEL; }
YY_BREAK
-case 41:
+case 42:
YY_RULE_SETUP
-#line 136 "engines/director/lingo/lingo-lex.l"
+#line 140 "engines/director/lingo/lingo-lex.l"
{ count(); return tPREVIOUS; }
YY_BREAK
-case 42:
+case 43:
YY_RULE_SETUP
-#line 137 "engines/director/lingo/lingo-lex.l"
+#line 141 "engines/director/lingo/lingo-lex.l"
+{ count(); return tPROPERTY; } // D4
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 142 "engines/director/lingo/lingo-lex.l"
{ count(); return tPUT; }
YY_BREAK
-case 43:
+case 45:
YY_RULE_SETUP
-#line 138 "engines/director/lingo/lingo-lex.l"
+#line 143 "engines/director/lingo/lingo-lex.l"
{ count(); return checkImmediate(tREPEAT); }
YY_BREAK
-case 44:
+case 46:
YY_RULE_SETUP
-#line 139 "engines/director/lingo/lingo-lex.l"
+#line 144 "engines/director/lingo/lingo-lex.l"
{ count(); return tSET; }
YY_BREAK
-case 45:
+case 47:
YY_RULE_SETUP
-#line 140 "engines/director/lingo/lingo-lex.l"
+#line 145 "engines/director/lingo/lingo-lex.l"
{ count(); return tSTARTS; }
YY_BREAK
-case 46:
+case 48:
YY_RULE_SETUP
-#line 141 "engines/director/lingo/lingo-lex.l"
+#line 146 "engines/director/lingo/lingo-lex.l"
+{ count(); return tTELL; }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 147 "engines/director/lingo/lingo-lex.l"
+{
+ count();
+
+ yylval.e[0] = g_lingo->_theEntities["last"]->entity;
+ yylval.e[1] = 0; // No field
+
+ return THEENTITYWITHID;
+ }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 155 "engines/director/lingo/lingo-lex.l"
{
count();
@@ -1279,9 +1328,9 @@ YY_RULE_SETUP
return THEENTITYWITHID;
}
YY_BREAK
-case 47:
+case 51:
YY_RULE_SETUP
-#line 149 "engines/director/lingo/lingo-lex.l"
+#line 163 "engines/director/lingo/lingo-lex.l"
{
count();
@@ -1323,9 +1372,9 @@ YY_RULE_SETUP
warning("Unhandled the entity %s", ptr);
}
YY_BREAK
-case 48:
+case 52:
YY_RULE_SETUP
-#line 189 "engines/director/lingo/lingo-lex.l"
+#line 203 "engines/director/lingo/lingo-lex.l"
{
count();
@@ -1358,9 +1407,9 @@ YY_RULE_SETUP
return THEENTITY;
}
YY_BREAK
-case 49:
+case 53:
YY_RULE_SETUP
-#line 220 "engines/director/lingo/lingo-lex.l"
+#line 234 "engines/director/lingo/lingo-lex.l"
{
count();
@@ -1381,69 +1430,69 @@ YY_RULE_SETUP
warning("Unhandled the entity %s", ptr);
}
YY_BREAK
-case 50:
+case 54:
YY_RULE_SETUP
-#line 239 "engines/director/lingo/lingo-lex.l"
+#line 253 "engines/director/lingo/lingo-lex.l"
{ count(); return tTHEN; }
YY_BREAK
-case 51:
+case 55:
YY_RULE_SETUP
-#line 240 "engines/director/lingo/lingo-lex.l"
+#line 254 "engines/director/lingo/lingo-lex.l"
{ count(); return tTO; }
YY_BREAK
-case 52:
+case 56:
YY_RULE_SETUP
-#line 241 "engines/director/lingo/lingo-lex.l"
+#line 255 "engines/director/lingo/lingo-lex.l"
{ count(); return tSPRITE; }
YY_BREAK
-case 53:
+case 57:
YY_RULE_SETUP
-#line 242 "engines/director/lingo/lingo-lex.l"
+#line 256 "engines/director/lingo/lingo-lex.l"
{ count(); return tWITH; }
YY_BREAK
-case 54:
+case 58:
YY_RULE_SETUP
-#line 243 "engines/director/lingo/lingo-lex.l"
+#line 257 "engines/director/lingo/lingo-lex.l"
{ count(); return tWITHIN; }
YY_BREAK
-case 55:
+case 59:
YY_RULE_SETUP
-#line 244 "engines/director/lingo/lingo-lex.l"
+#line 258 "engines/director/lingo/lingo-lex.l"
{ count(); return tWHEN; }
YY_BREAK
-case 56:
+case 60:
YY_RULE_SETUP
-#line 245 "engines/director/lingo/lingo-lex.l"
+#line 259 "engines/director/lingo/lingo-lex.l"
{ count(); return tWHILE; }
YY_BREAK
-case 57:
+case 61:
YY_RULE_SETUP
-#line 246 "engines/director/lingo/lingo-lex.l"
+#line 260 "engines/director/lingo/lingo-lex.l"
{ count(); return tWORD; }
YY_BREAK
-case 58:
+case 62:
YY_RULE_SETUP
-#line 248 "engines/director/lingo/lingo-lex.l"
+#line 262 "engines/director/lingo/lingo-lex.l"
{ count(); return tNEQ; }
YY_BREAK
-case 59:
+case 63:
YY_RULE_SETUP
-#line 249 "engines/director/lingo/lingo-lex.l"
+#line 263 "engines/director/lingo/lingo-lex.l"
{ count(); return tGE; }
YY_BREAK
-case 60:
+case 64:
YY_RULE_SETUP
-#line 250 "engines/director/lingo/lingo-lex.l"
+#line 264 "engines/director/lingo/lingo-lex.l"
{ count(); return tLE; }
YY_BREAK
-case 61:
+case 65:
YY_RULE_SETUP
-#line 251 "engines/director/lingo/lingo-lex.l"
+#line 265 "engines/director/lingo/lingo-lex.l"
{ count(); return tCONCAT; }
YY_BREAK
-case 62:
+case 66:
YY_RULE_SETUP
-#line 253 "engines/director/lingo/lingo-lex.l"
+#line 267 "engines/director/lingo/lingo-lex.l"
{
count();
yylval.s = new Common::String(yytext);
@@ -1461,21 +1510,28 @@ YY_RULE_SETUP
}
if (g_lingo->_builtins.contains(yytext)) {
- if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) {
+ int type = g_lingo->_builtins[yytext]->type;
+ if ((type == BLTIN || type == FBLTIN || type == RBLTIN) && g_lingo->_builtins[yytext]->parens == false) {
+ if (type == RBLTIN) {
+ if (g_lingo->_builtins[yytext]->nargs != 1 || g_lingo->_builtins[yytext]->maxArgs != 1)
+ error("Incorrectly set RBLTIN %s", yytext);
+
+ return RBLTINONEARG;
+ }
if (g_lingo->_builtins[yytext]->nargs == 0) {
if (g_lingo->_builtins[yytext]->maxArgs == 0)
- return BLTINNOARGS;
+ return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS;
else if (g_lingo->_builtins[yytext]->maxArgs == 1)
return BLTINNOARGSORONE;
else
- error("Incorrect setup for builtin: %s", yytext);
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
} else if (g_lingo->_builtins[yytext]->nargs == 1 &&
g_lingo->_builtins[yytext]->maxArgs == 1) {
- return BLTINONEARG;
+ return type == BLTIN ? BLTINONEARG : FBLTINONEARG;
} else if (g_lingo->_builtins[yytext]->nargs == -1) {
- return BLTINARGLIST;
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
} else {
- error("Incorrect setup for builtin: %s", yytext);
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
}
}
}
@@ -1483,43 +1539,43 @@ YY_RULE_SETUP
return ID;
}
YY_BREAK
-case 63:
+case 67:
YY_RULE_SETUP
-#line 291 "engines/director/lingo/lingo-lex.l"
+#line 312 "engines/director/lingo/lingo-lex.l"
{ count(); yylval.f = atof(yytext); return FLOAT; }
YY_BREAK
-case 64:
+case 68:
YY_RULE_SETUP
-#line 292 "engines/director/lingo/lingo-lex.l"
+#line 313 "engines/director/lingo/lingo-lex.l"
{ count(); yylval.i = strtol(yytext, NULL, 10); return INT; }
YY_BREAK
-case 65:
+case 69:
YY_RULE_SETUP
-#line 293 "engines/director/lingo/lingo-lex.l"
+#line 314 "engines/director/lingo/lingo-lex.l"
{ count(); return *yytext; }
YY_BREAK
-case 66:
-/* rule 66 can match eol */
+case 70:
+/* rule 70 can match eol */
YY_RULE_SETUP
-#line 294 "engines/director/lingo/lingo-lex.l"
+#line 315 "engines/director/lingo/lingo-lex.l"
{ return '\n'; }
YY_BREAK
-case 67:
+case 71:
YY_RULE_SETUP
-#line 295 "engines/director/lingo/lingo-lex.l"
+#line 316 "engines/director/lingo/lingo-lex.l"
{ count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; }
YY_BREAK
-case 68:
+case 72:
YY_RULE_SETUP
-#line 296 "engines/director/lingo/lingo-lex.l"
-
+#line 317 "engines/director/lingo/lingo-lex.l"
+{ count(); }
YY_BREAK
-case 69:
+case 73:
YY_RULE_SETUP
-#line 298 "engines/director/lingo/lingo-lex.l"
+#line 319 "engines/director/lingo/lingo-lex.l"
ECHO;
YY_BREAK
-#line 1523 "engines/director/lingo/lingo-lex.cpp"
+#line 1579 "engines/director/lingo/lingo-lex.cpp"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1812,7 +1868,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 253 )
+ if ( yy_current_state >= 273 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1840,11 +1896,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 253 )
+ if ( yy_current_state >= 273 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 252);
+ yy_is_jam = (yy_current_state == 272);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -2482,7 +2538,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
-#line 298 "engines/director/lingo/lingo-lex.l"
+#line 319 "engines/director/lingo/lingo-lex.l"
@@ -2493,7 +2549,7 @@ namespace Director {
int Lingo::parse(const char *code) {
YY_BUFFER_STATE bp;
- if (debugChannelSet(-1, kDebugLingoCompile))
+ if (debugChannelSet(-1, kDebugLingoParse))
yydebug = 1;
else
yydebug = 0;
diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l
index 00750c4523..6a38bac047 100644
--- a/engines/director/lingo/lingo-lex.l
+++ b/engines/director/lingo/lingo-lex.l
@@ -37,6 +37,9 @@ using namespace Director;
int yyparse();
static void count() {
+ if (debugChannelSet(-1, kDebugLingoParse))
+ debug("LEXER: Read '%s' at %d:%d", yytext, g_lingo->_linenumber, g_lingo->_colnumber);
+
g_lingo->_colnumber += strlen(yytext);
}
@@ -81,23 +84,24 @@ whitespace [\t ]
%%
+\xC2[\r\n] { g_lingo->_linenumber++; g_lingo->_colnumber = 0; }
--[^\r\n]*
-^{whitespace}+ { count(); }
-[\t]+ { count(); return ' '; }
+^{whitespace}+ { count(); }
+[\t]+ { count(); return ' '; }
-[#]{identifier} { count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3
+[#]{identifier} { count(); yylval.s = new Common::String(yytext); return SYMBOL; } // D3
(?i:after) { count(); return tAFTER; } // D3
-(?i:and) { count(); return tAND; }
+(?i:and) { count(); return tAND; }
(?i:before) { count(); return tBEFORE; } // D3
-(?i:char) { count(); return tCHAR; } // D3
+(?i:char) { count(); return tCHAR; } // D3
(?i:contains) { count(); return tCONTAINS; }
-(?i:done) { count(); return tDONE; }
-(?i:down) { count(); return tDOWN; }
-(?i:if) { count(); return tIF; }
+(?i:done) { count(); return tDONE; }
+(?i:down) { count(); return tDOWN; }
+(?i:if) { count(); return tIF; }
(?i:[\n\r]+[\t ]*else[\t ]+if) { countnl(); return tNLELSIF; }
(?i:[\n\r]+[\t ]*else) { countnl(); return tNLELSE; }
-(?i:else) { count(); return tELSE; }
+(?i:else) { count(); return tELSE; }
(?i:end)([\t ]*{identifier})? {
count();
@@ -110,34 +114,44 @@ whitespace [\t ]
return ENDCLAUSE;
}
(?i:factory) { count(); return tFACTORY; }
-(?i:exit) { count(); return tEXIT; }
+(?i:exit) { count(); return tEXIT; }
(?i:frame) { count(); return tFRAME; }
(?i:global) { count(); return tGLOBAL; }
-(?i:go[\t ]+to) { count(); return tGO; }
-(?i:go) { count(); return tGO; }
+(?i:go[\t ]+to) { count(); return tGO; }
+(?i:go) { count(); return tGO; }
(?i:instance) { count(); return tINSTANCE; }
-(?i:intersects) { count(); return tINTERSECTS; }
-(?i:into) { count(); return tINTO; }
-(?i:item) { count(); return tITEM; }
-(?i:line) { count(); return tLINE; }
-(?i:loop) { count(); return checkImmediate(tLOOP); }
+(?i:intersects) { count(); return tINTERSECTS; }
+(?i:into) { count(); return tINTO; }
+(?i:item) { count(); return tITEM; }
+(?i:line) { count(); return tLINE; }
+(?i:loop) { count(); return checkImmediate(tLOOP); }
(?i:macro) { count(); return tMACRO; }
(?i:method) { count(); return tMETHOD; }
-(?i:mod) { count(); return tMOD; }
+(?i:mod) { count(); return tMOD; }
(?i:movie) { count(); return tMOVIE; }
-(?i:next) { count(); return tNEXT; }
-(?i:not) { count(); return tNOT; }
-(?i:of) { count(); return tOF; }
-(?i:on) { count(); return tON; } // D3
-(?i:open) { count(); return tOPEN; }
-(?i:or) { count(); return tOR; }
-(?i:play) { count(); return tPLAY; }
-(?i:playAccel) { count(); yylval.s = new Common::String(yytext); return tPLAYACCEL; }
+(?i:next) { count(); return tNEXT; }
+(?i:not) { count(); return tNOT; }
+(?i:of) { count(); return tOF; }
+(?i:on) { count(); return tON; } // D3
+(?i:open) { count(); return tOPEN; }
+(?i:or) { count(); return tOR; }
+(?i:play) { count(); return tPLAY; }
+(?i:playAccel) { count(); yylval.s = new Common::String(yytext); return tPLAYACCEL; }
(?i:previous) { count(); return tPREVIOUS; }
-(?i:put) { count(); return tPUT; }
+(?i:property) { count(); return tPROPERTY; } // D4
+(?i:put) { count(); return tPUT; }
(?i:repeat) { count(); return checkImmediate(tREPEAT); }
-(?i:set) { count(); return tSET; }
+(?i:set) { count(); return tSET; }
(?i:starts) { count(); return tSTARTS; }
+(?i:tell) { count(); return tTELL; }
+(?i:the[ \t]+last[\t ]+of[\t ]+) {
+ count();
+
+ yylval.e[0] = g_lingo->_theEntities["last"]->entity;
+ yylval.e[1] = 0; // No field
+
+ return THEENTITYWITHID;
+ }
(?i:the[ \t]+sqrt[\t ]+of[\t ]+) {
count();
@@ -236,21 +250,21 @@ whitespace [\t ]
warning("Unhandled the entity %s", ptr);
}
-(?i:then) { count(); return tTHEN; }
-(?i:to) { count(); return tTO; }
+(?i:then) { count(); return tTHEN; }
+(?i:to) { count(); return tTO; }
(?i:sprite) { count(); return tSPRITE; }
-(?i:with) { count(); return tWITH; }
+(?i:with) { count(); return tWITH; }
(?i:within) { count(); return tWITHIN; }
-(?i:when) { count(); return tWHEN; }
+(?i:when) { count(); return tWHEN; }
(?i:while) { count(); return tWHILE; }
-(?i:word) { count(); return tWORD; }
+(?i:word) { count(); return tWORD; }
-[<][>] { count(); return tNEQ; }
-[>][=] { count(); return tGE; }
-[<][=] { count(); return tLE; }
-[&][&] { count(); return tCONCAT; }
+[<][>] { count(); return tNEQ; }
+[>][=] { count(); return tGE; }
+[<][=] { count(); return tLE; }
+[&][&] { count(); return tCONCAT; }
-{identifier} {
+{identifier} {
count();
yylval.s = new Common::String(yytext);
@@ -267,33 +281,40 @@ whitespace [\t ]
}
if (g_lingo->_builtins.contains(yytext)) {
- if (g_lingo->_builtins[yytext]->type == BLTIN && g_lingo->_builtins[yytext]->parens == false) {
+ int type = g_lingo->_builtins[yytext]->type;
+ if ((type == BLTIN || type == FBLTIN || type == RBLTIN) && g_lingo->_builtins[yytext]->parens == false) {
+ if (type == RBLTIN) {
+ if (g_lingo->_builtins[yytext]->nargs != 1 || g_lingo->_builtins[yytext]->maxArgs != 1)
+ error("Incorrectly set RBLTIN %s", yytext);
+
+ return RBLTINONEARG;
+ }
if (g_lingo->_builtins[yytext]->nargs == 0) {
if (g_lingo->_builtins[yytext]->maxArgs == 0)
- return BLTINNOARGS;
+ return type == BLTIN ? BLTINNOARGS : FBLTINNOARGS;
else if (g_lingo->_builtins[yytext]->maxArgs == 1)
return BLTINNOARGSORONE;
else
- error("Incorrect setup for builtin: %s", yytext);
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
} else if (g_lingo->_builtins[yytext]->nargs == 1 &&
g_lingo->_builtins[yytext]->maxArgs == 1) {
- return BLTINONEARG;
+ return type == BLTIN ? BLTINONEARG : FBLTINONEARG;
} else if (g_lingo->_builtins[yytext]->nargs == -1) {
- return BLTINARGLIST;
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
} else {
- error("Incorrect setup for builtin: %s", yytext);
+ return type == BLTIN ? BLTINARGLIST : FBLTINARGLIST;
}
}
}
return ID;
}
-{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; }
+{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; }
{constinteger} { count(); yylval.i = strtol(yytext, NULL, 10); return INT; }
-{operator} { count(); return *yytext; }
-{newline} { return '\n'; }
-{conststring} { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; }
-.
+{operator} { count(); return *yytext; }
+{newline} { return '\n'; }
+{conststring} { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; }
+. { count(); }
%%
@@ -304,7 +325,7 @@ namespace Director {
int Lingo::parse(const char *code) {
YY_BUFFER_STATE bp;
- if (debugChannelSet(-1, kDebugLingoCompile))
+ if (debugChannelSet(-1, kDebugLingoParse))
yydebug = 1;
else
yydebug = 0;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 71211e3bff..8f874435f7 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -30,7 +30,7 @@ class Sprite;
TheEntity entities[] = {
{ kTheActorList, "actorList", false }, // D4 property
- { kTheBeepOn, "beepOn", false }, // D2 property
+ { kTheBeepOn, "beepOn", false }, // D2 p
{ kTheButtonStyle, "buttonStyle", false }, // D2 p
{ kTheCast, "cast", true }, // D3
{ kTheCastMembers, "castmembers", false }, // D3
@@ -38,7 +38,8 @@ TheEntity entities[] = {
{ kTheChars, "chars", false }, // D3
{ kTheCheckBoxAccess, "checkBoxAccess", false }, // D2 p
{ kTheCheckBoxType, "checkBoxType", false }, // D2 p
- { kTheClickOn, "clickOn", false }, // D2 function
+ { kTheClickLoc, "clickLoc", false }, // D4 function
+ { kTheClickOn, "clickOn", false }, // D2 f
{ kTheColorDepth, "colorDepth", false }, // D2 p
{ kTheColorQD, "colorQD", false }, // D2 f
{ kTheCommandDown, "commandDown", false }, // D2 f
@@ -50,24 +51,29 @@ TheEntity entities[] = {
{ kTheFixStageSize, "fixStageSize", false }, // D2 p
{ kTheFloatPrecision, "floatPrecision", false }, // D3 p
{ kTheFrame, "frame", false }, // D2 f
+ { kTheFrameLabel, "frameLabel", false }, // D4 p
{ kTheFrameScript, "frameScript", false }, // D4 p
+ { kTheFramePalette, "framePalette", false }, // D4 p
{ kTheFreeBlock, "freeBlock", false }, // D2 f
{ kTheFreeBytes, "freeBytes", false }, // D2 f
{ kTheFullColorPermit, "fullColorPermit", false }, // D2 p
{ kTheImageDirect, "imageDirect", false }, // D2 p
{ kTheItems, "items", false }, // D3
- { kTheItemDelimiter, "itemDelimiter", false },
+ { kTheItemDelimiter, "itemDelimiter", false }, // D4 p
{ kTheKey, "key", false }, // D2 f
{ kTheKeyCode, "keyCode", false }, // D2 f
{ kTheKeyDownScript, "keyDownScript", false }, // D2 p
+ { kTheKeyUpScript, "keyUpScript", false }, // D4 p
{ kTheLabelList, "labelList", false }, // D3 f
+ { kTheLast, "last", false }, // D4 f
{ kTheLastClick, "lastClick", false }, // D2 f
{ kTheLastEvent, "lastEvent", false }, // D2 f
- { kTheLastFrame, "lastFrame", false },
+ { kTheLastFrame, "lastFrame", false }, // D4 p
{ kTheLastKey, "lastKey", false }, // D2 f
{ kTheLastRoll, "lastRoll", false }, // D2 f
{ kTheLines, "lines", false }, // D3
{ kTheMachineType, "machineType", false }, // D2 f
+ { kTheMaxInteger, "maxInteger", false }, // D4 f
{ kTheMemorySize, "memorySize", false }, // D2 f
{ kTheMenu, "menu", true },
{ kTheMenus, "menus", false },
@@ -85,16 +91,26 @@ TheEntity entities[] = {
{ kTheMouseV, "mouseV", false }, // D2 f
{ kTheMouseWord, "mouseWord", false }, // D3 f
{ kTheMovie, "movie", false }, // D2 f
- { kTheMultiSound, "multiSound", false },
+ { kTheMovieFileFreeSize,"movieFileFreeSize",false }, // D4 f
+ { kTheMovieFileSize, "movieFileSize", false }, // D4 f
+ { kTheMovieName, "movieName", false }, // D4 f
+ { kTheMoviePath, "moviePath", false }, // D4 f
+ { kTheMultiSound, "multiSound", false }, // D4 p
{ kTheOptionDown, "optionDown", false }, // D2 f
+ { kTheParamCount, "paramCount", false }, // D4 f
{ kThePathName, "pathName", false }, // D2 f
{ kThePauseState, "pauseState", false }, // D2 f
{ kThePerFrameHook, "perFrameHook", false }, // D2 p
- { kThePreloadEventAbort,"preloadEventAbort",false },
+ { kThePreloadEventAbort,"preloadEventAbort",false }, // D4 p
+ { kThePreLoadRAM, "preLoadRAM", false }, // D4 p
+ { kTheQuickTimePresent, "quickTimePresent", false }, // D4 f
+ { kTheRandomSeed, "randomSeed", false }, // D4 p
{ kTheResult, "result", false }, // D2 f
{ kTheRightMouseDown, "rightMouseDown", false },
{ kTheRightMouseUp, "rightMouseUp", false },
- { kTheRomanLingo, "romanLingo", false },
+ { kTheRomanLingo, "romanLingo", false }, // D4 p
+ { kTheSearchCurrentFolder,"searchCurrentFolder",false },// D4 f
+ { kTheSearchPath, "searchPath", false }, // D4 f
{ kTheSelection, "selection", false }, // D2 f
{ kTheSelEnd, "selEnd", false }, // D2 p
{ kTheSelStart, "selStart", false }, // D2 p
@@ -103,7 +119,7 @@ TheEntity entities[] = {
{ kTheSoundLevel, "soundLevel", false }, // D2 p
{ kTheSprite, "sprite", true }, // D4
{ kTheSqrt, "sqrt", false }, // D2 f
- { kTheStage, "stage", false },
+ { kTheStage, "stage", false }, // D4 p
{ kTheStageBottom, "stageBottom", false }, // D2 f
{ kTheStageColor, "stageColor", false }, // D3 p
{ kTheStageLeft, "stageLeft", false }, // D2 f
@@ -120,19 +136,24 @@ TheEntity entities[] = {
{ kTheTimeoutScript, "timeoutScript", false }, // D2 p
{ kTheTime, "time", false }, // D3 f
{ kTheTimer, "timer", false }, // D2 p
- { kTheWindow, "window", false },
+ { kTheTrace, "trace", false }, // D4 p
+ { kTheTraceLoad, "traceLoad", false }, // D4 p
+ { kTheTraceLogFile, "traceLogFile", false }, // D4 p
+ { kTheUpdateMovieEnabled,"updateMovieEnabled",false }, // D4 p
+ { kTheWindow, "window", true }, // D4
+ { kTheWindowList, "windowList", false }, // D4 p
{ kTheWords, "words", false }, // D3
{ kTheNOEntity, NULL, false }
};
TheEntityField fields[] = {
{ kTheSprite, "backColor", kTheBackColor }, // D2 p
- { kTheSprite, "blend", kTheBlend },
+ { kTheSprite, "blend", kTheBlend }, // D4 p
{ kTheSprite, "bottom", kTheBottom }, // D2 p
{ kTheSprite, "castNum", kTheCastNum }, // D2 p
{ kTheSprite, "constraint", kTheConstraint }, // D2 p
{ kTheSprite, "cursor", kTheCursor }, // D2 p
- { kTheSprite, "editableText", kTheEditableText },
+ { kTheSprite, "editableText", kTheEditableText }, // D4 p
{ kTheSprite, "foreColor", kTheForeColor }, // D2 p
{ kTheSprite, "height", kTheHeight }, // D2 p
{ kTheSprite, "immediate", kTheImmediate }, // D2 p
@@ -141,58 +162,63 @@ TheEntityField fields[] = {
{ kTheSprite, "lineSize", kTheLineSize }, // D2 p
{ kTheSprite, "locH", kTheLocH }, // D2 p
{ kTheSprite, "locV", kTheLocV }, // D2 p
- { kTheSprite, "moveable", kTheMoveable },
- { kTheSprite, "movieRate", kTheMovieRate },
- { kTheSprite, "movieTime", kTheMovieTime },
+ { kTheSprite, "moveableSprite",kTheMoveableSprite },// D4 p
+ { kTheSprite, "movieRate", kTheMovieRate }, // D4 P
+ { kTheSprite, "movieTime", kTheMovieTime }, // D4 P
{ kTheSprite, "pattern", kThePattern }, // D2 p
{ kTheSprite, "puppet", kThePuppet }, // D2 p
{ kTheSprite, "right", kTheRight }, // D2 p
- { kTheSprite, "scriptNum", kTheScriptNum },
- { kTheSprite, "startTime", kTheStartTime },
+ { kTheSprite, "scoreColor", kTheScoreColor }, // D4 p
+ { kTheSprite, "scriptNum", kTheScriptNum }, // D4 p
+ { kTheSprite, "startTime", kTheStartTime }, // D4 p
{ kTheSprite, "stretch", kTheStrech }, // D2 p
- { kTheSprite, "stopTime", kTheStopTime },
+ { kTheSprite, "stopTime", kTheStopTime }, // D4 p
{ kTheSprite, "top", kTheTop }, // D2 p
- { kTheSprite, "trails", kTheTrails },
+ { kTheSprite, "trails", kTheTrails }, // D4 p
{ kTheSprite, "type", kTheType }, // D2 p
- { kTheSprite, "visible", kTheVisible },
- { kTheSprite, "volume", kTheVolume },
+ { kTheSprite, "visible", kTheVisible }, // D4 p
+ { kTheSprite, "volume", kTheVolume }, // D4 p
{ kTheSprite, "width", kTheWidth }, // D2 p
// Common cast fields
{ kTheCast, "castType", kTheCastType }, // D4 p
- { kTheCast, "filename", kTheFilename },
- { kTheCast, "height", kTheHeight },
- { kTheCast, "loaded", kTheLoaded },
- { kTheCast, "modified", kTheModified },
+ { kTheCast, "filename", kTheFileName }, // D4 p
+ { kTheCast, "height", kTheHeight }, // D4 p
+ { kTheCast, "loaded", kTheLoaded }, // D4 p
+ { kTheCast, "modified", kTheModified }, // D4 p
{ kTheCast, "name", kTheName }, // D3 p
{ kTheCast, "number", kTheNumber }, // D3 p
- { kTheCast, "rect", kTheRect },
- { kTheCast, "purgePriority",kThePurgePriority }, // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal
- { kTheCast, "scriptText", kTheScriptText },
- { kTheCast, "width", kTheWidth },
+ { kTheCast, "rect", kTheRect }, // D4 p
+ { kTheCast, "purgePriority",kThePurgePriority },// D4 p // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal
+ { kTheCast, "scriptText", kTheScriptText }, // D4 p
+ { kTheCast, "width", kTheWidth }, // D4 p
// Shape fields
- { kTheCast, "backColor", kTheBackColor },
- { kTheCast, "foreColor", kTheForeColor },
+ { kTheCast, "backColor", kTheBackColor }, // D4 p
+ { kTheCast, "foreColor", kTheForeColor }, // D4 p
// Digital video fields
- { kTheCast, "controller", kTheController },
- { kTheCast, "directToStage",kTheDirectToStage },
- { kTheCast, "frameRate", kTheFrameRate },
- { kTheCast, "loop", kTheLoop },
- { kTheCast, "pausedAtStart",kThePausedAtStart },
- { kTheCast, "preload", kThePreload },
- { kTheCast, "sound", kTheSound }, // 0-1 off-on
+ { kTheCast, "center", kTheCenter }, // D4 p
+ { kTheCast, "controller", kTheController }, // D4 p
+ { kTheCast, "crop", kTheCrop }, // D4 p
+ { kTheCast, "directToStage",kTheDirectToStage },// D4 p
+ { kTheCast, "duration", kTheDuration }, // D4 p
+ { kTheCast, "frameRate", kTheFrameRate }, // D4 p
+ { kTheCast, "loop", kTheLoop }, // D4 p
+ { kTheCast, "pausedAtStart",kThePausedAtStart },// D4 p
+ { kTheCast, "preLoad", kThePreLoad }, // D4 p
+ { kTheCast, "sound", kTheSound }, // D4 p // 0-1 off-on
+ { kTheCast, "video", kTheVideo }, // D4 p
// Bitmap fields
{ kTheCast, "depth", kTheDepth },
- { kTheCast, "regPoint", kTheRegPoint },
- { kTheCast, "palette", kThePalette },
+ { kTheCast, "regPoint", kTheRegPoint }, // D4 p
+ { kTheCast, "palette", kThePalette }, // D4 p
{ kTheCast, "picture", kThePicture }, // D3 p
// TextCast fields
{ kTheCast, "hilite", kTheHilite }, // D2 p
- { kTheCast, "size", kTheSize },
+ { kTheCast, "size", kTheSize }, // D4 p
{ kTheCast, "text", kTheText }, // D2 p
// Field fields
@@ -202,10 +228,15 @@ TheEntityField fields[] = {
{ kTheField, "textSize", kTheTextSize }, // D3 p
{ kTheField, "textStyle", kTheTextStyle }, // D3 p
- { kTheWindow, "drawRect", kTheDrawRect },
- { kTheWindow, "filename", kTheFilename },
- { kTheWindow, "sourceRect", kTheSourceRect },
- { kTheWindow, "visible", kTheVisible },
+ { kTheWindow, "drawRect", kTheDrawRect }, // D4 p
+ { kTheWindow, "fileName", kTheFileName }, // D4 p
+ { kTheWindow, "modal", kTheModal }, // D4 p
+ { kTheWindow, "rect", kTheRect }, // D4 p
+ { kTheWindow, "title", kTheTitle }, // D4 p
+ { kTheWindow, "titleVisible", kTheTitleVisible }, // D4 p
+ { kTheWindow, "sourceRect", kTheSourceRect }, // D4 p
+ { kTheWindow, "visible", kTheVisible }, // D4 p
+ { kTheWindow, "windowType", kTheWindowType }, // D4 p
{ kTheMenuItem, "checkmark", kTheCheckMark }, // D3 p
{ kTheMenuItem, "enabled", kTheEnabled }, // D3 p
@@ -289,20 +320,20 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
d.toInt(); // Enforce Integer
- if (!_vm->_currentScore) {
+ if (!_vm->getCurrentScore()) {
warning("The sprite %d field %d setting over non-active score", id, field);
return;
}
- Sprite *sprite = _vm->_currentScore->getSpriteById(id);
+ Sprite *sprite = _vm->getCurrentScore()->getSpriteById(id);
if (!sprite)
return;
switch (field) {
case kTheCastNum:
- if (_vm->_currentScore->_casts.contains(d.u.i)) {
- sprite->_cast = _vm->_currentScore->_casts[d.u.i];
+ if (_vm->getCurrentScore()->_casts.contains(d.u.i)) {
+ sprite->_cast = _vm->getCurrentScore()->_casts[d.u.i];
sprite->_castId = d.u.i;
}
break;
@@ -327,7 +358,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
case kTheConstraint:
sprite->_constraint = d.u.i;
break;
- case kTheMoveable:
+ case kTheMoveableSprite:
sprite->_moveable = d.u.i;
break;
case kTheBackColor:
@@ -491,12 +522,12 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
return d;
}
- if (!_vm->_currentScore) {
+ if (!_vm->getCurrentScore()) {
warning("The sprite %d field %d setting over non-active score", id, field);
return d;
}
- Sprite *sprite = _vm->_currentScore->getSpriteById(id);
+ Sprite *sprite = _vm->getCurrentScore()->getSpriteById(id);
if (!sprite)
return d;
@@ -528,7 +559,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
case kTheConstraint:
d.u.i = sprite->_constraint;
break;
- case kTheMoveable:
+ case kTheMoveableSprite:
d.u.i = sprite->_moveable;
break;
case kTheBackColor:
@@ -602,14 +633,14 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
return d;
}
- if (!_vm->_currentScore) {
+ if (!_vm->getCurrentScore()) {
warning("The cast %d field %d setting over non-active score", id, field);
return d;
}
Cast *cast;
CastInfo *castInfo;
- if (!_vm->_currentScore->_casts.contains(id)) {
+ if (!_vm->getCurrentScore()->_casts.contains(id)) {
if (field == kTheLoaded) {
d.type = INT;
d.u.i = 0;
@@ -620,8 +651,8 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
warning("The cast %d found", id);
}
- cast = _vm->_currentScore->_casts[id];
- castInfo = _vm->_currentScore->_castsInfo[id];
+ cast = _vm->getCurrentScore()->_casts[id];
+ castInfo = _vm->getCurrentScore()->_castsInfo[id];
d.type = INT;
@@ -629,7 +660,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
case kTheCastType:
d.u.i = cast->type;
break;
- case kTheFilename:
+ case kTheFileName:
d.toString();
d.u.s = &castInfo->fileName;
break;
@@ -655,7 +686,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
return d;
}
- ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]);
+ ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]);
d.u.i = shape->bgCol;
}
break;
@@ -667,7 +698,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
return d;
}
- ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]);
+ ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]);
d.u.i = shape->fgCol;
}
break;
@@ -693,13 +724,13 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
return;
}
- if (!_vm->_currentScore) {
+ if (!_vm->getCurrentScore()) {
warning("The cast %d field %d setting over non-active score", id, field);
return;
}
- Cast *cast = _vm->_currentScore->_casts[id];
- CastInfo *castInfo = _vm->_currentScore->_castsInfo[id];
+ Cast *cast = _vm->getCurrentScore()->_casts[id];
+ CastInfo *castInfo = _vm->getCurrentScore()->_castsInfo[id];
if (!cast) {
warning("The cast %d found", id);
@@ -711,7 +742,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
cast->type = static_cast<CastType>(d.u.i);
cast->modified = 1;
break;
- case kTheFilename:
+ case kTheFileName:
castInfo->fileName = *d.u.s;
break;
case kTheName:
@@ -733,7 +764,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
if (cast->type != kCastShape) {
warning("Field %d of cast %d not found", field, id);
}
- ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]);
+ ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]);
shape->bgCol = d.u.i;
shape->modified = 1;
}
@@ -744,7 +775,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
warning("Field %d of cast %d not found", field, id);
return;
}
- ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]);
+ ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]);
shape->fgCol = d.u.i;
shape->modified = 1;
}
diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h
index 8cec0ced13..173efe6bbe 100644
--- a/engines/director/lingo/lingo-the.h
+++ b/engines/director/lingo/lingo-the.h
@@ -36,6 +36,7 @@ enum TheEntityType {
kTheChars,
kTheCheckBoxAccess,
kTheCheckBoxType,
+ kTheClickLoc,
kTheClickOn,
kTheColorDepth,
kTheColorQD,
@@ -48,6 +49,8 @@ enum TheEntityType {
kTheFixStageSize,
kTheFloatPrecision,
kTheFrame,
+ kTheFrameLabel,
+ kTheFramePalette,
kTheFrameScript,
kTheFreeBlock,
kTheFreeBytes,
@@ -58,7 +61,9 @@ enum TheEntityType {
kTheKey,
kTheKeyCode,
kTheKeyDownScript,
+ kTheKeyUpScript,
kTheLabelList,
+ kTheLast,
kTheLastClick,
kTheLastEvent,
kTheLastFrame,
@@ -66,6 +71,7 @@ enum TheEntityType {
kTheLastRoll,
kTheLines,
kTheMachineType,
+ kTheMaxInteger,
kTheMemorySize,
kTheMenu,
kTheMenuItem,
@@ -83,16 +89,26 @@ enum TheEntityType {
kTheMouseV,
kTheMouseWord,
kTheMovie,
+ kTheMovieFileFreeSize,
+ kTheMovieFileSize,
+ kTheMovieName,
+ kTheMoviePath,
kTheMultiSound,
kTheOptionDown,
+ kTheParamCount,
kThePathName,
kThePauseState,
kThePerFrameHook,
kThePreloadEventAbort,
+ kThePreLoadRAM,
+ kTheQuickTimePresent,
+ kTheRandomSeed,
kTheResult,
kTheRightMouseDown,
kTheRightMouseUp,
kTheRomanLingo,
+ kTheSearchCurrentFolder,
+ kTheSearchPath,
kTheSelection,
kTheSelEnd,
kTheSelStart,
@@ -118,80 +134,94 @@ enum TheEntityType {
kTheTimeoutPlay,
kTheTimeoutScript,
kTheTimer,
+ kTheTrace,
+ kTheTraceLoad,
+ kTheTraceLogFile,
+ kTheUpdateMovieEnabled,
kTheWindow,
+ kTheWindowList,
kTheWords
};
enum TheFieldType {
kTheNOField = 0,
kTheAbbr = 1,
+ kTheBackColor,
+ kTheBlend,
+ kTheBottom,
kTheCastNum,
kTheCastType,
+ kTheCenter,
kTheCheckMark,
+ kTheConstraint,
kTheController,
+ kTheCrop,
kTheCursor,
kTheDepth,
kTheDirectToStage,
kTheDrawRect,
- kTheLocH,
- kTheLocV,
- kTheBackColor,
- kTheBlend,
- kTheBottom,
- kTheConstraint,
+ kTheDuration,
kTheEditableText,
kTheEnabled,
+ kTheFileName,
kTheForeColor,
kTheFrameRate,
- kTheFilename,
kTheHeight,
kTheHilite,
kTheImmediate,
kTheInk,
kTheLeft,
kTheLineSize,
+ kTheLoaded,
+ kTheLocH,
+ kTheLocV,
kTheLong,
kTheLoop,
- kTheLoaded,
+ kTheModal,
kTheModified,
- kTheMoveable,
+ kTheMoveableSprite,
kTheMovieRate,
kTheMovieTime,
- kTheNumber,
kTheName,
+ kTheNumber,
kThePalette,
kThePattern,
kThePausedAtStart,
kThePicture,
- kThePreload,
+ kThePreLoad,
kThePuppet,
kThePurgePriority,
kTheRect,
kTheRegPoint,
kTheRight,
- kTheShort,
- kTheStopTime,
- kTheStretch,
- kTheStartTime,
+ kTheScoreColor,
kTheScript,
kTheScriptNum,
kTheScriptText,
+ kTheShort,
kTheSize,
- kTheStrech,
kTheSound,
kTheSourceRect,
+ kTheStartTime,
+ kTheStopTime,
+ kTheStrech,
+ kTheStretch,
kTheText,
kTheTextAlign,
kTheTextFont,
kTheTextheight,
kTheTextSize,
kTheTextStyle,
+ kTheTitle,
+ kTheTitleVisible,
kTheTop,
kTheTrails,
kTheType,
+ kTheVideo,
kTheVisible,
kTheVolume,
- kTheWidth
+ kTheWidth,
+ kTheWindowType
};
struct TheEntity {
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 4a9b612649..fc12b8d562 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -36,18 +36,19 @@ struct EventHandlerType {
const char *name;
} static const eventHandlerDescs[] = {
{ kEventPrepareMovie, "prepareMovie" },
- { kEventStartMovie, "startMovie" },
- { kEventStopMovie, "stopMovie" },
+ { kEventStartMovie, "startMovie" }, // D3?
+ { kEventStepMovie, "stepMovie" }, // D3?
+ { kEventStopMovie, "stopMovie" }, // D3?
{ kEventNew, "newSprite" },
{ kEventBeginSprite, "beginSprite" },
{ kEventEndSprite, "endSprite" },
- { kEventEnterFrame, "enterFrame" },
+ { kEventEnterFrame, "enterFrame" }, // D4
{ kEventPrepareFrame, "prepareFrame" },
{ kEventIdle, "idle" },
{ kEventStepFrame, "stepFrame"},
- { kEventExitFrame, "exitFrame" },
+ { kEventExitFrame, "exitFrame" }, // D4
{ kEventActivateWindow, "activateWindow" },
{ kEventDeactivateWindow, "deactivateWindow" },
@@ -57,10 +58,10 @@ struct EventHandlerType {
{ kEventCloseWindow, "closeWindow" },
{ kEventStart, "start" },
- { kEventKeyUp, "keyUp" },
- { kEventKeyDown, "keyDown" }, // D2 as when
- { kEventMouseUp, "mouseUp" }, // D2 as when
- { kEventMouseDown, "mouseDown" }, // D2 as when
+ { kEventKeyUp, "keyUp" }, // D4
+ { kEventKeyDown, "keyDown" }, // D2 w D4 (as when from D2)
+ { kEventMouseUp, "mouseUp" }, // D2 w D3?
+ { kEventMouseDown, "mouseDown" }, // D2 w D3?
{ kEventRightMouseDown, "rightMouseDown" },
{ kEventRightMouseUp, "rightMouseUp" },
{ kEventMouseEnter, "mouseEnter" },
@@ -74,7 +75,6 @@ struct EventHandlerType {
};
Symbol::Symbol() {
- name = NULL;
type = VOID;
u.s = NULL;
nargs = 0;
@@ -91,10 +91,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_eventHandlerTypes[t->handler] = t->name;
}
- initBuiltIns();
- initFuncs();
- initTheEntities();
-
_currentScript = 0;
_currentScriptType = kMovieScript;
_currentEntityId = 0;
@@ -119,6 +115,10 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_localvars = NULL;
+ initBuiltIns();
+ initFuncs();
+ initTheEntities();
+
warning("Lingo Inited");
}
@@ -158,7 +158,7 @@ const char *Lingo::findNextDefinition(const char *s) {
}
void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
- debugC(2, kDebugLingoCompile, "Add code \"%s\" for type %d with id %d", code, type, id);
+ debugC(2, kDebugLingoCompile, "Add code \"%s\" for type %s with id %d", code, scriptType2str(type), id);
if (_scripts[type].contains(id)) {
delete _scripts[type][id];
@@ -247,7 +247,7 @@ void Lingo::executeScript(ScriptType type, uint16 id) {
return;
}
- debugC(2, kDebugLingoExec, "Executing script type: %d, id: %d", type, id);
+ debugC(2, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
_currentScript = _scripts[type][id];
_pc = 0;
@@ -291,19 +291,20 @@ Symbol *Lingo::getHandler(Common::String &name) {
}
void Lingo::processEvent(LEvent event, ScriptType st, int entityId) {
- if (entityId <= 0)
+ if (entityId < 0)
return;
+ debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId);
+
_currentEntityId = entityId;
if (!_eventHandlerTypes.contains(event))
error("processEvent: Unknown event %d for entity %d", event, entityId);
if (_handlers.contains(ENTITY_INDEX(event, entityId))) {
- call(_eventHandlerTypes[event], 0); //D4+ Events
- pop();
+ call(_eventHandlerTypes[event], 0); // D4+ Events
} else if (_scripts[st].contains(entityId)) {
- executeScript(st, entityId + 1); //D3 list of scripts.
+ executeScript(st, entityId); // D3 list of scripts.
} else {
debugC(8, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId);
}
@@ -387,6 +388,7 @@ Common::String *Datum::toString() {
delete s;
s = u.s;
break;
+ case SYMBOL:
case OBJECT:
*s = Common::String::format("#%s", u.s->c_str());
break;
@@ -394,7 +396,7 @@ Common::String *Datum::toString() {
*s = "#void";
break;
case VAR:
- *s = Common::String::format("var: #%s", u.sym->name);
+ *s = Common::String::format("var: #%s", u.sym->name.c_str());
break;
default:
warning("Incorrect operation toString() for type: %s", type2str());
@@ -426,6 +428,8 @@ const char *Datum::type2str(bool isk) {
return isk ? "#symbol" : "SYMBOL";
case OBJECT:
return isk ? "#object" : "OBJECT";
+ case REFERENCE:
+ return "REFERENCE";
case VAR:
return isk ? "#var" : "VAR";
default:
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 8e033b181d..550156c1c7 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -36,6 +36,7 @@ namespace Director {
enum LEvent {
kEventPrepareMovie,
kEventStartMovie,
+ kEventStepMovie,
kEventStopMovie,
kEventNew,
@@ -103,7 +104,7 @@ struct Pointer_Hash {
typedef Common::HashMap<void *, FuncDesc *, Pointer_Hash, Pointer_EqualTo> FuncHash;
struct Symbol { /* symbol table entry */
- char *name;
+ Common::String name;
int type;
union {
int i; /* VAR */
@@ -173,6 +174,8 @@ public:
Lingo(DirectorEngine *vm);
~Lingo();
+ void restartLingo();
+
void addCode(const char *code, ScriptType type, uint16 id);
void executeScript(ScriptType type, uint16 id);
void printStack(const char *s);
@@ -284,6 +287,7 @@ public:
static void c_repeatwithcode();
static void c_ifcode();
static void c_whencode();
+ static void c_tellcode();
static void c_exitRepeat();
static void c_eq();
static void c_neq();
@@ -305,13 +309,14 @@ public:
static void c_gotoprevious();
static void c_global();
static void c_instance();
+ static void c_property();
static void c_play();
static void c_playdone();
static void c_open();
- void printStubWithArglist(const char *funcname, int nargs);
+ void printSTUBWithArglist(const char *funcname, int nargs);
void convertVOIDtoString(int arg, int nargs);
void dropStack(int nargs);
void drop(uint num);
@@ -368,13 +373,18 @@ public:
static void b_ilk(int nargs);
static void b_integerp(int nargs);
static void b_objectp(int nargs);
+ static void b_pictureP(int nargs);
static void b_stringp(int nargs);
static void b_symbolp(int nargs);
+ static void b_voidP(int nargs);
static void b_alert(int nargs);
+ static void b_birth(int nargs);
+ static void b_clearGlobals(int nargs);
static void b_cursor(int nargs);
static void b_framesToHMS(int nargs);
static void b_HMStoFrames(int nargs);
+ static void b_param(int nargs);
static void b_printFrom(int nargs);
static void b_showGlobals(int nargs);
static void b_showLocals(int nargs);
@@ -382,20 +392,28 @@ public:
static void b_constrainH(int nargs);
static void b_constrainV(int nargs);
- static void b_duplicateCast(int nargs);
+ static void b_copyToClipBoard(int nargs);
+ static void b_duplicate(int nargs);
static void b_editableText(int nargs);
- static void b_eraseCast(int nargs);
+ static void b_erase(int nargs);
+ static void b_findEmpty(int nargs);
+ static void b_importFileInto(int nargs);
static void b_installMenu(int nargs);
static void b_label(int nargs);
static void b_marker(int nargs);
+ static void b_move(int nargs);
static void b_moveableSprite(int nargs);
+ static void b_pasteClipBoardInto(int nargs);
static void b_puppetPalette(int nargs);
static void b_puppetSound(int nargs);
static void b_puppetSprite(int nargs);
static void b_puppetTempo(int nargs);
static void b_puppetTransition(int nargs);
+ static void b_ramNeeded(int nargs);
static void b_rollOver(int nargs);
static void b_spriteBox(int nargs);
+ static void b_unLoad(int nargs);
+ static void b_unLoadCast(int nargs);
static void b_updateStage(int nargs);
static void b_zoomBox(int nargs);
@@ -404,7 +422,9 @@ public:
static void b_dontPassEvent(int nargs);
static void b_delay(int nargs);
static void b_do(int nargs);
+ static void b_halt(int nargs);
static void b_nothing(int nargs);
+ static void b_pass(int nargs);
static void b_pause(int nargs);
static void b_playAccel(int nargs);
static void b_preLoad(int nargs);
@@ -417,25 +437,42 @@ public:
static void b_closeDA(int nargs);
static void b_closeResFile(int nargs);
static void b_closeXlib(int nargs);
+ static void b_getNthFileNameInFolder(int nargs);
static void b_openDA(int nargs);
static void b_openResFile(int nargs);
static void b_openXlib(int nargs);
static void b_setCallBack(int nargs);
+ static void b_saveMovie(int nargs);
static void b_showResFile(int nargs);
static void b_showXlib(int nargs);
static void b_xFactoryList(int nargs);
static void b_point(int nargs);
+ static void b_inside(int nargs);
+ static void b_intersect(int nargs);
+ static void b_map(int nargs);
+ static void b_offsetRect(int nargs);
+ static void b_rect(int nargs);
+ static void b_union(int nargs);
+
+ static void b_close(int nargs);
+ static void b_forget(int nargs);
+ static void b_inflate(int nargs);
+ static void b_moveToBack(int nargs);
+ static void b_moveToFront(int nargs);
+ static void b_window(int nargs);
static void b_beep(int nargs);
static void b_mci(int nargs);
static void b_mciwait(int nargs);
static void b_soundBusy(int nargs);
+ static void b_soundClose(int nargs);
static void b_soundFadeIn(int nargs);
static void b_soundFadeOut(int nargs);
static void b_soundPlayFile(int nargs);
static void b_soundStop(int nargs);
+ static void b_ancestor(int nargs);
static void b_backspace(int nargs);
static void b_empty(int nargs);
static void b_enter(int nargs);
@@ -449,8 +486,10 @@ public:
static void b_factory(int nargs);
void factoryCall(Common::String &name, int nargs);
+ static void b_cast(int nargs);
static void b_field(int nargs);
static void b_me(int nargs);
+ static void b_script(int nargs);
void func_mci(Common::String &s);
void func_mciwait(Common::String &s);
@@ -510,8 +549,6 @@ private:
void push(Datum d);
Datum pop(void);
- void restartLingo();
-
Common::HashMap<uint32, const char *> _eventHandlerTypes;
Common::HashMap<Common::String, uint32> _eventHandlerTypeIds;
Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases;
diff --git a/engines/director/lingo/tests/builtin.lingo b/engines/director/lingo/tests/builtin.lingo
index 351efdb12c..561ecd3659 100644
--- a/engines/director/lingo/tests/builtin.lingo
+++ b/engines/director/lingo/tests/builtin.lingo
@@ -22,3 +22,9 @@ puppetSprite 15, true
puppetTempo 30
puppetTransition 1
puppetTransition 2,4,20
+
+move cast 1, cast 3
+move cast 3
+put findEmpty(cast 10)
+pasteClipBoardInto cast 2
+put the width of cast 3
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 1e9791637f..b876b777bf 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -27,7 +27,6 @@
#include "engines/util.h"
#include "graphics/font.h"
-#include "graphics/fonts/macfont.h"
#include "graphics/palette.h"
#include "graphics/macgui/macfontmanager.h"
#include "graphics/macgui/macwindowmanager.h"
@@ -42,113 +41,24 @@
namespace Director {
-static byte defaultPalette[768] = {
- 0, 0, 0, 17, 17, 17, 34, 34, 34, 68, 68, 68, 85, 85, 85, 119,
- 119, 119, 136, 136, 136, 170, 170, 170, 187, 187, 187, 221, 221, 221, 238, 238,
- 238, 0, 0, 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119,
- 0, 0, 136, 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0,
- 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136,
- 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 17, 0, 0,
- 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, 0, 0, 170,
- 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 0, 0, 0, 51, 0, 0,
- 102, 0, 0, 153, 0, 0, 204, 0, 0, 255, 0, 51, 0, 0, 51, 51,
- 0, 51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 102, 0, 0,
- 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0, 102, 255, 0, 153,
- 0, 0, 153, 51, 0, 153, 102, 0, 153, 153, 0, 153, 204, 0, 153, 255,
- 0, 204, 0, 0, 204, 51, 0, 204, 102, 0, 204, 153, 0, 204, 204, 0,
- 204, 255, 0, 255, 0, 0, 255, 51, 0, 255, 102, 0, 255, 153, 0, 255,
- 204, 0, 255, 255, 51, 0, 0, 51, 0, 51, 51, 0, 102, 51, 0, 153,
- 51, 0, 204, 51, 0, 255, 51, 51, 0, 51, 51, 51, 51, 51, 102, 51,
- 51, 153, 51, 51, 204, 51, 51, 255, 51, 102, 0, 51, 102, 51, 51, 102,
- 102, 51, 102, 153, 51, 102, 204, 51, 102, 255, 51, 153, 0, 51, 153, 51,
- 51, 153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 204, 0, 51,
- 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51, 204, 255, 51, 255,
- 0, 51, 255, 51, 51, 255, 102, 51, 255, 153, 51, 255, 204, 51, 255, 255,
- 102, 0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0, 204, 102,
- 0, 255, 102, 51, 0, 102, 51, 51, 102, 51, 102, 102, 51, 153, 102, 51,
- 204, 102, 51, 255, 102, 102, 0, 102, 102, 51, 102, 102, 102, 102, 102, 153,
- 102, 102, 204, 102, 102, 255, 102, 153, 0, 102, 153, 51, 102, 153, 102, 102,
- 153, 153, 102, 153, 204, 102, 153, 255, 102, 204, 0, 102, 204, 51, 102, 204,
- 102, 102, 204, 153, 102, 204, 204, 102, 204, 255, 102, 255, 0, 102, 255, 51,
- 102, 255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 153, 0, 0, 153,
- 0, 51, 153, 0, 102, 153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 51,
- 0, 153, 51, 51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255,
- 153, 102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102, 204, 153,
- 102, 255, 153, 153, 0, 153, 153, 51, 153, 153, 102, 153, 153, 153, 153, 153,
- 204, 153, 153, 255, 153, 204, 0, 153, 204, 51, 153, 204, 102, 153, 204, 153,
- 153, 204, 204, 153, 204, 255, 153, 255, 0, 153, 255, 51, 153, 255, 102, 153,
- 255, 153, 153, 255, 204, 153, 255, 255, 204, 0, 0, 204, 0, 51, 204, 0,
- 102, 204, 0, 153, 204, 0, 204, 204, 0, 255, 204, 51, 0, 204, 51, 51,
- 204, 51, 102, 204, 51, 153, 204, 51, 204, 204, 51, 255, 204, 102, 0, 204,
- 102, 51, 204, 102, 102, 204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 153,
- 0, 204, 153, 51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255,
- 204, 204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204, 204, 204,
- 204, 255, 204, 255, 0, 204, 255, 51, 204, 255, 102, 204, 255, 153, 204, 255,
- 204, 204, 255, 255, 255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153,
- 255, 0, 204, 255, 0, 255, 255, 51, 0, 255, 51, 51, 255, 51, 102, 255,
- 51, 153, 255, 51, 204, 255, 51, 255, 255, 102, 0, 255, 102, 51, 255, 102,
- 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51,
- 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255,
- 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255,
- 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 };
-
-void DirectorEngine::testFontScaling() {
- int x = 10;
- int y = 10;
- int w = 640;
- int h = 480;
-
- initGraphics(w, h, true);
- g_system->getPaletteManager()->setPalette(defaultPalette, 0, 256);
-
- Graphics::ManagedSurface surface;
-
- surface.create(w, h);
- surface.clear(255);
-
- Graphics::MacFont origFont(Graphics::kMacFontNewYork, 18);
-
- const Graphics::MacFONTFont *font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(origFont);
-
- Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 200, 500);
-
- Graphics::MacFont bigFont(Graphics::kMacFontNewYork, 15);
-
- font1 = (const Graphics::MacFONTFont *)_wm->_fontMan->getFont(bigFont);
-
- Graphics::MacFONTFont::testBlit(font1, &surface, 0, x, y + 50 + 200, 500);
-
- const char *text = "d";
-
- for (int i = 9; i <= 20; i++) {
- Graphics::MacFont macFont(Graphics::kMacFontNewYork, i);
-
- const Graphics::Font *font = _wm->_fontMan->getFont(macFont);
-
- int width = font->getStringWidth(text);
-
- Common::Rect bbox = font->getBoundingBox(text, x, y, w);
- surface.frameRect(bbox, 15);
-
- font->drawString(&surface, text, x, y, width, 0);
-
- x += width + 1;
- }
+const char *scriptTypes[] = {
+ "MovieScript",
+ "SpriteScript",
+ "FrameScript",
+ "CastScript"
+};
- g_system->copyRectToScreen(surface.getPixels(), surface.pitch, 0, 0, w, h);
+const char *scriptType2str(ScriptType scr) {
+ if (scr < 0)
+ return "NoneScript";
- Common::Event event;
+ if (scr > kMaxScriptType)
+ return "<unknown>";
- while (true) {
- if (g_system->getEventManager()->pollEvent(event))
- if (event.type == Common::EVENT_QUIT)
- break;
-
- g_system->updateScreen();
- g_system->delayMillis(10);
- }
+ return scriptTypes[scr];
}
+
Score::Score(DirectorEngine *vm, Archive *archive) {
_vm = vm;
_surface = new Graphics::ManagedSurface;
@@ -156,6 +66,12 @@ Score::Score(DirectorEngine *vm, Archive *archive) {
_movieArchive = archive;
_lingo = _vm->getLingo();
_soundManager = _vm->getSoundManager();
+
+ // FIXME: TODO: Check whether the original truely does it
+ if (_vm->getVersion() <= 3) {
+ _lingo->executeScript(kMovieScript, 0);
+ }
+
_lingo->processEvent(kEventPrepareMovie, kMovieScript, 0);
_movieScriptCount = 0;
_labels = NULL;
@@ -244,10 +160,13 @@ void Score::loadArchive() {
setSpriteCasts();
- //Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T'));
- //if (stxt.size() > 0) {
- // loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin()));
- //}
+ // Try to load movie script, it sits in resource A11
+ if (_vm->getVersion() <= 3) {
+ Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T'));
+ if (stxt.size() > 0) {
+ loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin()));
+ }
+ }
}
Score::~Score() {
@@ -345,6 +264,8 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) {
//Common::hexdump(channelData, ARRAYSIZE(channelData));
frame->readChannels(str);
+ debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size(), frame->_actionId);
+
delete str;
_frames.push_back(frame);
@@ -381,6 +302,9 @@ void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) {
if (size == 0)
continue;
+ if (debugChannelSet(5, kDebugLoading))
+ stream.hexdump(size);
+
uint8 castType = stream.readByte();
switch (castType) {
@@ -440,7 +364,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
uint32 size1, size2, size3, castType;
byte unk1 = 0, unk2 = 0, unk3 = 0;
- if (_vm->getVersion() < 4) {
+ if (_vm->getVersion() <= 3) {
size1 = stream.readUint16();
size2 = stream.readUint32();
size3 = 0;
@@ -448,7 +372,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
unk1 = stream.readByte();
unk2 = stream.readByte();
unk3 = stream.readByte();
- } else if (_vm->getVersion() < 5) {
+ } else if (_vm->getVersion() == 4) {
size1 = stream.readUint16() + 2;
size2 = stream.readUint32();
size3 = 0;
@@ -474,35 +398,22 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
switch (castType) {
case kCastBitmap:
- warning("CASt: Bitmap");
- Common::hexdump(data, size1 + 16);
_casts[id] = new BitmapCast(castStream, _vm->getVersion());
_casts[id]->type = kCastBitmap;
break;
case kCastText:
- warning("CASt: Text");
- Common::hexdump(data, size1 + 16);
_casts[id] = new TextCast(castStream, _vm->getVersion());
_casts[id]->type = kCastText;
break;
case kCastShape:
- warning("CASt: Shape");
- Common::hexdump(data, size1 + 16);
-
_casts[id] = new ShapeCast(castStream, _vm->getVersion());
_casts[id]->type = kCastShape;
break;
case kCastButton:
- warning("CASt: Button");
- Common::hexdump(data, size1 + 16);
-
_casts[id] = new ButtonCast(castStream, _vm->getVersion());
_casts[id]->type = kCastButton;
break;
case kCastLingoScript:
- warning("CASt: Script");
- Common::hexdump(data, size1 + 16);
-
_casts[id] = new ScriptCast(castStream, _vm->getVersion());
_casts[id]->type = kCastLingoScript;
break;
@@ -541,7 +452,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
ci->type = castStrings[4];
if (!ci->script.empty()) {
- //the script type here could be wrong!
+ // the script type here could be wrong!
if (ConfMan.getBool("dump_scripts"))
dumpScript(ci->script.c_str(), kCastScript, id);
@@ -599,12 +510,13 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
uint16 offset = count * 4 + 2;
byte id = stream.readByte();
- /*byte subId = */ stream.readByte(); // I couldn't find how it used in continuity (except print). Frame actionId = 1 byte.
+
+ byte subId = stream.readByte(); // I couldn't find how it used in continuity (except print). Frame actionId = 1 byte.
uint16 stringPos = stream.readUint16() + offset;
for (uint16 i = 0; i < count; i++) {
uint16 nextId = stream.readByte();
- /*byte subId = */ stream.readByte();
+ byte nextSubId = stream.readByte();
uint16 nextStringPos = stream.readUint16() + offset;
uint16 streamPos = stream.pos();
@@ -615,12 +527,15 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) {
if (ch == 0x0d) {
ch = '\n';
}
- _actions[id] += ch;
+ _actions[i + 1] += ch;
}
+ debugC(3, kDebugLoading, "id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str());
+
stream.seek(streamPos);
id = nextId;
+ subId = nextSubId;
stringPos = nextStringPos;
if (stringPos == stream.size())
@@ -735,6 +650,12 @@ void Score::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id)
ci->fileName = getString(castStrings[3]);
ci->type = castStrings[4];
+ debugC(5, kDebugLoading, "CastInfo: name: '%s' directory: '%s', fileName: '%s', type: '%s'",
+ ci->name.c_str(), ci->directory.c_str(), ci->fileName.c_str(), ci->type.c_str());
+
+ if (!ci->name.empty())
+ _castsNames[ci->name] = id;
+
_castsInfo[id] = ci;
}
@@ -743,12 +664,19 @@ void Score::gotoLoop() {
// If no marker are to the left of the playback head, the playback head continues to the right.
Common::SortedArray<Label *>::iterator i;
- for (i = _labels->begin(); i != _labels->end(); ++i) {
- if ((*i)->name == _currentLabel) {
- _currentFrame = (*i)->number;
- return;
+ if (_labels == NULL) {
+ _currentFrame = 0;
+ return;
+ } else {
+ for (i = _labels->begin(); i != _labels->end(); ++i) {
+ if ((*i)->name == _currentLabel) {
+ _currentFrame = (*i)->number;
+ return;
+ }
}
}
+
+ g_director->_skipFrameAdvance = true;
}
int Score::getCurrentLabelNumber() {
@@ -765,13 +693,17 @@ int Score::getCurrentLabelNumber() {
}
void Score::gotoNext() {
- //we can just try to use the current frame and get the next label
+ // we can just try to use the current frame and get the next label
_currentFrame = getNextLabelNumber(_currentFrame);
+
+ g_director->_skipFrameAdvance = true;
}
void Score::gotoPrevious() {
- //we actually need the frame of the label prior to the most recent label.
+ // we actually need the frame of the label prior to the most recent label.
_currentFrame = getPreviousLabelNumber(getCurrentLabelNumber());
+
+ g_director->_skipFrameAdvance = true;
}
int Score::getNextLabelNumber(int referenceFrame) {
@@ -949,7 +881,6 @@ void Score::startLoop() {
_stopPlay = false;
_nextFrameTime = 0;
- _lingo->processEvent(kEventStartMovie, kMovieScript, 0);
_frames[_currentFrame]->prepareFrame(this);
while (!_stopPlay && _currentFrame < _frames.size()) {
@@ -981,7 +912,7 @@ void Score::update() {
}
}
- // TODO Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame
+ // TODO: Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame
if (_vm->getVersion() >= 6)
_lingo->processEvent(kEventPrepareFrame, kFrameScript, _currentFrame);
@@ -994,8 +925,13 @@ void Score::update() {
}
}
- _currentFrame++;
- if (_currentFrame >= _frames.size()) return;
+ if (!g_director->_playbackPaused && !g_director->_skipFrameAdvance)
+ _currentFrame++;
+
+ g_director->_skipFrameAdvance = false;
+
+ if (_currentFrame >= _frames.size())
+ return;
_frames[_currentFrame]->prepareFrame(this);
// Stage is drawn between the prepareFrame and enterFrame events (Lingo in a Nutshell)
@@ -1030,11 +966,12 @@ void Score::update() {
}
}
}
+
_nextFrameTime = g_system->getMillis() + (float)_currentFrameRate / 60 * 1000;
}
void Score::processEvents() {
- //TODO: re-instate when we know which script to run.
+ // TODO: re-instate when we know which script to run.
//if (_currentFrame > 0)
// _lingo->processEvent(kEventIdle, _currentFrame - 1);
@@ -1050,9 +987,9 @@ void Score::processEvents() {
if (event.type == Common::EVENT_LBUTTONDOWN) {
Common::Point pos = g_system->getEventManager()->getMousePos();
- //D3 doesn't have both mouse up and down.
+ // D3 doesn't have both mouse up and down.
if (_vm->getVersion() > 3) {
- //TODO: check that this is the order of script execution!
+ // TODO: check that this is the order of script execution!
uint16 spriteId = _frames[_currentFrame]->getSpriteIDFromPos(pos);
_lingo->processEvent(kEventMouseDown, kCastScript, _frames[_currentFrame]->_sprites[spriteId]->_castId);
_lingo->processEvent(kEventMouseDown, kSpriteScript, _frames[_currentFrame]->_sprites[spriteId]->_scriptId);
@@ -1064,11 +1001,11 @@ void Score::processEvents() {
uint16 spriteId = _frames[_currentFrame]->getSpriteIDFromPos(pos);
if (_vm->getVersion() > 3) {
- //TODO: check that this is the order of script execution!
+ // TODO: check that this is the order of script execution!
_lingo->processEvent(kEventMouseUp, kCastScript, _frames[_currentFrame]->_sprites[spriteId]->_castId);
_lingo->processEvent(kEventMouseUp, kSpriteScript, _frames[_currentFrame]->_sprites[spriteId]->_scriptId);
} else {
- //D3 doesn't have cast member or sprite scripts. Just Frame Scripts.
+ // D3 doesn't have cast member or sprite scripts. Just Frame Scripts.
_lingo->processEvent(kEventMouseUp, kFrameScript, _frames[_currentFrame]->_sprites[spriteId]->_scriptId);
}
}
@@ -1094,7 +1031,7 @@ void Score::processEvents() {
warning("Keycode: %d", _vm->_keyCode);
}
- //TODO: is movie script correct? Can this be elsewhere?
+ // TODO: is movie script correct? Can this be elsewhere?
_lingo->processEvent(kEventKeyDown, kMovieScript, 0);
}
}
diff --git a/engines/director/score.h b/engines/director/score.h
index a53c13fc4d..2e762f0dad 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -52,6 +52,8 @@ enum ScriptType {
kMaxScriptType = 3
};
+const char *scriptType2str(ScriptType scr);
+
class Score {
public:
Score(DirectorEngine *vm, Archive *);
@@ -100,6 +102,7 @@ public:
Common::Array<Frame *> _frames;
Common::HashMap<int, Cast *> _casts;
Common::HashMap<uint16, CastInfo *> _castsInfo;
+ Common::HashMap<Common::String, int> _castsNames;
Common::SortedArray<Label *> *_labels;
Common::HashMap<uint16, Common::String> _actions;
Common::HashMap<uint16, Common::String> _fontMap;
@@ -109,6 +112,9 @@ public:
Archive *_movieArchive;
Common::Rect _movieRect;
+ bool _stopPlay;
+ uint32 _nextFrameTime;
+
private:
uint16 _versionMinor;
uint16 _versionMajor;
@@ -121,9 +127,7 @@ private:
uint16 _castArrayStart;
uint16 _currentFrame;
Common::String _currentLabel;
- uint32 _nextFrameTime;
uint32 _flags;
- bool _stopPlay;
uint16 _castArrayEnd;
uint16 _movieScriptCount;
uint16 _stageColor;
diff --git a/engines/dm/champion.cpp b/engines/dm/champion.cpp
index 616ea637b4..4536ff7de2 100644
--- a/engines/dm/champion.cpp
+++ b/engines/dm/champion.cpp
@@ -43,7 +43,7 @@ namespace DM {
void Champion::resetToZero() {
for (int16 i = 0; i < 30; ++i)
- _slots[i] = Thing::_none;
+ _slots[i] = _vm->_thingNone;
for (int16 i = 0; i < 20; ++i)
_skills[i].resetToZero();
_attributes = _wounds = 0;
@@ -161,7 +161,9 @@ void ChampionMan::initConstants() {
}
ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) {
+ _champions = new Champion[4];
for (uint16 i = 0; i < 4; ++i) {
+ _champions[i].setVm(_vm);
_championPendingDamage[i] = 0;
_championPendingWounds[i] = 0;
_champions[i].resetToZero();
@@ -182,6 +184,10 @@ ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) {
initConstants();
}
+ChampionMan::~ChampionMan() {
+ delete[] _champions;
+}
+
bool ChampionMan::isLeaderHandObjectThrown(int16 side) {
if (_leaderIndex == kDMChampionNone)
return false;
@@ -213,7 +219,7 @@ bool ChampionMan::isObjectThrown(uint16 champIndex, int16 slotIndex, int16 side)
curChampion->setSlot((ChampionSlot)slotIndex, actionHandThing);
} else {
curThing = getObjectRemovedFromSlot(champIndex, slotIndex);
- if (curThing == Thing::_none)
+ if (curThing == _vm->_thingNone)
return false;
}
@@ -525,7 +531,7 @@ void ChampionMan::drawChangedObjectIcons() {
}
void ChampionMan::addObjectInSlot(ChampionIndex champIndex, Thing thing, ChampionSlot slotIndex) {
- if (thing == Thing::_none)
+ if (thing == _vm->_thingNone)
return;
InventoryMan &invMan = *_vm->_inventoryMan;
@@ -606,8 +612,8 @@ Thing ChampionMan::getObjectRemovedFromLeaderHand() {
_leaderEmptyHanded = true;
Thing leaderHandObject = _leaderHandObject;
- if (leaderHandObject != Thing::_none) {
- _leaderHandObject = Thing::_none;
+ if (leaderHandObject != _vm->_thingNone) {
+ _leaderHandObject = _vm->_thingNone;
_leaderHandObjectIconIndex = kDMIconIndiceNone;
eventMan.showMouse();
_vm->_objectMan->clearLeaderObjectName();
@@ -672,14 +678,14 @@ Thing ChampionMan::getObjectRemovedFromSlot(uint16 champIndex, uint16 slotIndex)
if (slotIndex >= kDMSlotChest1) {
curThing = inventory._chestSlots[slotIndex - kDMSlotChest1];
- inventory._chestSlots[slotIndex - kDMSlotChest1] = Thing::_none;
+ inventory._chestSlots[slotIndex - kDMSlotChest1] = _vm->_thingNone;
} else {
curThing = curChampion->_slots[slotIndex];
- curChampion->_slots[slotIndex] = Thing::_none;
+ curChampion->_slots[slotIndex] = _vm->_thingNone;
}
- if (curThing == Thing::_none)
- return Thing::_none;
+ if (curThing == _vm->_thingNone)
+ return _vm->_thingNone;
bool isInventoryChampion = (_vm->indexToOrdinal(champIndex) == inventory._inventoryChampionOrdinal);
int16 curIconIndex = _vm->_objectMan->getIconIndex(curThing);
@@ -1217,7 +1223,7 @@ void ChampionMan::addScentStrength(int16 mapX, int16 mapY, int32 cycleCount) {
}
void ChampionMan::putObjectInLeaderHand(Thing thing, bool setMousePointer) {
- if (thing == Thing::_none)
+ if (thing == _vm->_thingNone)
return;
EventManager &evtMan = *_vm->_eventMan;
@@ -1346,23 +1352,23 @@ void ChampionMan::clickOnSlotBox(uint16 slotBoxIndex) {
else
slotThing = _champions[champIndex]._slots[slotIndex];
- if ((slotThing == Thing::_none) && (leaderHandObject == Thing::_none))
+ if ((slotThing == _vm->_thingNone) && (leaderHandObject == _vm->_thingNone))
return;
- if ((leaderHandObject != Thing::_none) && (!(dungeon._objectInfos[dungeon.getObjectInfoIndex(leaderHandObject)]._allowedSlots & _slotMasks[slotIndex])))
+ if ((leaderHandObject != _vm->_thingNone) && (!(dungeon._objectInfos[dungeon.getObjectInfoIndex(leaderHandObject)]._allowedSlots & _slotMasks[slotIndex])))
return;
EventManager &evtMan = *_vm->_eventMan;
evtMan.showMouse();
- if (leaderHandObject != Thing::_none)
+ if (leaderHandObject != _vm->_thingNone)
getObjectRemovedFromLeaderHand();
- if (slotThing != Thing::_none) {
+ if (slotThing != _vm->_thingNone) {
getObjectRemovedFromSlot(champIndex, slotIndex);
putObjectInLeaderHand(slotThing, false);
}
- if (leaderHandObject != Thing::_none)
+ if (leaderHandObject != _vm->_thingNone)
addObjectInSlot((ChampionIndex)champIndex, leaderHandObject, (ChampionSlot)slotIndex);
drawChampionState((ChampionIndex)champIndex);
@@ -1509,7 +1515,7 @@ void ChampionMan::championKill(uint16 champIndex) {
dropAllObjects(champIndex);
Thing unusedThing = dungeon.getUnusedThing(kDMMaskChampionBones | kDMThingTypeJunk);
uint16 curCell = 0;
- if (unusedThing != Thing::_none) {
+ if (unusedThing != _vm->_thingNone) {
Junk *L0966_ps_Junk = (Junk *)dungeon.getThingData(unusedThing);
L0966_ps_Junk->setType(kDMJunkTypeBones);
L0966_ps_Junk->setDoNotDiscard(true);
@@ -1592,7 +1598,7 @@ void ChampionMan::dropAllObjects(uint16 champIndex) {
DungeonMan &dungeon = *_vm->_dungeonMan;
for (uint16 slotIndex = kDMSlotReadyHand; slotIndex < kDMSlotChest1; slotIndex++) {
Thing curThing = getObjectRemovedFromSlot(champIndex, slotDropOrder[slotIndex]);
- if (curThing != Thing::_none)
+ if (curThing != _vm->_thingNone)
_vm->_moveSens->getMoveResult(_vm->thingWithNewCell(curThing, curCell), kDMMapXNotOnASquare, 0, dungeon._partyMapX, dungeon._partyMapY);
}
}
@@ -1875,7 +1881,7 @@ void ChampionMan::resetDataToStartGame() {
Thing handThing = _leaderHandObject;
EventManager &evtMan = *_vm->_eventMan;
- if (handThing == Thing::_none) {
+ if (handThing == _vm->_thingNone) {
_leaderEmptyHanded = true;
_leaderHandObjectIconIndex = kDMIconIndiceNone;
evtMan.setMousePointer();
@@ -1903,7 +1909,7 @@ void ChampionMan::resetDataToStartGame() {
return;
}
- _leaderHandObject = Thing::_none;
+ _leaderHandObject = _vm->_thingNone;
_leaderHandObjectIconIndex = kDMIconIndiceNone;
_leaderEmptyHanded = true;
}
@@ -1938,7 +1944,7 @@ void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
championPtr->_food = 1500 + _vm->getRandomNumber(256);
championPtr->_water = 1500 + _vm->getRandomNumber(256);
for (int16 slotIdx = kDMSlotReadyHand; slotIdx < kDMSlotChest1; slotIdx++)
- championPtr->_slots[slotIdx] = Thing::_none;
+ championPtr->_slots[slotIdx] = _vm->_thingNone;
Thing curThing = dungeon.getSquareFirstThing(dungeon._partyMapX, dungeon._partyMapY);
while (curThing.getType() != kDMstringTypeText)
@@ -2012,7 +2018,7 @@ void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
curMapX += _vm->_dirIntoStepCountEast[dungeon._partyDir], curMapY += _vm->_dirIntoStepCountNorth[dungeon._partyDir];
curThing = dungeon.getSquareFirstThing(curMapX, curMapY);
int16 slotIdx = kDMSlotBackpackLine1_1;
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
ThingType thingType = curThing.getType();
if ((thingType > kDMThingTypeSensor) && (curThing.getCell() == championObjectsCell)) {
int16 objectAllowedSlots = dungeon._objectInfos[dungeon.getObjectInfoIndex(curThing)]._allowedSlots;
@@ -2030,7 +2036,7 @@ void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
if (skipCheck)
break;
- if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == Thing::_none))
+ if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == _vm->_thingNone))
curSlotIndex = kDMSlotNeck;
else
curSlotIndex = slotIdx++;
@@ -2038,27 +2044,27 @@ void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
break;
}
case kDMThingTypeWeapon:
- if (championPtr->_slots[kDMSlotActionHand] == Thing::_none)
+ if (championPtr->_slots[kDMSlotActionHand] == _vm->_thingNone)
curSlotIndex = kDMSlotActionHand;
- else if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == Thing::_none))
+ else if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == _vm->_thingNone))
curSlotIndex = kDMSlotNeck;
else
curSlotIndex = slotIdx++;
break;
case kDMThingTypeScroll:
case kDMThingTypePotion:
- if (championPtr->_slots[kDMSlotPouch1] == Thing::_none)
+ if (championPtr->_slots[kDMSlotPouch1] == _vm->_thingNone)
curSlotIndex = kDMSlotPouch1;
- else if (championPtr->_slots[kDMSlotPouch_2] == Thing::_none)
+ else if (championPtr->_slots[kDMSlotPouch_2] == _vm->_thingNone)
curSlotIndex = kDMSlotPouch_2;
- else if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == Thing::_none))
+ else if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == _vm->_thingNone))
curSlotIndex = kDMSlotNeck;
else
curSlotIndex = slotIdx++;
break;
case kDMThingTypeContainer:
case kDMThingTypeJunk:
- if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == Thing::_none))
+ if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == _vm->_thingNone))
curSlotIndex = kDMSlotNeck;
else
curSlotIndex = slotIdx++;
@@ -2068,8 +2074,8 @@ void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
break;
}
- while (championPtr->_slots[curSlotIndex] != Thing::_none) {
- if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == Thing::_none))
+ while (championPtr->_slots[curSlotIndex] != _vm->_thingNone) {
+ if ((objectAllowedSlots & _slotMasks[kDMSlotNeck]) && (championPtr->_slots[kDMSlotNeck] == _vm->_thingNone))
curSlotIndex = kDMSlotNeck;
else
curSlotIndex = slotIdx++;
@@ -2395,7 +2401,7 @@ void ChampionMan::drawSlot(uint16 champIndex, int16 slotIndex) {
evtMan.hideMouse();
int16 iconIndex;
- if (thing == Thing::_none) {
+ if (thing == _vm->_thingNone) {
if (slotIndex <= kDMSlotFeet) {
iconIndex = kDMIconIndiceReadyHand + (slotIndex << 1);
if (champ->getWoundsFlag((ChampionWound)(1 << slotIndex))) {
diff --git a/engines/dm/champion.h b/engines/dm/champion.h
index ffcd7abc42..60c45a8825 100644
--- a/engines/dm/champion.h
+++ b/engines/dm/champion.h
@@ -397,6 +397,9 @@ public:
}; // @ SKILL
class Champion {
+private:
+ DMEngine *_vm;
+
public:
uint16 _attributes;
uint16 _wounds;
@@ -428,6 +431,9 @@ public:
int16 _shieldDefense;
byte _portrait[928]; // 32 x 29 pixel portrait
+ Champion() {}
+ void setVm(DMEngine *vm) { _vm = vm; }
+
Thing &getSlot(ChampionSlot slot) { return _slots[slot]; }
void setSlot(ChampionSlot slot, Thing val) { _slots[slot] = val; }
@@ -487,7 +493,7 @@ class ChampionMan {
public:
- Champion _champions[4]; // @ K0071_as_Champions
+ Champion *_champions; // @ K0071_as_Champions
uint16 _partyChampionCount; // @ G0305_ui_PartyChampionCount
bool _partyDead; // @ G0303_B_PartyDead
Thing _leaderHandObject; // @ G0414_T_LeaderHandObject
@@ -502,6 +508,8 @@ public:
bool _mousePointerHiddenToDrawChangedObjIconOnScreen; // @ G0420_B_MousePointerHiddenToDrawChangedObjectIconOnScreen
explicit ChampionMan(DMEngine *vm);
+ ~ChampionMan();
+
ChampionIndex getIndexInCell(int16 cell); // @ F0285_CHAMPION_GetIndexInCell
bool isLeaderHandObjectThrown(int16 side); // @ F0329_CHAMPION_IsLeaderHandObjectThrown
bool isObjectThrown(uint16 champIndex, int16 slotIndex, int16 side); // @ F0328_CHAMPION_IsObjectThrown
diff --git a/engines/dm/console.cpp b/engines/dm/console.cpp
index 978fadb750..c27d143ddd 100644
--- a/engines/dm/console.cpp
+++ b/engines/dm/console.cpp
@@ -150,7 +150,7 @@ bool Console::Cmd_pos(int argc, const char** argv) {
if (haventWarned.check())
debugPrintf("Setting position directly can cause glitches and crashes.\n");
debugPrintf("Position set to (%d, %d)\n", x, y);
- _vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY,
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY,
x - currMap._offsetMapX, y - currMap._offsetMapY);
} else
goto argumentError;
@@ -184,7 +184,7 @@ bool Console::Cmd_map(int argc, const char** argv) {
debugPrintf("Setting map directly can cause glitches and crashes.\n");
debugPrintf("Map set to %d\n", index);
- _vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
_vm->_newPartyMapIndex = _vm->_dungeonMan->getLocationAfterLevelChange(
_vm->_dungeonMan->_partyMapIndex, index - _vm->_dungeonMan->_partyMapIndex,
&_vm->_dungeonMan->_partyMapX, &_vm->_dungeonMan->_partyMapY);
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp
index 25d741f376..8fdb1c8d88 100644
--- a/engines/dm/dm.cpp
+++ b/engines/dm/dm.cpp
@@ -120,7 +120,14 @@ int16 DMEngine::getDistance(int16 mapx1, int16 mapy1, int16 mapx2, int16 mapy2)
return ABS(mapx1 - mapx2) + ABS(mapy1 - mapy2);
}
-DMEngine::DMEngine(OSystem *syst, const DMADGameDescription *desc) : Engine(syst), _console(nullptr), _gameVersion(desc) {
+DMEngine::DMEngine(OSystem *syst, const DMADGameDescription *desc) :
+ Engine(syst), _console(nullptr), _gameVersion(desc),
+ _thingNone(0), _thingEndOfList(0xFFFE), _thingFirstExplosion(0xFF80),
+ _thingExplFireBall(0xFF80), _thingExplSlime(0xFF81), _thingExplLightningBolt(0xFF82),
+ _thingExplHarmNonMaterial(0xFF83), _thingExplOpenDoor(0xFF84), _thingExplPoisonBolt(0xFF86),
+ _thingExplPoisonCloud(0xFF87), _thingExplSmoke(0xFFA8), _thingExplFluxcage(0xFFB2),
+ _thingExplRebirthStep1(0xFFE4), _thingExplRebirthStep2(0xFFE5), _thingParty(0xFFFF)
+ {
// register random source
_rnd = new Common::RandomSource("dm");
@@ -280,7 +287,7 @@ void DMEngine::initializeGame() {
startGame();
if (_gameMode != kDMModeLoadSavedGame)
- _moveSens->getMoveResult(Thing::_party, kDMMapXNotOnASquare, 0, _dungeonMan->_partyMapX, _dungeonMan->_partyMapY);
+ _moveSens->getMoveResult(_thingParty, kDMMapXNotOnASquare, 0, _dungeonMan->_partyMapX, _dungeonMan->_partyMapY);
_eventMan->showMouse();
_eventMan->discardAllInput();
}
@@ -413,7 +420,7 @@ void DMEngine::gameloop() {
if (_newPartyMapIndex != kDMMapIndexNone) {
processNewPartyMap(_newPartyMapIndex);
- _moveSens->getMoveResult(Thing::_party, kDMMapXNotOnASquare, 0, _dungeonMan->_partyMapX, _dungeonMan->_partyMapY);
+ _moveSens->getMoveResult(_thingParty, kDMMapXNotOnASquare, 0, _dungeonMan->_partyMapX, _dungeonMan->_partyMapY);
_newPartyMapIndex = kDMMapIndexNone;
_eventMan->discardAllInput();
}
@@ -928,12 +935,12 @@ void DMEngine::fuseSequence() {
for (;;) {
Thing curThing = _dungeonMan->getSquareFirstObject(fluxCageMapX, fluxcageMapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _thingEndOfList) {
if (curThing.getType() == kDMThingTypeExplosion) {
Explosion *curExplosion = (Explosion*)_dungeonMan->getThingData(curThing);
if (curExplosion->getType() == kDMExplosionTypeFluxcage) {
_dungeonMan->unlinkThingFromList(curThing, Thing(0), fluxCageMapX, fluxcageMapY);
- curExplosion->setNextThing(Thing::_none);
+ curExplosion->setNextThing(_thingNone);
continue;
}
}
@@ -948,14 +955,14 @@ void DMEngine::fuseSequence() {
}
fuseSequenceUpdate();
for (int16 attackId = 55; attackId <= 255; attackId += 40) {
- _projexpl->createExplosion(Thing::_explFireBall, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
+ _projexpl->createExplosion(_thingExplFireBall, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
fuseSequenceUpdate();
}
_sound->requestPlay(kDMSoundIndexBuzz, lordChaosMapX, lordChaosMapY, kDMSoundModePlayIfPrioritized);
lordGroup->_type = kDMCreatureTypeLordOrder;
fuseSequenceUpdate();
for (int16 attackId = 55; attackId <= 255; attackId += 40) {
- _projexpl->createExplosion(Thing::_explHarmNonMaterial, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
+ _projexpl->createExplosion(_thingExplHarmNonMaterial, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
fuseSequenceUpdate();
}
for (int16 cycleCount = 3; cycleCount > 0; cycleCount--) {
@@ -966,8 +973,8 @@ void DMEngine::fuseSequence() {
fuseSequenceUpdate();
}
}
- _projexpl->createExplosion(Thing::_explFireBall, 255, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
- _projexpl->createExplosion(Thing::_explHarmNonMaterial, 255, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
+ _projexpl->createExplosion(_thingExplFireBall, 255, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
+ _projexpl->createExplosion(_thingExplHarmNonMaterial, 255, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
fuseSequenceUpdate();
lordGroup->_type = kDMCreatureTypeGreyLord;
fuseSequenceUpdate();
@@ -976,7 +983,7 @@ void DMEngine::fuseSequence() {
for (int16 curMapX = 0; curMapX < _dungeonMan->_currMapWidth; curMapX++) {
for (int curMapY = 0; curMapY < _dungeonMan->_currMapHeight; curMapY++) {
Thing curThing = _groupMan->groupGetThing(curMapX, curMapY);
- if ((curThing != Thing::_endOfList) && ((curMapX != lordChaosMapX) || (curMapY != lordChaosMapY))) {
+ if ((curThing != _thingEndOfList) && ((curMapX != lordChaosMapX) || (curMapY != lordChaosMapY))) {
_groupMan->groupDelete(curMapX, curMapY);
}
}
@@ -986,7 +993,7 @@ void DMEngine::fuseSequence() {
Thing curThing = _dungeonMan->getSquareFirstThing(0, 0);
int16 textStringThingCount = 0;
Thing textStringThings[8];
- while (curThing != Thing::_endOfList) {
+ while (curThing != _thingEndOfList) {
if (curThing.getType() == kDMstringTypeText)
textStringThings[textStringThingCount++] = curThing;
@@ -1011,7 +1018,7 @@ void DMEngine::fuseSequence() {
}
for (int16 attackId = 55; attackId <= 255; attackId += 40) {
- _projexpl->createExplosion(Thing::_explHarmNonMaterial, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
+ _projexpl->createExplosion(_thingExplHarmNonMaterial, attackId, lordChaosMapX, lordChaosMapY, kDMCreatureTypeSingleCenteredCreature);
fuseSequenceUpdate();
}
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index 9056a744fb..16307778ba 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -167,21 +167,6 @@ struct DMADGameDescription {
class Thing {
public:
uint16 _data;
- static const Thing _none; // @ C0xFFFF_THING_NONE
- static const Thing _endOfList; // @ C0xFFFE_THING_ENDOFLIST
- static const Thing _firstExplosion; // @ C0xFF80_THING_FIRST_EXPLOSION
- static const Thing _explFireBall; // @ C0xFF80_THING_EXPLOSION_FIREBALL
- static const Thing _explSlime; // @ C0xFF81_THING_EXPLOSION_SLIME
- static const Thing _explLightningBolt; // @ C0xFF82_THING_EXPLOSION_LIGHTNING_BOLT
- static const Thing _explHarmNonMaterial; // @ C0xFF83_THING_EXPLOSION_HARM_NON_MATERIAL
- static const Thing _explOpenDoor; // @ C0xFF84_THING_EXPLOSION_OPEN_DOOR
- static const Thing _explPoisonBolt; // @ C0xFF86_THING_EXPLOSION_POISON_BOLT
- static const Thing _explPoisonCloud; // @ C0xFF87_THING_EXPLOSION_POISON_CLOUD
- static const Thing _explSmoke; // @ C0xFFA8_THING_EXPLOSION_SMOKE
- static const Thing _explFluxcage; // @ C0xFFB2_THING_EXPLOSION_FLUXCAGE
- static const Thing _explRebirthStep1; // @ C0xFFE4_THING_EXPLOSION_REBIRTH_STEP1
- static const Thing _explRebirthStep2; // @ C0xFFE5_THING_EXPLOSION_REBIRTH_STEP2
- static const Thing _party; // @ C0xFFFF_THING_PARTY
Thing() : _data(0) {}
Thing(const Thing &other) { set(other._data); }
@@ -329,6 +314,22 @@ public:
int32 _gameTime; // @ G0313_ul_GameTime
char _stringBuildBuffer[128]; // @ G0353_ac_StringBuildBuffer
int16 _waitForInputMaxVerticalBlankCount; // @ G0318_i_WaitForInputMaximumVerticalBlankCount
+
+ Thing _thingNone; // @ C0xFFFF_THING_NONE
+ Thing _thingEndOfList; // @ C0xFFFE_THING_ENDOFLIST
+ Thing _thingFirstExplosion; // @ C0xFF80_THING_FIRST_EXPLOSION
+ Thing _thingExplFireBall; // @ C0xFF80_THING_EXPLOSION_FIREBALL
+ Thing _thingExplSlime; // @ C0xFF81_THING_EXPLOSION_SLIME
+ Thing _thingExplLightningBolt; // @ C0xFF82_THING_EXPLOSION_LIGHTNING_BOLT
+ Thing _thingExplHarmNonMaterial; // @ C0xFF83_THING_EXPLOSION_HARM_NON_MATERIAL
+ Thing _thingExplOpenDoor; // @ C0xFF84_THING_EXPLOSION_OPEN_DOOR
+ Thing _thingExplPoisonBolt; // @ C0xFF86_THING_EXPLOSION_POISON_BOLT
+ Thing _thingExplPoisonCloud; // @ C0xFF87_THING_EXPLOSION_POISON_CLOUD
+ Thing _thingExplSmoke; // @ C0xFFA8_THING_EXPLOSION_SMOKE
+ Thing _thingExplFluxcage; // @ C0xFFB2_THING_EXPLOSION_FLUXCAGE
+ Thing _thingExplRebirthStep1; // @ C0xFFE4_THING_EXPLOSION_REBIRTH_STEP1
+ Thing _thingExplRebirthStep2; // @ C0xFFE5_THING_EXPLOSION_REBIRTH_STEP2
+ Thing _thingParty; // @ C0xFFFF_THING_PARTY
};
bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header);
diff --git a/engines/dm/dungeonman.cpp b/engines/dm/dungeonman.cpp
index 618c61a307..2d0d65f2a4 100644
--- a/engines/dm/dungeonman.cpp
+++ b/engines/dm/dungeonman.cpp
@@ -543,22 +543,6 @@ void DungeonMan::decompressDungeonFile() {
f.close();
}
-const Thing Thing::_none(0); // @ C0xFFFF_THING_NONE
-const Thing Thing::_endOfList(0xFFFE); // @ C0xFFFE_THING_ENDOFLIST
-const Thing Thing::_firstExplosion(0xFF80); // @ C0xFF80_THING_FIRST_EXPLOSION
-const Thing Thing::_explFireBall(0xFF80); // @ C0xFF80_THING_EXPLOSION_FIREBALL
-const Thing Thing::_explSlime(0xFF81); // @ C0xFF81_THING_EXPLOSION_SLIME
-const Thing Thing::_explLightningBolt(0xFF82); // @ C0xFF82_THING_EXPLOSION_LIGHTNING_BOLT
-const Thing Thing::_explHarmNonMaterial(0xFF83); // @ C0xFF83_THING_EXPLOSION_HARM_NON_MATERIAL
-const Thing Thing::_explOpenDoor(0xFF84); // @ C0xFF84_THING_EXPLOSION_OPEN_DOOR
-const Thing Thing::_explPoisonBolt(0xFF86); // @ C0xFF86_THING_EXPLOSION_POISON_BOLT
-const Thing Thing::_explPoisonCloud(0xFF87); // @ C0xFF87_THING_EXPLOSION_POISON_CLOUD
-const Thing Thing::_explSmoke(0xFFA8); // @ C0xFFA8_THING_EXPLOSION_SMOKE
-const Thing Thing::_explFluxcage(0xFFB2); // @ C0xFFB2_THING_EXPLOSION_FLUXCAGE
-const Thing Thing::_explRebirthStep1(0xFFE4); // @ C0xFFE4_THING_EXPLOSION_REBIRTH_STEP1
-const Thing Thing::_explRebirthStep2(0xFFE5); // @ C0xFFE5_THING_EXPLOSION_REBIRTH_STEP2
-const Thing Thing::_party(0xFFFF); // @ C0xFFFF_THING_PARTY
-
void DungeonMan::loadDungeonFile(Common::InSaveFile *file) {
static const byte additionalThingCounts[16] = { // @ G0236_auc_Graphic559_AdditionalThingCounts{
0, /* Door */
@@ -685,7 +669,7 @@ void DungeonMan::loadDungeonFile(Common::InSaveFile *file) {
if (_vm->_gameMode != kDMModeLoadSavedGame) {
for (uint16 i = 0; i < 300; ++i)
- _squareFirstThings[actualSquareFirstThingCount + i] = Thing::_none;
+ _squareFirstThings[actualSquareFirstThingCount + i] = _vm->_thingNone;
}
// load text data
@@ -739,7 +723,7 @@ void DungeonMan::loadDungeonFile(Common::InSaveFile *file) {
timeline._eventMaxCount += _dungeonFileHeader._thingCounts[thingType];
for (uint16 i = 0; i < additionalThingCounts[thingType]; ++i)
- (_thingData[thingType] + (thingCount + i) * thingStoreWordCount)[0] = Thing::_none.toUint16();
+ (_thingData[thingType] + (thingCount + i) * thingStoreWordCount)[0] = _vm->_thingNone.toUint16();
}
}
@@ -864,7 +848,7 @@ int16 DungeonMan::getSquareFirstThingIndex(int16 mapX, int16 mapY) {
Thing DungeonMan::getSquareFirstThing(int16 mapX, int16 mapY) {
int16 index = getSquareFirstThingIndex(mapX, mapY);
if (index == -1)
- return Thing::_endOfList;
+ return _vm->_thingEndOfList;
return _squareFirstThings[index];
}
@@ -918,7 +902,7 @@ void DungeonMan::setSquareAspect(uint16 *aspectArray, Direction dir, int16 mapX,
squareIsFakeWall = false;
T0172010_ClosedFakeWall:
setSquareAspectOrnOrdinals(aspectArray, leftRandomWallOrnamentAllowed, frontRandomWallOrnamentAllowed, rightRandomWallOrnamentAllowed, dir, mapX, mapY, squareIsFakeWall);
- while ((curThing != Thing::_endOfList) && (curThing.getType() <= kDMThingTypeSensor)) {
+ while ((curThing != _vm->_thingEndOfList) && (curThing.getType() <= kDMThingTypeSensor)) {
ThingType curThingType = curThing.getType();
int16 AL0310_i_SideIndex = _vm->normalizeModulo4(curThing.getCell() - dir);
if (AL0310_i_SideIndex) { /* Invisible on the back wall if 0 */
@@ -938,7 +922,7 @@ T0172010_ClosedFakeWall:
curThing = getNextThing(curThing);
}
if (squareIsFakeWall && (_partyMapX != mapX) && (_partyMapY != mapY)) {
- aspectArray[kDMSquareAspectFirstGroupOrObject] = Thing::_endOfList.toUint16();
+ aspectArray[kDMSquareAspectFirstGroupOrObject] = _vm->_thingEndOfList.toUint16();
return;
}
break;
@@ -971,7 +955,7 @@ T0172010_ClosedFakeWall:
AL0307_uc_FootprintsAllowed = true;
}
- while ((curThing != Thing::_endOfList) && (curThing.getType() <= kDMThingTypeSensor)) {
+ while ((curThing != _vm->_thingEndOfList) && (curThing.getType() <= kDMThingTypeSensor)) {
if (curThing.getType() == kDMThingTypeSensor) {
Sensor *curSensor = (Sensor *)getThingData(curThing);
aspectArray[kDMSquareAspectFloorOrn] = curSensor->getAttrOrnOrdinal();
@@ -988,7 +972,7 @@ T0172010_ClosedFakeWall:
aspectArray[kDMSquareAspectElement] = (bool((getFlag(AL0307_uc_Square, kDMSquareMaskStairsNorthSouth) >> 3)) == _vm->isOrientedWestEast(dir)) ? kDMElementTypeStairsSide : kDMElementTypeStairsFront;
aspectArray[kDMSquareAspectStairsUp] = getFlag(AL0307_uc_Square, kDMSquareMaskStairsUp);
AL0307_uc_FootprintsAllowed = false;
- while ((curThing != Thing::_endOfList) && (curThing.getType() <= kDMThingTypeSensor))
+ while ((curThing != _vm->_thingEndOfList) && (curThing.getType() <= kDMThingTypeSensor))
curThing = getNextThing(curThing);
break;
case kDMElementTypeDoor:
@@ -1001,7 +985,7 @@ T0172010_ClosedFakeWall:
}
AL0307_uc_FootprintsAllowed = true;
- while ((curThing != Thing::_endOfList) && (curThing.getType() <= kDMThingTypeSensor))
+ while ((curThing != _vm->_thingEndOfList) && (curThing.getType() <= kDMThingTypeSensor))
curThing = getNextThing(curThing);
AL0307_uc_ScentOrdinal = championMan.getScentOrdinal(mapX, mapY);
@@ -1219,7 +1203,7 @@ Thing DungeonMan::getUnusedThing(uint16 thingType) {
Thing curThing;
for (;;) { /*_Infinite loop_*/
- if (*thingPtr == Thing::_none) { /* If thing data is unused */
+ if (*thingPtr == _vm->_thingNone) { /* If thing data is unused */
curThing = Thing((thingType << 10) | (thingCount - thingIdx));
break;
}
@@ -1227,8 +1211,8 @@ Thing DungeonMan::getUnusedThing(uint16 thingType) {
thingPtr += thingDataByteCount; /* Proceed to the next thing data */
} else {
curThing = getDiscardThing(thingType);
- if (curThing == Thing::_none)
- return Thing::_none;
+ if (curThing == _vm->_thingNone)
+ return _vm->_thingNone;
thingPtr = (Thing *)getThingData(curThing);
break;
@@ -1236,7 +1220,7 @@ Thing DungeonMan::getUnusedThing(uint16 thingType) {
}
memset(thingPtr, 0, thingDataByteCount * 2);
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
return curThing;
}
@@ -1266,11 +1250,11 @@ uint16 DungeonMan::getObjectWeight(Thing thing) {
2, 0, 8
};
- if (thing == Thing::_none)
+ if (thing == _vm->_thingNone)
return 0;
// Initialization is not present in original
- // Set to 0 by default as it's the default value used for Thing::_none
+ // Set to 0 by default as it's the default value used for _vm->_none
uint16 weight = 0;
Junk *junk = (Junk *)getThingData(thing);
@@ -1290,7 +1274,7 @@ uint16 DungeonMan::getObjectWeight(Thing thing) {
case kDMThingTypeContainer:
weight = 50;
thing = ((Container *)junk)->getSlot();
- while (thing != Thing::_endOfList) {
+ while (thing != _vm->_thingEndOfList) {
weight += getObjectWeight(thing);
thing = getNextThing(thing);
}
@@ -1332,11 +1316,11 @@ int16 DungeonMan::getObjectInfoIndex(Thing thing) {
}
void DungeonMan::linkThingToList(Thing thingToLink, Thing thingInList, int16 mapX, int16 mapY) {
- if (thingToLink == Thing::_endOfList)
+ if (thingToLink == _vm->_thingEndOfList)
return;
Thing *thingPtr = (Thing *)getThingData(thingToLink);
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
/* If mapX >= 0 then the thing is linked to the list of things on the specified square else it is linked at the end of the specified thing list */
if (mapX >= 0) {
byte *currSquare = &_currMapData[mapX][mapY];
@@ -1366,7 +1350,7 @@ void DungeonMan::linkThingToList(Thing thingToLink, Thing thingInList, int16 map
}
}
Thing nextThing = getNextThing(thingInList);
- while (nextThing != Thing::_endOfList)
+ while (nextThing != _vm->_thingEndOfList)
nextThing = getNextThing(thingInList = nextThing);
thingPtr = (Thing *)getThingData(thingInList);
@@ -1381,13 +1365,13 @@ WeaponInfo *DungeonMan::getWeaponInfo(Thing thing) {
int16 DungeonMan::getProjectileAspect(Thing thing) {
ThingType thingType = thing.getType();
if (thingType == kDMThingTypeExplosion) {
- if (thing == Thing::_explFireBall)
+ if (thing == _vm->_thingExplFireBall)
return -_vm->indexToOrdinal(k10_ProjectileAspectExplosionFireBall);
- if (thing == Thing::_explSlime)
+ if (thing == _vm->_thingExplSlime)
return -_vm->indexToOrdinal(k12_ProjectileAspectExplosionSlime);
- if (thing == Thing::_explLightningBolt)
+ if (thing == _vm->_thingExplLightningBolt)
return -_vm->indexToOrdinal(k3_ProjectileAspectExplosionLightningBolt);
- if ((thing == Thing::_explPoisonBolt) || (thing == Thing::_explPoisonCloud))
+ if ((thing == _vm->_thingExplPoisonBolt) || (thing == _vm->_thingExplPoisonCloud))
return -_vm->indexToOrdinal(k13_ProjectileAspectExplosionPoisonBoltCloud);
return -_vm->indexToOrdinal(k11_ProjectileAspectExplosionDefault);
@@ -1426,7 +1410,7 @@ int16 DungeonMan::getLocationAfterLevelChange(int16 mapIndex, int16 levelDelta,
Thing DungeonMan::getSquareFirstObject(int16 mapX, int16 mapY) {
Thing thing = getSquareFirstThing(mapX, mapY);
- while ((thing != Thing::_endOfList) && (thing.getType() < kDMThingTypeGroup))
+ while ((thing != _vm->_thingEndOfList) && (thing.getType() < kDMThingTypeGroup))
thing = getNextThing(thing);
return thing;
@@ -1445,7 +1429,7 @@ Thing DungeonMan::getDiscardThing(uint16 thingType) {
static unsigned char lastDiscardedThingMapIndex[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (thingType == kDMThingTypeExplosion)
- return Thing::_none;
+ return _vm->_thingNone;
GroupMan &groupMan = *_vm->_groupMan;
ProjExpl &projExpl = *_vm->_projexpl;
@@ -1525,13 +1509,13 @@ Thing DungeonMan::getDiscardThing(uint16 thingType) {
lastDiscardedThingMapIndex[thingType] = mapIndex;
return Thing(squareThing.getTypeAndIndex());
}
- } while ((squareThing = getNextThing(squareThing)) != Thing::_endOfList);
+ } while ((squareThing = getNextThing(squareThing)) != _vm->_thingEndOfList);
}
}
}
if ((mapIndex == _partyMapIndex) || (_dungeonFileHeader._mapCount <= 1)) {
lastDiscardedThingMapIndex[thingType] = mapIndex;
- return Thing::_none;
+ return _vm->_thingNone;
}
do {
@@ -1575,7 +1559,7 @@ bool DungeonMan::isCreatureAllowedOnMap(Thing thing, uint16 mapIndex) {
}
void DungeonMan::unlinkThingFromList(Thing thingToUnlink, Thing thingInList, int16 mapX, int16 mapY) {
- if (thingToUnlink == Thing::_endOfList)
+ if (thingToUnlink == _vm->_thingEndOfList)
return;
uint16 tmp = thingToUnlink.toUint16();
@@ -1587,24 +1571,24 @@ void DungeonMan::unlinkThingFromList(Thing thingToUnlink, Thing thingInList, int
thingPtr = (Thing *)getThingData(thingToUnlink);
uint16 firstThingIndex = getSquareFirstThingIndex(mapX, mapY);
Thing *currThing = &_squareFirstThings[firstThingIndex]; /* BUG0_01 Coding error without consequence. The engine does not check that there are things at the specified square coordinates. f160_getSquareFirstThingIndex would return -1 for an empty square. No consequence as the function is never called with the coordinates of an empty square (except in the case of BUG0_59) */
- if ((*thingPtr == Thing::_endOfList) && (((Thing *)currThing)->getTypeAndIndex() == thingToUnlink.toUint16())) { /* If the thing to unlink is the last thing on the square */
+ if ((*thingPtr == _vm->_thingEndOfList) && (((Thing *)currThing)->getTypeAndIndex() == thingToUnlink.toUint16())) { /* If the thing to unlink is the last thing on the square */
clearFlag(_currMapData[mapX][mapY], kDMSquareMaskThingListPresent);
uint16 squareFirstThingIdx = _dungeonFileHeader._squareFirstThingCount - 1;
for (uint16 i = 0; i < squareFirstThingIdx - firstThingIndex; ++i)
currThing[i] = currThing[i + 1];
- _squareFirstThings[squareFirstThingIdx] = Thing::_none;
+ _squareFirstThings[squareFirstThingIdx] = _vm->_thingNone;
uint16 *cumulativeFirstThingCount = _currMapColCumulativeSquareFirstThingCount + mapX + 1;
uint16 currColumn = _dungeonColumCount - (_dungeonMapsFirstColumnIndex[_currMapIndex] + mapX) - 1;
while (currColumn--) { /* For each column starting from and after the column containing the square where the thing is unlinked */
(*cumulativeFirstThingCount++)--; /* Decrement the cumulative first thing count */
}
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
return;
}
if (((Thing *)currThing)->getTypeAndIndex() == thingToUnlink.toUint16()) {
*currThing = *thingPtr;
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
return;
}
thingInList = *currThing;
@@ -1612,9 +1596,9 @@ void DungeonMan::unlinkThingFromList(Thing thingToUnlink, Thing thingInList, int
Thing currThing = getNextThing(thingInList);
while (currThing.getTypeAndIndex() != thingToUnlink.toUint16()) {
- if ((currThing == Thing::_endOfList) || (currThing == Thing::_none)) {
+ if ((currThing == _vm->_thingEndOfList) || (currThing == _vm->_thingNone)) {
if (thingPtr)
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
return;
}
currThing = getNextThing(thingInList = currThing);
@@ -1622,7 +1606,7 @@ void DungeonMan::unlinkThingFromList(Thing thingToUnlink, Thing thingInList, int
thingPtr = (Thing *)getThingData(thingInList);
*thingPtr = getNextThing(currThing);
thingPtr = (Thing *)getThingData(thingToUnlink);
- *thingPtr = Thing::_endOfList;
+ *thingPtr = _vm->_thingEndOfList;
}
int16 DungeonMan::getStairsExitDirection(int16 mapX, int16 mapY) {
@@ -1678,12 +1662,12 @@ Thing DungeonMan::getObjForProjectileLaucherOrObjGen(uint16 iconIndex) {
junkType = kDMWeaponTorch;
break;
default:
- return Thing::_none;
+ return _vm->_thingNone;
}
Thing unusedThing = getUnusedThing(thingType);
- if (unusedThing == Thing::_none)
- return Thing::_none;
+ if (unusedThing == _vm->_thingNone)
+ return _vm->_thingNone;
Junk *junkPtr = (Junk *)getThingData(unusedThing);
junkPtr->setType(junkType); /* Also works for WEAPON in cases other than Boulder */
diff --git a/engines/dm/eventman.cpp b/engines/dm/eventman.cpp
index 43f9bd8efc..622a7d5e1f 100644
--- a/engines/dm/eventman.cpp
+++ b/engines/dm/eventman.cpp
@@ -948,9 +948,9 @@ void EventManager::commandTurnParty(CommandType cmdType) {
return;
}
- _vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, Thing::_party, true, false);
+ _vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, _vm->_thingParty, true, false);
_vm->_championMan->setPartyDirection(_vm->normalizeModulo4(_vm->_dungeonMan->_partyDir + ((cmdType == kDMCommandTurnRight) ? 1 : 3)));
- _vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, Thing::_party, true, true);
+ _vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, _vm->_thingParty, true, true);
}
void EventManager::commandMoveParty(CommandType cmdType) {
@@ -1005,7 +1005,7 @@ void EventManager::commandMoveParty(CommandType cmdType) {
isMovementBlocked = true;
break;
case kDMElementTypeStairs: {
- _vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
_vm->_dungeonMan->_partyMapX = partyMapX;
_vm->_dungeonMan->_partyMapY = partyMapY;
byte stairState = curSquare.toByte();
@@ -1038,7 +1038,7 @@ void EventManager::commandMoveParty(CommandType cmdType) {
if (damage)
_vm->_sound->requestPlay(kDMSoundIndexPartyDamaged, partyMapX, partyMapY, kDMSoundModePlayImmediately);
} else {
- isMovementBlocked = (_vm->_groupMan->groupGetThing(partyMapX, partyMapY) != Thing::_endOfList);
+ isMovementBlocked = (_vm->_groupMan->groupGetThing(partyMapX, partyMapY) != _vm->_thingEndOfList);
if (isMovementBlocked)
_vm->_groupMan->processEvents29to41(partyMapX, partyMapY, kDMEventTypeCreateReactionPartyIsAdjacent, 0);
}
@@ -1052,9 +1052,9 @@ void EventManager::commandMoveParty(CommandType cmdType) {
}
if (isStairsSquare)
- _vm->_moveSens->getMoveResult(Thing::_party, kDMMapXNotOnASquare, 0, partyMapX, partyMapY);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, kDMMapXNotOnASquare, 0, partyMapX, partyMapY);
else
- _vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, partyMapX, partyMapY);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, partyMapX, partyMapY);
uint16 disabledMovtTicks = 1;
championsPtr = _vm->_championMan->_champions;
@@ -1282,7 +1282,7 @@ void EventManager::commandProcessCommands160To162ClickInResurrectReincarnatePane
for (uint16 slotIndex = kDMSlotReadyHand; slotIndex < kDMSlotChest1; slotIndex++) {
Thing thing = champ->getSlot((ChampionSlot)slotIndex);
- if (thing != Thing::_none) {
+ if (thing != _vm->_thingNone) {
_vm->_dungeonMan->unlinkThingFromList(thing, Thing(0), mapX, mapY);
}
}
@@ -1371,7 +1371,7 @@ void EventManager::processType80_clickInDungeonView_grabLeaderHandObject(uint16
if (viewCell >= kDMViewCellBackRight) {
mapX += _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_partyDir], mapY += _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_partyDir];
Thing groupThing = _vm->_groupMan->groupGetThing(mapX, mapY);
- if ((groupThing != Thing::_endOfList) &&
+ if ((groupThing != _vm->_thingEndOfList) &&
!_vm->_moveSens->isLevitating(groupThing) &&
_vm->_groupMan->getCreatureOrdinalInCell((Group*)_vm->_dungeonMan->getThingData(groupThing), _vm->normalizeModulo4(viewCell + _vm->_dungeonMan->_partyDir))) {
return; /* It is not possible to grab an object on floor if there is a non levitating creature on its cell */
@@ -1454,7 +1454,7 @@ void EventManager::discardAllInput() {
}
void EventManager::commandTakeStairs(bool stairsGoDown) {
- _vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
_vm->_newPartyMapIndex = _vm->_dungeonMan->getLocationAfterLevelChange(_vm->_dungeonMan->_partyMapIndex, stairsGoDown ? -1 : 1, &_vm->_dungeonMan->_partyMapX, &_vm->_dungeonMan->_partyMapY);
_vm->_dungeonMan->setCurrentMap(_vm->_newPartyMapIndex);
_vm->_championMan->setPartyDirection(_vm->_dungeonMan->getStairsExitDirection(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY));
diff --git a/engines/dm/gfx.cpp b/engines/dm/gfx.cpp
index ccab619b50..caf6dc45c9 100644
--- a/engines/dm/gfx.cpp
+++ b/engines/dm/gfx.cpp
@@ -116,7 +116,7 @@ DisplayMan::DisplayMan(DMEngine *dmEngine) : _vm(dmEngine) {
for (int i = 0; i < 18; i++)
_currMapDoorOrnIndices[i] = 0;
- _inscriptionThing = Thing::_none;
+ _inscriptionThing = _vm->_thingNone;
_useByteBoxCoordinates = false;
_bitmapCeiling = nullptr;
@@ -3177,14 +3177,14 @@ void DisplayMan::drawObjectsCreaturesProjectilesExplosions(Thing thingParam, Dir
{276, 60} /* D0R */
};
- if (thingParam == Thing::_endOfList)
+ if (thingParam == _vm->_thingEndOfList)
return;
DungeonMan &dungeon = *_vm->_dungeonMan;
int16 orderedViewCellOrdinals = cellOrder;
Group *group = nullptr;
- Thing groupThing = Thing::_none;
+ Thing groupThing = _vm->_thingNone;
bool squareHasExplosion = drawCreaturesCompleted = false;
bool squareHasProjectile = false;
cellCounter = 0;
@@ -3351,14 +3351,14 @@ T0115015_DrawProjectileAsObject:
if (drawProjectileAsObject)
goto T0115171_BackFromT0115015_DrawProjectileAsObject;
}
- } while ((thingParam = dungeon.getNextThing(thingParam)) != Thing::_endOfList);
+ } while ((thingParam = dungeon.getNextThing(thingParam)) != _vm->_thingEndOfList);
if (AL_2_viewCell == kDMViewCellAlcove)
break; /* End of processing when drawing objects in an alcove */
if (viewSquareIndex < kDMViewSquareD3C)
break; /* End of processing if square is too far away at D4 */
/* Draw creatures */
drawingLastBackRowCell = ((AL_2_viewCell <= kDMViewCellFrontRight) || (cellCounter == 1)) && (!remainingViewCellOrdinalsToProcess || ((remainingViewCellOrdinalsToProcess & 0x0000000F) >= 3)); /* If (draw cell on the back row or second cell being processed) and (no more cells to draw or next cell to draw is a cell on the front row) */
- if ((groupThing == Thing::_none) || drawCreaturesCompleted)
+ if ((groupThing == _vm->_thingNone) || drawCreaturesCompleted)
goto T0115129_DrawProjectiles; /* Skip code to draw creatures */
ActiveGroup *activeGroup;
@@ -3733,7 +3733,7 @@ T0115129_DrawProjectiles:
}
}
T0115171_BackFromT0115015_DrawProjectileAsObject:;
- } while ((thingParam = dungeon.getNextThing(thingParam)) != Thing::_endOfList);
+ } while ((thingParam = dungeon.getNextThing(thingParam)) != _vm->_thingEndOfList);
} while (remainingViewCellOrdinalsToProcess);
/* Draw explosions */
@@ -3765,7 +3765,7 @@ T0115171_BackFromT0115015_DrawProjectileAsObject:;
AL_4_explosionAspectIndex = kDMExplosionAspectSmoke;
} else {
if (AL_4_explosionType == kDMExplosionTypeRebirthStep1) {
- objectAspect = (ObjectAspect *)&_projectileAspect[_vm->ordinalToIndex(-dungeon.getProjectileAspect(Thing::_explLightningBolt))];
+ objectAspect = (ObjectAspect *)&_projectileAspect[_vm->ordinalToIndex(-dungeon.getProjectileAspect(_vm->_thingExplLightningBolt))];
bitmapRedBanana = getNativeBitmapOrGraphic(((ProjectileAspect *)objectAspect)->_firstNativeBitmapRelativeIndex + (kDMGraphicIdxFirstProjectile + 1));
explosionCoordinates = rebirthStep1ExplosionCoordinates[AL_1_viewSquareExplosionIndex - 3];
byteWidth = getScaledDimension((((ProjectileAspect *)objectAspect)->_byteWidth), explosionCoordinates[2]);
@@ -3869,7 +3869,7 @@ T0115200_DrawExplosion:
blitToBitmap(bitmapRedBanana, _bitmapViewport, boxByteGreen, AL_4_xPos, 0, byteWidth, k112_byteWidthViewport, kDMColorFlesh, heightRedEagle, k136_heightViewport);
}
}
- } while ((thingParam = dungeon.getNextThing(thingParam))!= Thing::_endOfList);
+ } while ((thingParam = dungeon.getNextThing(thingParam))!= _vm->_thingEndOfList);
if ((fluxcageExplosion != 0) && (doorFrontViewDrawingPass != 1) && !_doNotDrawFluxcagesDuringEndgame) { /* Fluxcage is an explosion displayed as a field (like teleporters), above all other graphics */
AL_1_viewSquareExplosionIndex -= 3; /* Convert square index for explosions back to square index */
diff --git a/engines/dm/group.cpp b/engines/dm/group.cpp
index a72342da3d..8656d9fa2f 100644
--- a/engines/dm/group.cpp
+++ b/engines/dm/group.cpp
@@ -155,7 +155,7 @@ void GroupMan::dropGroupPossessions(int16 mapX, int16 mapY, Thing groupThing, So
}
Thing currentThing = group->_slot;
- if ((currentThing) != Thing::_endOfList) {
+ if ((currentThing) != _vm->_thingEndOfList) {
bool weaponDropped = false;
Thing nextThing;
do {
@@ -165,7 +165,7 @@ void GroupMan::dropGroupPossessions(int16 mapX, int16 mapY, Thing groupThing, So
weaponDropped = true;
}
_vm->_moveSens->getMoveResult(currentThing, kDMMapXNotOnASquare, 0, mapX, mapY);
- } while ((currentThing = nextThing) != Thing::_endOfList);
+ } while ((currentThing = nextThing) != _vm->_thingEndOfList);
if (soundMode != kDMSoundModeDoNotPlaySound)
_vm->_sound->requestPlay(weaponDropped ? kDMSoundIndexMetallicThud : kDMSoundIndexWoodenThudAttackTrolinAntmanStoneGolem, mapX, mapY, soundMode);
@@ -289,7 +289,7 @@ void GroupMan::dropCreatureFixedPossessions(CreatureType creatureType, int16 map
}
Thing nextUnusedThing = dungeon.getUnusedThing(currThingType);
- if ((nextUnusedThing) == Thing::_none)
+ if ((nextUnusedThing) == _vm->_thingNone)
continue;
Weapon *currWeapon = (Weapon *)dungeon.getThingData(nextUnusedThing);
@@ -390,7 +390,7 @@ Thing GroupMan::groupGetThing(int16 mapX, int16 mapY) {
DungeonMan &dungeon = *_vm->_dungeonMan;
Thing curThing = dungeon.getSquareFirstThing(mapX, mapY);
- while ((curThing != Thing::_endOfList) && (curThing.getType() != kDMThingTypeGroup))
+ while ((curThing != _vm->_thingEndOfList) && (curThing.getType() != kDMThingTypeGroup))
curThing = dungeon.getNextThing(curThing);
return curThing;
@@ -489,7 +489,7 @@ int16 GroupMan::groupGetDamageCreatureOutcome(Group *group, uint16 creatureIndex
else
attack = 255;
- _vm->_projexpl->createExplosion(Thing::_explSmoke, attack, mapX, mapY, cell); /* BUG0_66 Smoke is placed on the source map instead of the destination map when a creature dies by falling through a pit. The game has a special case to correctly drop the creature possessions on the destination map but there is no such special case for the smoke. Note that the death must be caused by the damage of the fall (there is no smoke if the creature is removed because its type is not allowed on the destination map). However this bug has no visible consequence because of BUG0_26: the smoke explosion falls in the pit right after being placed in the dungeon and before being drawn on screen so it is only visible on the destination square */
+ _vm->_projexpl->createExplosion(_vm->_thingExplSmoke, attack, mapX, mapY, cell); /* BUG0_66 Smoke is placed on the source map instead of the destination map when a creature dies by falling through a pit. The game has a special case to correctly drop the creature possessions on the destination map but there is no such special case for the smoke. Note that the death must be caused by the damage of the fall (there is no smoke if the creature is removed because its type is not allowed on the destination map). However this bug has no visible consequence because of BUG0_26: the smoke explosion falls in the pit right after being placed in the dungeon and before being drawn on screen so it is only visible on the destination square */
return retVal;
}
@@ -501,7 +501,7 @@ int16 GroupMan::groupGetDamageCreatureOutcome(Group *group, uint16 creatureIndex
void GroupMan::groupDelete(int16 mapX, int16 mapY) {
Thing groupThing = groupGetThing(mapX, mapY);
- if (groupThing == Thing::_endOfList)
+ if (groupThing == _vm->_thingEndOfList)
return;
DungeonMan &dungeon = *_vm->_dungeonMan;
@@ -510,7 +510,7 @@ void GroupMan::groupDelete(int16 mapX, int16 mapY) {
for (uint16 i = 0; i < 4; ++i)
group->_health[i] = 0;
_vm->_moveSens->getMoveResult(groupThing, mapX, mapY, kDMMapXNotOnASquare, 0);
- group->_nextThing = Thing::_none;
+ group->_nextThing = _vm->_thingNone;
if (dungeon._currMapIndex == dungeon._partyMapIndex) {
_activeGroups[group->getActiveGroupIndex()]._groupThingIndex = -1;
_currActiveGroupCount--;
@@ -608,7 +608,7 @@ void GroupMan::processEvents29to41(int16 eventMapX, int16 eventMapY, TimelineEve
Thing groupThing = groupGetThing(eventMapX, eventMapY);
/* If there is no creature at the location specified in the event then the event is ignored */
- if (groupThing == Thing::_endOfList)
+ if (groupThing == _vm->_thingEndOfList)
return;
ChampionMan &championMan = *_vm->_championMan;
@@ -1089,7 +1089,7 @@ T0209136:
bool GroupMan::isMovementPossible(CreatureInfo *creatureInfo, int16 mapX, int16 mapY, uint16 dir, bool allowMovementOverImaginaryPitsAndFakeWalls) {
_groupMovementTestedDirections[dir] = true;
- _groupMovementBlockedByGroupThing = Thing::_endOfList;
+ _groupMovementBlockedByGroupThing = _vm->_thingEndOfList;
_groupMovementBlockedByDoor = false;
_groupMovementBlockedByParty = false;
if (creatureInfo->_movementTicks == kDMMovementTicksImmobile)
@@ -1114,7 +1114,7 @@ bool GroupMan::isMovementPossible(CreatureInfo *creatureInfo, int16 mapX, int16
if (getFlag(creatureInfo->_attributes, kDMCreatureMaskArchenemy)) {
Thing curThing = dungeon.getSquareFirstThing(mapX, mapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if ((curThing).getType() == kDMThingTypeExplosion) {
Teleporter *curTeleporter = (Teleporter *)dungeon.getThingData(curThing);
if (((Explosion *)curTeleporter)->setType(kDMExplosionTypeFluxcage)) {
@@ -1148,7 +1148,7 @@ bool GroupMan::isMovementPossible(CreatureInfo *creatureInfo, int16 mapX, int16
}
_groupMovementBlockedByGroupThing = groupGetThing(mapX, mapY);
- return (_groupMovementBlockedByGroupThing == Thing::_endOfList);
+ return (_groupMovementBlockedByGroupThing == _vm->_thingEndOfList);
}
int16 GroupMan::getDistanceBetweenSquares(int16 srcMapX, int16 srcMapY, int16 destMapX, int16 destMapY) {
@@ -1475,47 +1475,47 @@ bool GroupMan::isCreatureAttacking(Group *group, int16 mapX, int16 mapY, uint16
targetCell += primaryDirectionToParty;
targetCell &= 0x0003;
if ((creatureInfo->getAttackRange() > 1) && ((_currGroupDistanceToParty > 1) || _vm->getRandomNumber(2))) {
- Thing projectileThing = Thing::_none;
+ Thing projectileThing = _vm->_thingNone;
switch (creatureType) {
case kDMCreatureTypeVexirk:
case kDMCreatureTypeLordChaos:
if (_vm->getRandomNumber(2)) {
- projectileThing = Thing::_explFireBall;
+ projectileThing = _vm->_thingExplFireBall;
} else {
switch (_vm->getRandomNumber(4)) {
case 0:
- projectileThing = Thing::_explHarmNonMaterial;
+ projectileThing = _vm->_thingExplHarmNonMaterial;
break;
case 1:
- projectileThing = Thing::_explLightningBolt;
+ projectileThing = _vm->_thingExplLightningBolt;
break;
case 2:
- projectileThing = Thing::_explPoisonCloud;
+ projectileThing = _vm->_thingExplPoisonCloud;
break;
case 3:
- projectileThing = Thing::_explOpenDoor;
+ projectileThing = _vm->_thingExplOpenDoor;
}
}
break;
case kDMCreatureTypeSwampSlime:
- projectileThing = Thing::_explSlime;
+ projectileThing = _vm->_thingExplSlime;
break;
case kDMCreatureTypeWizardEye:
if (_vm->getRandomNumber(8)) {
- projectileThing = Thing::_explLightningBolt;
+ projectileThing = _vm->_thingExplLightningBolt;
} else {
- projectileThing = Thing::_explOpenDoor;
+ projectileThing = _vm->_thingExplOpenDoor;
}
break;
case kDMCreatureTypeMaterializerZytaz:
if (_vm->getRandomNumber(2)) {
- projectileThing = Thing::_explPoisonCloud;
+ projectileThing = _vm->_thingExplPoisonCloud;
break;
}
case kDMCreatureTypeDemon:
case kDMCreatureTypeRedDragon:
- projectileThing = Thing::_explFireBall;
+ projectileThing = _vm->_thingExplFireBall;
break;
default:
break;
@@ -1594,14 +1594,14 @@ void GroupMan::stealFromChampion(Group *group, uint16 championIndex) {
stealFromSlotIndex += _vm->getRandomNumber(17); /* Select a random slot in the backpack */
Thing slotThing = champion->_slots[stealFromSlotIndex];
- if ((slotThing != Thing::_none)) {
+ if ((slotThing != _vm->_thingNone)) {
objectStolen = true;
slotThing = championMan.getObjectRemovedFromSlot(championIndex, stealFromSlotIndex);
- if (group->_slot == Thing::_endOfList) {
+ if (group->_slot == _vm->_thingEndOfList) {
group->_slot = slotThing;
/* BUG0_12 An object is cloned and appears at two different locations in the dungeon and/or inventory. The game may crash when interacting with this object. If a Giggler with no possessions steals an object that was previously in a chest and was not the last object in the chest then the objects that followed it are cloned. In the chest, the object is part of a linked list of objects that is not reset when the object is removed from the chest and placed in the inventory (but not in the dungeon), nor when it is stolen and added as the first Giggler possession. If the Giggler already has a possession before stealing the object then this does not create a cloned object.
- The following statement is missing: L0394_T_Thing->Next = Thing::_endOfList;
- This creates cloned things if L0394_T_Thing->Next is not Thing::_endOfList which is the case when the object comes from a chest in which it was not the last object */
+ The following statement is missing: L0394_T_Thing->Next = _vm->_endOfList;
+ This creates cloned things if L0394_T_Thing->Next is not _vm->_endOfList which is the case when the object comes from a chest in which it was not the last object */
} else {
_vm->_dungeonMan->linkThingToList(slotThing, group->_slot, kDMMapXNotOnASquare, 0);
}
@@ -1782,7 +1782,7 @@ void GroupMan::addAllActiveGroups() {
break;
}
curThing = dungeon.getNextThing(curThing);
- } while (curThing != Thing::_endOfList);
+ } while (curThing != _vm->_thingEndOfList);
}
}
}
@@ -1793,11 +1793,11 @@ Thing GroupMan::groupGetGenerated(CreatureType creatureType, int16 healthMultipl
Thing groupThing = dungeon.getUnusedThing(kDMThingTypeGroup);
if (((_currActiveGroupCount >= (_maxActiveGroupCount - 5)) && (dungeon._currMapIndex == dungeon._partyMapIndex))
- || (groupThing == Thing::_none)) {
- return Thing::_none;
+ || (groupThing == _vm->_thingNone)) {
+ return _vm->_thingNone;
}
Group *group = (Group *)dungeon.getThingData(groupThing);
- group->_slot = Thing::_endOfList;
+ group->_slot = _vm->_thingEndOfList;
group->setDoNotDiscard(false);
group->setDir(dir);
group->setCount(creatureCount);
@@ -1828,7 +1828,7 @@ Thing GroupMan::groupGetGenerated(CreatureType creatureType, int16 healthMultipl
impact (in which case the thing data was marked as unused) or the party is on the destination
square and an event is created to move the creature into the dungeon later
(in which case the thing is referenced in the event) */
- return Thing::_none;
+ return _vm->_thingNone;
}
_vm->_sound->requestPlay(kDMSoundIndexBuzz, mapX, mapY, kDMSoundModePlayIfPrioritized);
return groupThing;
@@ -1846,7 +1846,7 @@ bool GroupMan::isSquareACorridorTeleporterPitOrDoor(int16 mapX, int16 mapY) {
int16 GroupMan::getMeleeTargetCreatureOrdinal(int16 groupX, int16 groupY, int16 partyX, int16 partyY, uint16 champCell) {
Thing groupThing = groupGetThing(groupX, groupY);
- if (groupThing == Thing::_endOfList)
+ if (groupThing == _vm->_thingEndOfList)
return 0;
Group *group = (Group *)_vm->_dungeonMan->getThingData(groupThing);
@@ -1955,7 +1955,7 @@ void GroupMan::fluxCageAction(int16 mapX, int16 mapY) {
return;
Thing unusedThing = dungeon.getUnusedThing(kDMThingTypeExplosion);
- if (unusedThing == Thing::_none)
+ if (unusedThing == _vm->_thingNone)
return;
dungeon.linkThingToList(unusedThing, Thing(0), mapX, mapY);
@@ -1995,7 +1995,7 @@ void GroupMan::fluxCageAction(int16 mapX, int16 mapY) {
uint16 GroupMan::isLordChaosOnSquare(int16 mapX, int16 mapY) {
Thing thing = groupGetThing(mapX, mapY);
- if (thing == Thing::_endOfList)
+ if (thing == _vm->_thingEndOfList)
return 0;
Group *group = (Group *)_vm->_dungeonMan->getThingData(thing);
@@ -2013,7 +2013,7 @@ bool GroupMan::isFluxcageOnSquare(int16 mapX, int16 mapY) {
return false;
Thing thing = dungeon.getSquareFirstThing(mapX, mapY);
- while (thing != Thing::_endOfList) {
+ while (thing != _vm->_thingEndOfList) {
if ((thing.getType() == kDMThingTypeExplosion) && (((Explosion *)dungeon._thingData[kDMThingTypeExplosion])[thing.getIndex()].getType() == kDMExplosionTypeFluxcage))
return true;
@@ -2028,7 +2028,7 @@ void GroupMan::fuseAction(uint16 mapX, uint16 mapY) {
if ((mapX >= dungeon._currMapWidth) || (mapY >= dungeon._currMapHeight))
return;
- _vm->_projexpl->createExplosion(Thing::_explHarmNonMaterial, 255, mapX, mapY, kDMCreatureTypeSingleCenteredCreature); /* BUG0_17 The game crashes after the Fuse action is performed while looking at a wall on a map boundary. An explosion thing is created on the square in front of the party but there is no check to ensure the square coordinates are in the map bounds. This corrupts a memory location and leads to a game crash */
+ _vm->_projexpl->createExplosion(_vm->_thingExplHarmNonMaterial, 255, mapX, mapY, kDMCreatureTypeSingleCenteredCreature); /* BUG0_17 The game crashes after the Fuse action is performed while looking at a wall on a map boundary. An explosion thing is created on the square in front of the party but there is no check to ensure the square coordinates are in the map bounds. This corrupts a memory location and leads to a game crash */
Thing lordChaosThing = Thing(isLordChaosOnSquare(mapX, mapY));
if (lordChaosThing.toUint16()) {
bool isFluxcages[4];
diff --git a/engines/dm/inventory.cpp b/engines/dm/inventory.cpp
index 7ee28f3bea..b05adc6120 100644
--- a/engines/dm/inventory.cpp
+++ b/engines/dm/inventory.cpp
@@ -74,7 +74,7 @@ InventoryMan::InventoryMan(DMEngine *vm) : _vm(vm) {
_panelContent = kDMPanelContentFoodWaterPoisoned;
for (uint16 i = 0; i < 8; ++i)
_chestSlots[i] = Thing(0);
- _openChest = Thing::_none;
+ _openChest = _vm->_thingNone;
_objDescTextXpos = 0;
_objDescTextYpos = 0;
@@ -266,11 +266,11 @@ void InventoryMan::drawPanel() {
_panelContent = kDMPanelContentScroll;
break;
default:
- thing = Thing::_none;
+ thing = _vm->_thingNone;
break;
}
- if (thing == Thing::_none)
+ if (thing == _vm->_thingNone)
drawPanelFoodWaterPoisoned();
else
drawPanelObject(thing, false);
@@ -280,20 +280,20 @@ void InventoryMan::closeChest() {
DungeonMan &dunMan = *_vm->_dungeonMan;
bool processFirstChestSlot = true;
- if (_openChest == Thing::_none)
+ if (_openChest == _vm->_thingNone)
return;
Container *container = (Container *)dunMan.getThingData(_openChest);
- _openChest = Thing::_none;
- container->getSlot() = Thing::_endOfList;
+ _openChest = _vm->_thingNone;
+ container->getSlot() = _vm->_thingEndOfList;
Thing prevThing;
for (int16 chestSlotIndex = 0; chestSlotIndex < 8; ++chestSlotIndex) {
Thing thing = _chestSlots[chestSlotIndex];
- if (thing != Thing::_none) {
- _chestSlots[chestSlotIndex] = Thing::_none; // CHANGE8_09_FIX
+ if (thing != _vm->_thingNone) {
+ _chestSlots[chestSlotIndex] = _vm->_thingNone; // CHANGE8_09_FIX
if (processFirstChestSlot) {
processFirstChestSlot = false;
- *dunMan.getThingData(thing) = Thing::_endOfList.toUint16();
+ *dunMan.getThingData(thing) = _vm->_thingEndOfList.toUint16();
container->getSlot() = prevThing = thing;
} else {
dunMan.linkThingToList(thing, prevThing, kDMMapXNotOnASquare, 0);
@@ -368,7 +368,7 @@ void InventoryMan::openAndDrawChest(Thing thingToOpen, Container *chest, bool is
if (_openChest == thingToOpen)
return;
- if (_openChest != Thing::_none)
+ if (_openChest != _vm->_thingNone)
closeChest(); // CHANGE8_09_FIX
_openChest = thingToOpen;
@@ -380,7 +380,7 @@ void InventoryMan::openAndDrawChest(Thing thingToOpen, Container *chest, bool is
int16 chestSlotIndex = 0;
Thing thing = chest->getSlot();
int16 thingCount = 0;
- while (thing != Thing::_endOfList) {
+ while (thing != _vm->_thingEndOfList) {
if (++thingCount > 8)
break; // CHANGE8_08_FIX, make sure that no more than the first 8 objects in a chest are drawn
@@ -390,7 +390,7 @@ void InventoryMan::openAndDrawChest(Thing thingToOpen, Container *chest, bool is
}
while (chestSlotIndex < 8) {
objMan.drawIconInSlotBox(chestSlotIndex + kDMSlotBoxChestFirstSlot, kDMIconIndiceNone);
- _chestSlots[chestSlotIndex++] = Thing::_none;
+ _chestSlots[chestSlotIndex++] = _vm->_thingNone;
}
}
@@ -872,7 +872,7 @@ void InventoryMan::drawStopPressingEye() {
drawPanel();
_vm->_displayMan->drawViewport(k0_viewportNotDungeonView);
Thing leaderHandObject = _vm->_championMan->_leaderHandObject;
- if (leaderHandObject != Thing::_none)
+ if (leaderHandObject != _vm->_thingNone)
_vm->_objectMan->drawLeaderObjectName(leaderHandObject);
_vm->_eventMan->showMouse();
@@ -940,7 +940,7 @@ void InventoryMan::clickOnMouth() {
} else if (handThingType == kDMThingTypePotion)
removeObjectFromLeaderHand = false;
else {
- junkData->setNextThing(Thing::_none);
+ junkData->setNextThing(_vm->_thingNone);
removeObjectFromLeaderHand = true;
}
_vm->_eventMan->showMouse();
diff --git a/engines/dm/loadsave.cpp b/engines/dm/loadsave.cpp
index 8bc3770226..3d8f76c33f 100644
--- a/engines/dm/loadsave.cpp
+++ b/engines/dm/loadsave.cpp
@@ -63,7 +63,7 @@ LoadgameResult DMEngine::loadgame(int16 slot) {
//L1366_B_FadePalette = !F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C0_DO_NOT_FORCE_DIALOG_DM_CSB, true);
_restartGameAllowed = false;
_championMan->_partyChampionCount = 0;
- _championMan->_leaderHandObject = Thing::_none;
+ _championMan->_leaderHandObject = _thingNone;
} else {
fileName = getSavefileName(slot);
saveFileManager = _system->getSavefileManager();
diff --git a/engines/dm/menus.cpp b/engines/dm/menus.cpp
index ce5e6d2054..348bdfdb2d 100644
--- a/engines/dm/menus.cpp
+++ b/engines/dm/menus.cpp
@@ -206,7 +206,7 @@ void MenuMan::drawActionIcon(ChampionIndex championIndex) {
byte *bitmapIcon = dm._tmpBitmap;
Thing thing = champion.getSlot(kDMSlotActionHand);
IconIndice iconIndex;
- if (thing == Thing::_none) {
+ if (thing == _vm->_thingNone) {
iconIndex = kDMIconIndiceActionEmptyHand;
} else if (dungeon._objectInfos[dungeon.getObjectInfoIndex(thing)]._actionSetIndex) {
iconIndex = _vm->_objectMan->getIconIndex(thing);
@@ -590,7 +590,7 @@ int16 MenuMan::getChampionSpellCastResult(uint16 champIndex) {
if (curSpell->getType() == kDMSpellTypeProjectileOpenDoor)
skillLevel <<= 1;
- championMan.isProjectileSpellCast(champIndex, Thing(curSpell->getType() + Thing::_firstExplosion.toUint16()), CLIP(21, (powerSymbolOrdinal + 2) * (4 + (skillLevel << 1)), 255), 0);
+ championMan.isProjectileSpellCast(champIndex, Thing(curSpell->getType() + _vm->_thingFirstExplosion.toUint16()), CLIP(21, (powerSymbolOrdinal + 2) * (4 + (skillLevel << 1)), 255), 0);
break;
case kDMSpellKindOther: {
TimelineEvent newEvent;
@@ -666,15 +666,15 @@ int16 MenuMan::getChampionSpellCastResult(uint16 champIndex) {
break;
case kDMSpellTypeOtherZokathra: {
Thing unusedObject = dungeon.getUnusedThing(kDMThingTypeJunk);
- if (unusedObject == Thing::_none)
+ if (unusedObject == _vm->_thingNone)
break;
Junk *junkData = (Junk *)dungeon.getThingData(unusedObject);
junkData->setType(kDMJunkTypeZokathra);
ChampionSlot slotIndex;
- if (curChampion->_slots[kDMSlotReadyHand] == Thing::_none)
+ if (curChampion->_slots[kDMSlotReadyHand] == _vm->_thingNone)
slotIndex = kDMSlotReadyHand;
- else if (curChampion->_slots[kDMSlotActionHand] == Thing::_none)
+ else if (curChampion->_slots[kDMSlotActionHand] == _vm->_thingNone)
slotIndex = kDMSlotActionHand;
else
slotIndex = kDMSlotLeaderHand;
@@ -819,7 +819,7 @@ Potion *MenuMan::getEmptyFlaskInHand(Champion *champ, Thing *potionThing) {
DungeonMan &dungeon = *_vm->_dungeonMan;
for (int16 slotIndex = kDMSlotHead; --slotIndex >= kDMSlotReadyHand; ) {
Thing curThing = champ->_slots[slotIndex];
- if ((curThing != Thing::_none) && (_vm->_objectMan->getIconIndex(curThing) == kDMIconIndicePotionEmptyFlask)) {
+ if ((curThing != _vm->_thingNone) && (_vm->_objectMan->getIconIndex(curThing) == kDMIconIndicePotionEmptyFlask)) {
*potionThing = curThing;
return (Potion *)dungeon.getThingData(curThing);
}
@@ -1100,27 +1100,27 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
bool setDirectionFl = false;
int16 kineticEnergy = 0;
- Thing explosionThing = Thing::_none;
+ Thing explosionThing = _vm->_thingNone;
bool actionPerformed = true;
switch (actionIndex) {
case kDMActionLightning:
kineticEnergy = 180;
- explosionThing = Thing::_explLightningBolt;
+ explosionThing = _vm->_thingExplLightningBolt;
setDirectionFl = true;
break;
case kDMActionDispel:
kineticEnergy = 150;
- explosionThing = Thing::_explHarmNonMaterial;
+ explosionThing = _vm->_thingExplHarmNonMaterial;
setDirectionFl = true;
break;
case kDMActionFireball:
kineticEnergy = 150;
- explosionThing = Thing::_explFireBall;
+ explosionThing = _vm->_thingExplFireBall;
setDirectionFl = true;
break;
case kDMActionSpit:
kineticEnergy = 250;
- explosionThing = Thing::_explFireBall;
+ explosionThing = _vm->_thingExplFireBall;
setDirectionFl = true;
break;
case kDMActionBash:
@@ -1240,16 +1240,16 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
kineticEnergy = _vm->getRandomNumber(128) + 100;
switch (_vm->getRandomNumber(6)) {
case 0:
- explosionThing = Thing::_explPoisonBolt;
+ explosionThing = _vm->_thingExplPoisonBolt;
break;
case 1:
- explosionThing = Thing::_explPoisonCloud;
+ explosionThing = _vm->_thingExplPoisonCloud;
break;
case 2:
- explosionThing = Thing::_explHarmNonMaterial;
+ explosionThing = _vm->_thingExplHarmNonMaterial;
break;
default:
- explosionThing = Thing::_explFireBall;
+ explosionThing = _vm->_thingExplFireBall;
break;
}
setDirectionFl = true;
@@ -1311,12 +1311,12 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
nextMapX += _vm->_dirIntoStepCountEast[dungeon._partyDir];
nextMapY += _vm->_dirIntoStepCountNorth[dungeon._partyDir];
/* CHANGE6_00_FIX The presence of a group over the pit is checked so that you cannot climb down a pit with the rope if there is a group levitating over it */
- if ((dungeon.getSquare(nextMapX, nextMapY).getType() == kDMElementTypePit) && (_vm->_groupMan->groupGetThing(nextMapX, nextMapY) == Thing::_endOfList)) {
+ if ((dungeon.getSquare(nextMapX, nextMapY).getType() == kDMElementTypePit) && (_vm->_groupMan->groupGetThing(nextMapX, nextMapY) == _vm->_thingEndOfList)) {
/* BUG0_77 The party moves forward when using the rope in front of a closed pit. The engine does not check whether
the pit is open before moving the party over the pit. This is not consistent with the behavior when using the
rope in front of a corridor where nothing happens */
_vm->_moveSens->_useRopeToClimbDownPit = true;
- _vm->_moveSens->getMoveResult(Thing::_party, dungeon._partyMapX, dungeon._partyMapY, nextMapX, nextMapY);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, dungeon._partyMapX, dungeon._partyMapY, nextMapX, nextMapY);
_vm->_moveSens->_useRopeToClimbDownPit = false;
} else {
actionDisabledTicks = 0;
@@ -1327,11 +1327,11 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
if (weaponInHand->getType() == (int)kDMJunkTypeMagicalBoxBlue) {
freezeTicks = 30;
championMan.getObjectRemovedFromSlot(champIndex, kDMSlotActionHand);
- weaponInHand->setNextThing(Thing::_none);
+ weaponInHand->setNextThing(_vm->_thingNone);
} else if (weaponInHand->getType() == (int)kDMJunkTypeMagicalBoxGreen) {
freezeTicks = 125;
championMan.getObjectRemovedFromSlot(champIndex, kDMSlotActionHand);
- weaponInHand->setNextThing(Thing::_none);
+ weaponInHand->setNextThing(_vm->_thingNone);
} else {
freezeTicks = 70;
decrementCharges(curChampion);
@@ -1510,7 +1510,7 @@ bool MenuMan::isMeleeActionPerformed(int16 champIndex, Champion *champ, int16 ac
DungeonMan &dungeon = *_vm->_dungeonMan;
_vm->_sound->requestPlay(kDMSoundIndexAttackSkelettonAnimatedArmorDethKnight, dungeon._partyMapX, dungeon._partyMapY, kDMSoundModePlayIfPrioritized);
- if (_actionTargetGroupThing == Thing::_endOfList)
+ if (_actionTargetGroupThing == _vm->_thingEndOfList)
return false;
uint16 championCell = champ->_cell;
@@ -1546,7 +1546,7 @@ bool MenuMan::isMeleeActionPerformed(int16 champIndex, Champion *champ, int16 ac
bool MenuMan::isGroupFrightenedByAction(int16 champIndex, uint16 actionIndex, int16 mapX, int16 mapY) {
bool retVal = false;
- if (_actionTargetGroupThing == Thing::_endOfList)
+ if (_actionTargetGroupThing == _vm->_thingEndOfList)
return retVal;
ChampionMan &championMan = *_vm->_championMan;
@@ -1688,7 +1688,7 @@ void MenuMan::processCommands116To119_setActingChampion(uint16 champIndex) {
uint16 actionSetIndex;
Thing slotActionThing = curChampion->_slots[kDMSlotActionHand];
- if (slotActionThing == Thing::_none)
+ if (slotActionThing == _vm->_thingNone)
actionSetIndex = 2; /* Actions Punch, Kick and War Cry */
else {
actionSetIndex = dungeon._objectInfos[dungeon.getObjectInfoIndex(slotActionThing)]._actionSetIndex;
diff --git a/engines/dm/movesens.cpp b/engines/dm/movesens.cpp
index 7c7dc19606..cb9f93ab2b 100644
--- a/engines/dm/movesens.cpp
+++ b/engines/dm/movesens.cpp
@@ -62,7 +62,7 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
Thing squareFirstThing = dungeon.getSquareFirstThing(mapX, mapY);
Thing thingBeingProcessed = squareFirstThing;
- while (thingBeingProcessed != Thing::_endOfList) {
+ while (thingBeingProcessed != _vm->_thingEndOfList) {
ThingType thingType = thingBeingProcessed.getType();
if (thingType == kDMThingTypeSensor)
sensorCountToProcessPerCell[thingBeingProcessed.getCell()]++;
@@ -71,7 +71,7 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
thingBeingProcessed = dungeon.getNextThing(thingBeingProcessed);
}
- for (thingBeingProcessed = squareFirstThing; thingBeingProcessed != Thing::_endOfList; thingBeingProcessed = dungeon.getNextThing(thingBeingProcessed)) {
+ for (thingBeingProcessed = squareFirstThing; thingBeingProcessed != _vm->_thingEndOfList; thingBeingProcessed = dungeon.getNextThing(thingBeingProcessed)) {
Thing lastProcessedThing = thingBeingProcessed;
uint16 ProcessedThingType = thingBeingProcessed.getType();
if (ProcessedThingType == kDMThingTypeSensor) {
@@ -114,7 +114,7 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
break;
Sensor *lastSensor = (Sensor *)dungeon.getThingData(lastProcessedThing);
lastSensor->setNextThing(currentSensor->getNextThing());
- currentSensor->setNextThing(Thing::_none);
+ currentSensor->setNextThing(_vm->_thingNone);
thingBeingProcessed = lastProcessedThing;
}
@@ -133,18 +133,18 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
case kDMSensorWallSingleObjStorageRotateSensors:
if (_vm->_championMan->_leaderEmptyHanded) {
leaderHandObject = getObjectOfTypeInCell(mapX, mapY, cellIdx, sensorData);
- if (leaderHandObject == Thing::_none)
+ if (leaderHandObject == _vm->_thingNone)
continue;
dungeon.unlinkThingFromList(leaderHandObject, Thing(0), mapX, mapY);
_vm->_championMan->putObjectInLeaderHand(leaderHandObject, true);
} else {
- if ((_vm->_objectMan->getObjectType(leaderHandObject) != sensorData) || (getObjectOfTypeInCell(mapX, mapY, cellIdx, sensorData) != Thing::_none))
+ if ((_vm->_objectMan->getObjectType(leaderHandObject) != sensorData) || (getObjectOfTypeInCell(mapX, mapY, cellIdx, sensorData) != _vm->_thingNone))
continue;
_vm->_championMan->getObjectRemovedFromLeaderHand();
dungeon.linkThingToList(_vm->thingWithNewCell(leaderHandObject, cellIdx), Thing(0), mapX, mapY);
- leaderHandObject = Thing::_none;
+ leaderHandObject = _vm->_thingNone;
}
triggerLocalEffect(kDMSensorEffectToggle, mapX, mapY, cellIdx); /* This will cause a rotation of the sensors at the specified cell on the specified square after all sensors have been processed */
if ((sensorEffect == kDMSensorEffectHold) && !_vm->_championMan->_leaderEmptyHanded)
@@ -158,7 +158,7 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
continue;
Thing thingOnSquare = dungeon.getSquareFirstObject(mapX, mapY);
- if ((_vm->_objectMan->getObjectType(leaderHandObject) != sensorData) || (thingOnSquare == Thing::_none))
+ if ((_vm->_objectMan->getObjectType(leaderHandObject) != sensorData) || (thingOnSquare == _vm->_thingNone))
continue;
dungeon.unlinkThingFromList(thingOnSquare, Thing(0), mapX, mapY);
@@ -188,13 +188,13 @@ bool MovesensMan::sensorIsTriggeredByClickOnWall(int16 mapX, int16 mapY, uint16
if (!_vm->_championMan->_leaderEmptyHanded && ((processedSensorType == kDMSensorWallOrnClickWithSpecObjRemoved) || (processedSensorType == kDMSensorWallOrnClickWithSpecObjRemovedRotateSensors) || (processedSensorType == kDMSensorWallOrnClickWithSpecObjRemovedSensor))) {
Thing *leaderThing = (Thing *)dungeon.getThingData(leaderHandObject);
- *leaderThing = Thing::_none;
+ *leaderThing = _vm->_thingNone;
_vm->_championMan->getObjectRemovedFromLeaderHand();
- leaderHandObject = Thing::_none;
+ leaderHandObject = _vm->_thingNone;
} else if (_vm->_championMan->_leaderEmptyHanded
&& (processedSensorType == kDMSensorWallObjGeneratorRotateSensors)) {
leaderHandObject = dungeon.getObjForProjectileLaucherOrObjGen(sensorData);
- if (leaderHandObject != Thing::_none)
+ if (leaderHandObject != _vm->_thingNone)
_vm->_championMan->putObjectInLeaderHand(leaderHandObject, true);
}
triggerEffect(currentSensor, sensorEffect, mapX, mapY, cellIdx);
@@ -218,13 +218,13 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
uint16 thingCell = 0;
bool thingLevitates = false;
- if (thing != Thing::_party) {
+ if (thing != _vm->_thingParty) {
thingType = thing.getType();
thingCell = thing.getCell();
thingLevitates = isLevitating(thing);
}
/* If moving the party or a creature on the party map from a dungeon square then check for a projectile impact */
- if ((mapX >= 0) && ((thing == Thing::_party) || ((thingType == kDMThingTypeGroup) && (dungeon._currMapIndex == dungeon._partyMapIndex)))) {
+ if ((mapX >= 0) && ((thing == _vm->_thingParty) || ((thingType == kDMThingTypeGroup) && (dungeon._currMapIndex == dungeon._partyMapIndex)))) {
if (moveIsKilledByProjectileImpact(mapX, mapY, destMapX, destMapY, thing))
return true; /* The specified group thing cannot be moved because it was killed by a projectile impact */
}
@@ -243,7 +243,7 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
bool drawDungeonViewWhileFalling = false;
bool destinationIsTeleporterTarget = false;
int16 requiredTeleporterScope;
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
dungeon._partyMapX = destMapX;
dungeon._partyMapY = destMapY;
requiredTeleporterScope = kDMTeleporterScopeObjectsOrParty;
@@ -280,7 +280,7 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
destMapY = teleporter->getTargetMapY();
audibleTeleporter = teleporter->isAudible();
dungeon.setCurrentMap(mapIndexDestination = teleporter->getTargetMapIndex());
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
dungeon._partyMapX = destMapX;
dungeon._partyMapY = destMapY;
if (teleporter->isAudible())
@@ -321,7 +321,7 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
}
mapIndexDestination = dungeon.getLocationAfterLevelChange(mapIndexDestination, 1, &destMapX, &destMapY);
dungeon.setCurrentMap(mapIndexDestination);
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
dungeon._partyMapX = destMapX;
dungeon._partyMapY = destMapY;
if (_vm->_championMan->_partyChampionCount > 0) {
@@ -346,7 +346,7 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
if (outcome == kDMKillOutcomeSomeCreaturesInGroup)
_vm->_groupMan->dropMovingCreatureFixedPossession(thing, destMapX, destMapY);
}
- } else if ((destinationSquareType == (int)kDMElementTypeStairs) && (thing != Thing::_party) && (thingType != kDMThingTypeProjectile)) {
+ } else if ((destinationSquareType == (int)kDMElementTypeStairs) && (thing != _vm->_thingParty) && (thingType != kDMThingTypeProjectile)) {
if (!getFlag(destinationSquareData, kDMSquareMaskStairsUp)) {
mapIndexDestination = dungeon.getLocationAfterLevelChange(mapIndexDestination, 1, &destMapX, &destMapY);
dungeon.setCurrentMap(mapIndexDestination);
@@ -376,13 +376,13 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
_moveResultCell = thing.getCell();
partySquare = (mapIndexDestination == mapIndexSource) && (destMapX == mapX) && (destMapY == mapY);
if (partySquare) {
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
if (dungeon._partyDir == direction)
return false;
} else if ((_moveResultCell == thingCell) && (thingType != kDMThingTypeProjectile))
return false;
} else {
- if ((thing == Thing::_party) && _vm->_championMan->_partyChampionCount) {
+ if ((thing == _vm->_thingParty) && _vm->_championMan->_partyChampionCount) {
uint16 oldDestinationSquare = destinationSquareData;
int16 scentIndex = _vm->_championMan->_party._scentCount;
while (scentIndex >= 24) {
@@ -410,23 +410,23 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
}
}
if (mapX >= 0) {
- if (thing == Thing::_party)
- processThingAdditionOrRemoval(mapX, mapY, Thing::_party, partySquare, false);
+ if (thing == _vm->_thingParty)
+ processThingAdditionOrRemoval(mapX, mapY, _vm->_thingParty, partySquare, false);
else if (thingLevitates)
- dungeon.unlinkThingFromList(thing, Thing::_none, mapX, mapY);
+ dungeon.unlinkThingFromList(thing, _vm->_thingNone, mapX, mapY);
else
processThingAdditionOrRemoval(mapX, mapY, thing, (dungeon._currMapIndex == dungeon._partyMapIndex) && (mapX == dungeon._partyMapX) && (mapY == dungeon._partyMapY), false);
}
if (destMapX >= 0) {
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
dungeon.setCurrentMap(mapIndexDestination);
- if ((thing = _vm->_groupMan->groupGetThing(dungeon._partyMapX, dungeon._partyMapY)) != Thing::_endOfList) { /* Delete group if party moves onto its square */
+ if ((thing = _vm->_groupMan->groupGetThing(dungeon._partyMapX, dungeon._partyMapY)) != _vm->_thingEndOfList) { /* Delete group if party moves onto its square */
_vm->_groupMan->dropGroupPossessions(dungeon._partyMapX, dungeon._partyMapY, thing, kDMSoundModePlayIfPrioritized);
_vm->_groupMan->groupDelete(dungeon._partyMapX, dungeon._partyMapY);
}
if (mapIndexDestination == mapIndexSource)
- processThingAdditionOrRemoval(dungeon._partyMapX, dungeon._partyMapY, Thing::_party, partySquare, true);
+ processThingAdditionOrRemoval(dungeon._partyMapX, dungeon._partyMapY, _vm->_thingParty, partySquare, true);
else {
dungeon.setCurrentMap(mapIndexSource);
_vm->_newPartyMapIndex = mapIndexDestination;
@@ -436,7 +436,7 @@ bool MovesensMan::getMoveResult(Thing thing, int16 mapX, int16 mapY, int16 destM
dungeon.setCurrentMap(mapIndexDestination);
Teleporter *L0712_ps_Teleporter = (Teleporter *)dungeon.getThingData(thing);
int16 activeGroupIndex = ((Group *)L0712_ps_Teleporter)->getActiveGroupIndex();
- if (((mapIndexDestination == dungeon._partyMapIndex) && (destMapX == dungeon._partyMapX) && (destMapY == dungeon._partyMapY)) || (_vm->_groupMan->groupGetThing(destMapX, destMapY) != Thing::_endOfList)) { /* If a group tries to move to the party square or over another group then create an event to move the group later */
+ if (((mapIndexDestination == dungeon._partyMapIndex) && (destMapX == dungeon._partyMapX) && (destMapY == dungeon._partyMapY)) || (_vm->_groupMan->groupGetThing(destMapX, destMapY) != _vm->_thingEndOfList)) { /* If a group tries to move to the party square or over another group then create an event to move the group later */
dungeon.setCurrentMap(mapIndexSource);
if (mapX >= 0)
_vm->_groupMan->groupDeleteEvents(mapX, mapY);
@@ -522,7 +522,7 @@ bool MovesensMan::moveIsKilledByProjectileImpact(int16 srcMapX, int16 srcMapY, i
championOrCreatureOrdinalInCell[i] = 0;
ElementType impactType;
- if (thing == Thing::_party) {
+ if (thing == _vm->_thingParty) {
impactType = kDMElementTypeChampion;
for (uint16 cellIdx = kDMCellNorthWest; cellIdx < kDMCellSouthWest + 1; cellIdx++) {
if (_vm->_championMan->getIndexInCell((ViewCell)cellIdx) >= 0)
@@ -565,7 +565,7 @@ bool MovesensMan::moveIsKilledByProjectileImpact(int16 srcMapX, int16 srcMapY, i
uint16 projectileMapY = srcMapY;
T0266017_CheckProjectileImpacts:
Thing curThing = dungeon.getSquareFirstThing(projectileMapX, projectileMapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if ((curThing.getType() == kDMThingTypeProjectile) &&
(_vm->_timeline->_events[(((Projectile *)dungeon._thingData[kDMThingTypeProjectile])[curThing.getIndex()])._eventIndex]._type != kDMEventTypeMoveProjectileIgnoreImpacts)) {
int16 championOrCreatureOrdinal = championOrCreatureOrdinalInCell[curThing.getCell()];
@@ -706,7 +706,7 @@ void MovesensMan::processThingAdditionOrRemoval(uint16 mapX, uint16 mapY, Thing
int16 thingType;
IconIndice objectType;
- if (thing != Thing::_party) {
+ if (thing != _vm->_thingParty) {
thingType = thing.getType();
objectType = _vm->_objectMan->getObjectType(thing);
} else {
@@ -730,7 +730,7 @@ void MovesensMan::processThingAdditionOrRemoval(uint16 mapX, uint16 mapY, Thing
bool squareContainsThingOfDifferentType = false;
Thing curThing = dungeon.getSquareFirstThing(mapX, mapY);
if (sensorTriggeredCell == kDMCellAny) {
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
uint16 curThingType = curThing.getType();
if (curThingType == kDMThingTypeGroup)
squareContainsGroup = true;
@@ -745,7 +745,7 @@ void MovesensMan::processThingAdditionOrRemoval(uint16 mapX, uint16 mapY, Thing
curThing = dungeon.getNextThing(curThing);
}
} else {
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if ((sensorTriggeredCell == curThing.getCell()) && (curThing.getType() > kDMThingTypeGroup)) {
squareContainsObject = true;
squareContainsThingOfSameType |= (_vm->_objectMan->getObjectType(curThing) == objectType);
@@ -757,7 +757,7 @@ void MovesensMan::processThingAdditionOrRemoval(uint16 mapX, uint16 mapY, Thing
if (addThing && (thingType != kDMThingTypeParty))
dungeon.linkThingToList(thing, Thing(0), mapX, mapY);
- for (curThing = dungeon.getSquareFirstThing(mapX, mapY); curThing != Thing::_endOfList; curThing = dungeon.getNextThing(curThing)) {
+ for (curThing = dungeon.getSquareFirstThing(mapX, mapY); curThing != _vm->_thingEndOfList; curThing = dungeon.getNextThing(curThing)) {
uint16 curThingType = curThing.getType();
if (curThingType == kDMThingTypeSensor) {
Sensor *curSensor = (Sensor *)dungeon.getThingData(curThing);
@@ -890,7 +890,7 @@ bool MovesensMan::isObjectInPartyPossession(int16 objectType) {
if (curObjectType == kDMIconIndiceContainerChestClosed) {
Container *container = (Container *)dungeon.getThingData(curThing);
curThing = container->getSlot();
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if (_vm->_objectMan->getObjectType(curThing) == objectType)
return true;
@@ -975,17 +975,17 @@ void MovesensMan::processRotationEffect() {
}
Sensor *firstSensor = (Sensor *)dungeon.getThingData(firstSensorThing);
Thing lastSensorThing = firstSensor->getNextThing();
- while ((lastSensorThing != Thing::_endOfList)
+ while ((lastSensorThing != _vm->_thingEndOfList)
&& ((lastSensorThing.getType() != kDMThingTypeSensor)
|| ((_sensorRotationEffCell != kDMCellAny) && (lastSensorThing.getCell() != _sensorRotationEffCell)))) {
lastSensorThing = dungeon.getNextThing(lastSensorThing);
}
- if (lastSensorThing == Thing::_endOfList)
+ if (lastSensorThing == _vm->_thingEndOfList)
break;
dungeon.unlinkThingFromList(firstSensorThing, Thing(0), _sensorRotationEffMapX, _sensorRotationEffMapY);
Sensor *lastSensor = (Sensor *)dungeon.getThingData(lastSensorThing);
lastSensorThing = dungeon.getNextThing(lastSensorThing);
- while (((lastSensorThing != Thing::_endOfList) && (lastSensorThing.getType() == kDMThingTypeSensor))) {
+ while (((lastSensorThing != _vm->_thingEndOfList) && (lastSensorThing.getType() == kDMThingTypeSensor))) {
if ((_sensorRotationEffCell == kDMCellAny) || (lastSensorThing.getCell() == _sensorRotationEffCell))
lastSensor = (Sensor *)dungeon.getThingData(lastSensorThing);
lastSensorThing = dungeon.getNextThing(lastSensorThing);
@@ -1010,12 +1010,12 @@ void MovesensMan::createEventMoveGroup(Thing groupThing, int16 mapX, int16 mapY,
Thing MovesensMan::getObjectOfTypeInCell(int16 mapX, int16 mapY, int16 cell, int16 objectType) {
DungeonMan &dungeon = *_vm->_dungeonMan;
Thing curThing = dungeon.getSquareFirstObject(mapX, mapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if ((_vm->_objectMan->getObjectType(curThing) == objectType) && ((cell == kDMCellAny) || (curThing.getCell() == cell)))
return curThing;
curThing = dungeon.getNextThing(curThing);
}
- return Thing::_none;
+ return _vm->_thingNone;
}
}
diff --git a/engines/dm/objectman.cpp b/engines/dm/objectman.cpp
index 3b191e877c..66c6761f9a 100644
--- a/engines/dm/objectman.cpp
+++ b/engines/dm/objectman.cpp
@@ -132,7 +132,7 @@ void ObjectMan::loadObjectNames() {
}
IconIndice ObjectMan::getObjectType(Thing thing) {
- if (thing == Thing::_none)
+ if (thing == _vm->_thingNone)
return kDMIconIndiceNone;
int16 objectInfoIndex = _vm->_dungeonMan->getObjectInfoIndex(thing);
diff --git a/engines/dm/projexpl.cpp b/engines/dm/projexpl.cpp
index e4faa3f627..85767cd633 100644
--- a/engines/dm/projexpl.cpp
+++ b/engines/dm/projexpl.cpp
@@ -47,7 +47,7 @@ ProjExpl::ProjExpl(DMEngine *vm) : _vm(vm) {
void ProjExpl::createProjectile(Thing thing, int16 mapX, int16 mapY, uint16 cell, Direction dir, byte kineticEnergy, byte attack, byte stepEnergy) {
Thing projectileThing = _vm->_dungeonMan->getUnusedThing(kDMThingTypeProjectile);
- if (projectileThing == Thing::_none) /* BUG0_16 If the game cannot create a projectile thing because it has run out of such things (60 maximum) then the object being thrown/shot/launched is orphaned. If the game has run out of projectile things it will try to remove a projectile from elsewhere in the dungeon, except in an area of 11x11 squares centered around the party (to make sure the player cannot actually see the thing disappear on screen) */
+ if (projectileThing == _vm->_thingNone) /* BUG0_16 If the game cannot create a projectile thing because it has run out of such things (60 maximum) then the object being thrown/shot/launched is orphaned. If the game has run out of projectile things it will try to remove a projectile from elsewhere in the dungeon, except in an area of 11x11 squares centered around the party (to make sure the player cannot actually see the thing disappear on screen) */
return;
projectileThing = _vm->thingWithNewCell(projectileThing, cell);
@@ -80,18 +80,18 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
Thing projectileAssociatedThing = projectileThingData->_slot;
int16 projectileAssociatedThingType = projectileAssociatedThing.getType();
Potion *potion = nullptr;
- Thing explosionThing = Thing::_none;
+ Thing explosionThing = _vm->_thingNone;
if (projectileAssociatedThingType == kDMThingTypePotion) {
Group *projectileAssociatedGroup = (Group *)_vm->_dungeonMan->getThingData(projectileAssociatedThing);
PotionType potionType = ((Potion *)projectileAssociatedGroup)->getType();
if ((potionType == kDMPotionTypeVen) || (potionType == kDMPotionTypeFulBomb)) {
- explosionThing = (potionType == kDMPotionTypeVen) ? Thing::_explPoisonCloud: Thing::_explFireBall;
+ explosionThing = (potionType == kDMPotionTypeVen) ? _vm->_thingExplPoisonCloud: _vm->_thingExplFireBall;
removePotion = true;
potionPower = ((Potion *)projectileAssociatedGroup)->getPower();
potion = (Potion *)projectileAssociatedGroup;
}
}
- bool createExplosionOnImpact = (projectileAssociatedThingType == kDMThingTypeExplosion) && (projectileAssociatedThing != Thing::_explSlime) && (projectileAssociatedThing != Thing::_explPoisonBolt);
+ bool createExplosionOnImpact = (projectileAssociatedThingType == kDMThingTypeExplosion) && (projectileAssociatedThing != _vm->_thingExplSlime) && (projectileAssociatedThing != _vm->_thingExplPoisonBolt);
Thing *curGroupSlot = nullptr;
int16 projectileMapX;
int16 projectileMapY;
@@ -116,7 +116,7 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
byte curSquare = _vm->_dungeonMan->_currMapData[projectileTargetMapX][projectileTargetMapY];
int16 curDoorState = Square(curSquare).getDoorState();
Door *curDoor = (Door *)_vm->_dungeonMan->getSquareFirstThingData(projectileTargetMapX, projectileTargetMapY);
- if ((curDoorState != kDMDoorStateDestroyed) && (projectileAssociatedThing == Thing::_explOpenDoor)) {
+ if ((curDoorState != kDMDoorStateDestroyed) && (projectileAssociatedThing == _vm->_thingExplOpenDoor)) {
if (curDoor->hasButton())
_vm->_moveSens->addEvent(kDMEventTypeDoor, projectileTargetMapX, projectileTargetMapY, kDMCellNorthWest, kDMSensorEffectToggle, _vm->_gameTime + 1);
break;
@@ -128,7 +128,7 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
DoorInfo curDoorInfo = _vm->_dungeonMan->_currMapDoorInfo[curDoor->getType()];
if (getFlag(curDoorInfo._attributes, kDMMaskDoorInfoProjectilesCanPassThrough)) {
if (projectileAssociatedThingType == kDMThingTypeExplosion) {
- if (projectileAssociatedThing.toUint16() >= Thing::_explHarmNonMaterial.toUint16())
+ if (projectileAssociatedThing.toUint16() >= _vm->_thingExplHarmNonMaterial.toUint16())
return false;
} else {
int16 associatedThingIndex = _vm->_dungeonMan->getObjectInfoIndex(projectileAssociatedThing);
@@ -165,12 +165,12 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
curCreatureIndex--;
CreatureType curCreatureType = curGroup->_type;
CreatureInfo *curCreatureInfo = &_vm->_dungeonMan->_creatureInfos[curCreatureType];
- if ((projectileAssociatedThing == Thing::_explFireBall) && (curCreatureType == kDMCreatureTypeBlackFlame)) {
+ if ((projectileAssociatedThing == _vm->_thingExplFireBall) && (curCreatureType == kDMCreatureTypeBlackFlame)) {
uint16 *curCreatureHealth = &curGroup->_health[curCreatureIndex];
*curCreatureHealth = MIN(1000, *curCreatureHealth + getProjectileImpactAttack(projectileThingData, projectileAssociatedThing));
goto T0217044;
}
- if (getFlag(curCreatureInfo->_attributes, kDMCreatureMaskNonMaterial) && (projectileAssociatedThing != Thing::_explHarmNonMaterial))
+ if (getFlag(curCreatureInfo->_attributes, kDMCreatureMaskNonMaterial) && (projectileAssociatedThing != _vm->_thingExplHarmNonMaterial))
return false;
attack = (uint16)((unsigned long)getProjectileImpactAttack(projectileThingData, projectileAssociatedThing) << 6) / curCreatureInfo->_defense;
@@ -206,14 +206,14 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
} else {
explosionAttack = projectileThingData->_kineticEnergy;
}
- if ((projectileAssociatedThing == Thing::_explLightningBolt) && !(explosionAttack >>= 1))
+ if ((projectileAssociatedThing == _vm->_thingExplLightningBolt) && !(explosionAttack >>= 1))
goto T0217044;
- createExplosion(projectileAssociatedThing, explosionAttack, mapXCombo, mapYCombo, (projectileAssociatedThing == Thing::_explPoisonCloud) ? (uint16)kDMCreatureTypeSingleCenteredCreature : cell);
+ createExplosion(projectileAssociatedThing, explosionAttack, mapXCombo, mapYCombo, (projectileAssociatedThing == _vm->_thingExplPoisonCloud) ? (uint16)kDMCreatureTypeSingleCenteredCreature : cell);
} else {
uint16 soundIndex;
if ((projectileAssociatedThing).getType() == kDMThingTypeWeapon)
soundIndex = kDMSoundIndexMetallicThud;
- else if (projectileAssociatedThing == Thing::_explPoisonBolt)
+ else if (projectileAssociatedThing == _vm->_thingExplPoisonBolt)
soundIndex = kDMSoundIndexSpell;
else
soundIndex = kDMSoundIndexWoodenThudAttackTrolinAntmanStoneGolem;
@@ -222,7 +222,7 @@ bool ProjExpl::hasProjectileImpactOccurred(int16 impactType, int16 mapXCombo, in
}
T0217044:
if (removePotion) {
- potion->_nextThing = Thing::_none;
+ potion->_nextThing = _vm->_thingNone;
projectileThingData->_slot = explosionThing;
}
_vm->_dungeonMan->unlinkThingFromList(projectileThing, Thing(0), projectileMapX, projectileMapY);
@@ -246,14 +246,14 @@ uint16 ProjExpl::getProjectileImpactAttack(Projectile *projectile, Thing thing)
attack = _vm->getRandomNumber(4);
attack += _vm->_dungeonMan->getObjectWeight(thing) >> 1;
- } else if (thing == Thing::_explSlime) {
+ } else if (thing == _vm->_thingExplSlime) {
attack = _vm->getRandomNumber(16);
_projectilePoisonAttack = attack + 10;
attack += _vm->getRandomNumber(32);
} else {
- if (thing.toUint16() >= Thing::_explHarmNonMaterial.toUint16()) {
+ if (thing.toUint16() >= _vm->_thingExplHarmNonMaterial.toUint16()) {
_projectileAttackType = kDMAttackTypeMagic;
- if (thing == Thing::_explPoisonBolt) {
+ if (thing == _vm->_thingExplPoisonBolt) {
_projectilePoisonAttack = kineticEnergy;
return 1;
}
@@ -261,7 +261,7 @@ uint16 ProjExpl::getProjectileImpactAttack(Projectile *projectile, Thing thing)
}
_projectileAttackType = kDMAttackTypeFire;
attack = _vm->getRandomNumber(16) + _vm->getRandomNumber(16) + 10;
- if (thing == Thing::_explLightningBolt) {
+ if (thing == _vm->_thingExplLightningBolt) {
_projectileAttackType = kDMAttackTypeLightning;
attack *= 5;
}
@@ -274,7 +274,7 @@ uint16 ProjExpl::getProjectileImpactAttack(Projectile *projectile, Thing thing)
void ProjExpl::createExplosion(Thing explThing, uint16 attack, uint16 mapXCombo, uint16 mapYCombo, uint16 cell) {
Thing unusedThing = _vm->_dungeonMan->getUnusedThing(kDMThingTypeExplosion);
- if (unusedThing == Thing::_none)
+ if (unusedThing == _vm->_thingNone)
return;
Explosion *explosion = &((Explosion *)_vm->_dungeonMan->_thingData[kDMThingTypeExplosion])[(unusedThing).getIndex()];
@@ -301,35 +301,35 @@ void ProjExpl::createExplosion(Thing explThing, uint16 attack, uint16 mapXCombo,
unusedThing = _vm->thingWithNewCell(unusedThing, cell);
}
- explosion->setType(explThing.toUint16() - Thing::_firstExplosion.toUint16());
+ explosion->setType(explThing.toUint16() - _vm->_thingFirstExplosion.toUint16());
explosion->setAttack(attack);
- if (explThing.toUint16() < Thing::_explHarmNonMaterial.toUint16()) {
+ if (explThing.toUint16() < _vm->_thingExplHarmNonMaterial.toUint16()) {
uint16 soundIndex = (attack > 80) ? kDMSoundIndexStrongExplosion : kDMSoundIndexWeakExplosion;
_vm->_sound->requestPlay(soundIndex, projectileMapX, projectileMapY, kDMSoundModePlayIfPrioritized);
- } else if (explThing != Thing::_explSmoke)
+ } else if (explThing != _vm->_thingExplSmoke)
_vm->_sound->requestPlay(kDMSoundIndexSpell, projectileMapX, projectileMapY, kDMSoundModePlayIfPrioritized);
_vm->_dungeonMan->linkThingToList(unusedThing, Thing(0), projectileMapX, projectileMapY);
TimelineEvent newEvent;
- newEvent._mapTime = _vm->setMapAndTime(_vm->_dungeonMan->_currMapIndex, _vm->_gameTime + ((explThing == Thing::_explRebirthStep1) ? 5 : 1));
+ newEvent._mapTime = _vm->setMapAndTime(_vm->_dungeonMan->_currMapIndex, _vm->_gameTime + ((explThing == _vm->_thingExplRebirthStep1) ? 5 : 1));
newEvent._type = kDMEventTypeExplosion;
newEvent._priority = 0;
newEvent._Cu._slot = unusedThing.toUint16();
newEvent._Bu._location._mapX = projectileMapX;
newEvent._Bu._location._mapY = projectileMapY;
_vm->_timeline->addEventGetEventIndex(&newEvent);
- if ((explThing == Thing::_explLightningBolt) || (explThing == Thing::_explFireBall)) {
+ if ((explThing == _vm->_thingExplLightningBolt) || (explThing == _vm->_thingExplFireBall)) {
projectileMapX = projectileTargetMapX;
projectileMapY = projectileTargetMapY;
attack = (attack >> 1) + 1;
attack += _vm->getRandomNumber(attack) + 1;
- if ((explThing == Thing::_explFireBall) || (attack >>= 1)) {
+ if ((explThing == _vm->_thingExplFireBall) || (attack >>= 1)) {
if ((_vm->_dungeonMan->_currMapIndex == _vm->_dungeonMan->_partyMapIndex) && (projectileMapX == _vm->_dungeonMan->_partyMapX) && (projectileMapY == _vm->_dungeonMan->_partyMapY)) {
int16 wounds = kDMWoundReadHand | kDMWoundActionHand | kDMWoundHead | kDMWoundTorso | kDMWoundLegs | kDMWoundFeet;
_vm->_championMan->getDamagedChampionCount(attack, wounds, kDMAttackTypeFire);
} else {
unusedThing = _vm->_groupMan->groupGetThing(projectileMapX, projectileMapY);
- if (unusedThing != Thing::_endOfList) {
+ if (unusedThing != _vm->_thingEndOfList) {
Group *creatureGroup = (Group *)_vm->_dungeonMan->getThingData(unusedThing);
CreatureInfo *creatureInfo = &_vm->_dungeonMan->_creatureInfos[creatureGroup->_type];
int16 creatureFireResistance = creatureInfo->getFireResistance();
@@ -351,7 +351,7 @@ int16 ProjExpl::projectileGetImpactCount(int16 impactType, int16 mapX, int16 map
int16 impactCount = 0;
_creatureDamageOutcome = kDMKillOutcomeNoCreaturesInGroup;
- for (Thing curThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY); curThing != Thing::_endOfList; ) {
+ for (Thing curThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY); curThing != _vm->_thingEndOfList; ) {
if (((curThing).getType() == kDMThingTypeProjectile) && ((curThing).getCell() == cell) &&
hasProjectileImpactOccurred(impactType, mapX, mapY, cell, curThing)) {
projectileDeleteEvent(curThing);
@@ -377,16 +377,16 @@ void ProjExpl::projectileDelete(Thing projectileThing, Thing *groupSlot, int16 m
if (projectileSlotThing.getType() != kDMThingTypeExplosion) {
if (groupSlot != NULL) {
Thing previousThing = *groupSlot;
- if (previousThing == Thing::_endOfList) {
+ if (previousThing == _vm->_thingEndOfList) {
Thing *genericThing = (Thing *)_vm->_dungeonMan->getThingData(projectileSlotThing);
- *genericThing = Thing::_endOfList;
+ *genericThing = _vm->_thingEndOfList;
*groupSlot = projectileSlotThing;
} else
_vm->_dungeonMan->linkThingToList(projectileSlotThing, previousThing, kDMMapXNotOnASquare, 0);
} else
_vm->_moveSens->getMoveResult(Thing((projectileSlotThing).getTypeAndIndex() | getFlag(projectileThing.toUint16(), 0xC)), -2, 0, mapX, mapY);
}
- projectile->_nextThing = Thing::_none;
+ projectile->_nextThing = _vm->_thingNone;
}
void ProjExpl::processEvents48To49(TimelineEvent *event) {
@@ -407,7 +407,7 @@ void ProjExpl::processEvents48To49(TimelineEvent *event) {
if ((_vm->_dungeonMan->_currMapIndex == _vm->_dungeonMan->_partyMapIndex) && (destinationMapX == _vm->_dungeonMan->_partyMapX) && (destinationMapY == _vm->_dungeonMan->_partyMapY) && hasProjectileImpactOccurred(kDMElementTypeChampion, destinationMapX, destinationMapY, projectileCurCell, projectileThingNewCell))
return;
- if ((_vm->_groupMan->groupGetThing(destinationMapX, destinationMapY) != Thing::_endOfList) && hasProjectileImpactOccurred(kDMElementTypeCreature, destinationMapX, destinationMapY, projectileCurCell, projectileThing))
+ if ((_vm->_groupMan->groupGetThing(destinationMapX, destinationMapY) != _vm->_thingEndOfList) && hasProjectileImpactOccurred(kDMElementTypeCreature, destinationMapX, destinationMapY, projectileCurCell, projectileThing))
return;
uint16 stepEnergy = curEvent->_Cu._projectile.getStepEnergy();
@@ -481,15 +481,15 @@ void ProjExpl::processEvent25(TimelineEvent *event) {
CreatureInfo *creatureInfo = nullptr;
CreatureType creatureType;
- if (groupThing != Thing::_endOfList) {
+ if (groupThing != _vm->_thingEndOfList) {
group = (Group *)_vm->_dungeonMan->getThingData(groupThing);
creatureType = group->_type;
creatureInfo = &_vm->_dungeonMan->_creatureInfos[creatureType];
}
- Thing explosionThing = Thing(Thing::_firstExplosion.toUint16() + explosion->getType());
+ Thing explosionThing = Thing(_vm->_thingFirstExplosion.toUint16() + explosion->getType());
int16 attack;
- if (explosionThing == Thing::_explPoisonCloud)
+ if (explosionThing == _vm->_thingExplPoisonCloud)
attack = MAX(1, MIN(explosion->getAttack() >> 5, 4) + _vm->getRandomNumber(2)); /* Value between 1 and 5 */
else {
attack = (explosion->getAttack() >> 1) + 1;
@@ -508,7 +508,7 @@ void ProjExpl::processEvent25(TimelineEvent *event) {
break;
case 0xFF83:
- if ((groupThing != Thing::_endOfList) && getFlag(creatureInfo->_attributes, kDMCreatureMaskNonMaterial)) {
+ if ((groupThing != _vm->_thingEndOfList) && getFlag(creatureInfo->_attributes, kDMCreatureMaskNonMaterial)) {
if ((creatureType == kDMCreatureTypeMaterializerZytaz) && (_vm->_dungeonMan->_currMapIndex == _vm->_dungeonMan->_partyMapIndex)) {
int16 nonMaterialAdditionalAttack = attack >> 3;
attack -= nonMaterialAdditionalAttack;
@@ -537,7 +537,7 @@ void ProjExpl::processEvent25(TimelineEvent *event) {
case 0xFF87:
if (explosionOnPartySquare)
_vm->_championMan->getDamagedChampionCount(attack, kDMWoundNone, kDMAttackTypeNormal);
- else if ((groupThing != Thing::_endOfList)
+ else if ((groupThing != _vm->_thingEndOfList)
&& (attack = _vm->_groupMan->groupGetResistanceAdjustedPoisonAttack(creatureType, attack))
&& (_vm->_groupMan->getDamageAllCreaturesOutcome(group, mapX, mapY, attack, true) != kDMKillOutcomeAllCreaturesInGroup)
&& (attack > 2)) {
@@ -556,7 +556,7 @@ void ProjExpl::processEvent25(TimelineEvent *event) {
_vm->_timeline->addEventGetEventIndex(&newEvent);
} else {
_vm->_dungeonMan->unlinkThingFromList(Thing(event->_Cu._slot), Thing(0), mapX, mapY);
- explosion->setNextThing(Thing::_none);
+ explosion->setNextThing(_vm->_thingNone);
}
}
}
diff --git a/engines/dm/timeline.cpp b/engines/dm/timeline.cpp
index c6a77ece46..7ee1a467c7 100644
--- a/engines/dm/timeline.cpp
+++ b/engines/dm/timeline.cpp
@@ -310,7 +310,7 @@ void Timeline::processTimeline() {
if (!_vm->_gameWon) {
_vm->_dungeonMan->unlinkThingFromList(Thing(newEvent._Cu._slot), Thing(0), newEvent._Bu._location._mapX, newEvent._Bu._location._mapY);
curEvent = (TimelineEvent *)_vm->_dungeonMan->getThingData(Thing(newEvent._Cu._slot));
- ((Explosion *)curEvent)->setNextThing(Thing::_none);
+ ((Explosion *)curEvent)->setNextThing(_vm->_thingNone);
}
break;
case kDMEventTypeEnableChampionAction:
@@ -413,7 +413,7 @@ void Timeline::processEventDoorAnimation(TimelineEvent *event) {
}
Thing groupThing = _vm->_groupMan->groupGetThing(mapX, mapY);
uint16 creatureAttributes = _vm->_dungeonMan->getCreatureAttributes(groupThing);
- if ((groupThing != Thing::_endOfList) && !getFlag(creatureAttributes, kDMCreatureMaskNonMaterial)) {
+ if ((groupThing != _vm->_thingEndOfList) && !getFlag(creatureAttributes, kDMCreatureMaskNonMaterial)) {
if (doorState >= (verticalDoorFl ? CreatureInfo::getHeight(creatureAttributes) : 1)) { /* Creature height or 1 */
if (_vm->_groupMan->getDamageAllCreaturesOutcome((Group *)_vm->_dungeonMan->getThingData(groupThing), mapX, mapY, 5, true) != kDMKillOutcomeAllCreaturesInGroup)
_vm->_groupMan->processEvents29to41(mapX, mapY, kDMEventTypeCreateReactionDangerOnSquare, 0);
@@ -463,7 +463,7 @@ void Timeline::processEventSquareFakewall(TimelineEvent *event) {
addEventGetEventIndex(event);
} else {
Thing groupThing = _vm->_groupMan->groupGetThing(mapX, mapY);
- if ((groupThing != Thing::_endOfList) && !getFlag(_vm->_dungeonMan->getCreatureAttributes(groupThing), kDMCreatureMaskNonMaterial)) {
+ if ((groupThing != _vm->_thingEndOfList) && !getFlag(_vm->_dungeonMan->getCreatureAttributes(groupThing), kDMCreatureMaskNonMaterial)) {
event->_mapTime++;
addEventGetEventIndex(event);
} else
@@ -511,25 +511,25 @@ void Timeline::processEventSquarePit(TimelineEvent *event) {
void Timeline::moveTeleporterOrPitSquareThings(uint16 mapX, uint16 mapY) {
if ((_vm->_dungeonMan->_currMapIndex == _vm->_dungeonMan->_partyMapIndex)
&& (mapX == _vm->_dungeonMan->_partyMapX) && (mapY == _vm->_dungeonMan->_partyMapY)) {
- _vm->_moveSens->getMoveResult(Thing::_party, mapX, mapY, mapX, mapY);
+ _vm->_moveSens->getMoveResult(_vm->_thingParty, mapX, mapY, mapX, mapY);
_vm->_championMan->drawChangedObjectIcons();
}
Thing curThing = _vm->_groupMan->groupGetThing(mapX, mapY);
- if (curThing != Thing::_endOfList)
+ if (curThing != _vm->_thingEndOfList)
_vm->_moveSens->getMoveResult(curThing, mapX, mapY, mapX, mapY);
curThing = _vm->_dungeonMan->getSquareFirstObject(mapX, mapY);
Thing nextThing = curThing;
int16 thingsToMoveCount = 0;
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if (curThing.getType() > kDMThingTypeGroup)
thingsToMoveCount++;
curThing = _vm->_dungeonMan->getNextThing(curThing);
}
curThing = nextThing;
- while ((curThing != Thing::_endOfList) && thingsToMoveCount) {
+ while ((curThing != _vm->_thingEndOfList) && thingsToMoveCount) {
thingsToMoveCount--;
nextThing = _vm->_dungeonMan->getNextThing(curThing);
uint16 curThingType = curThing.getType();
@@ -580,7 +580,7 @@ void Timeline::processEventSquareWall(TimelineEvent *event) {
int16 mapY = event->_Bu._location._mapY;
Thing curThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
uint16 curCell = event->_Cu.A._cell;
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
int16 curThingType = curThing.getType();
if ((curThingType == kDMstringTypeText) && (curThing.getCell() == event->_Cu.A._cell)) {
TextString *textString = (TextString *)_vm->_dungeonMan->getThingData(curThing);
@@ -657,39 +657,39 @@ void Timeline::triggerProjectileLauncher(Sensor *sensor, TimelineEvent *event) {
Thing firstProjectileAssociatedThing;
Thing secondProjectileAssociatedThing;
if ((sensorType == kDMSensorWallSingleProjLauncherExplosion) || (sensorType == kDMSensorWallDoubleProjLauncherExplosion))
- firstProjectileAssociatedThing = secondProjectileAssociatedThing = Thing(sensorData + Thing::_firstExplosion.toUint16());
+ firstProjectileAssociatedThing = secondProjectileAssociatedThing = Thing(sensorData + _vm->_thingFirstExplosion.toUint16());
else if ((sensorType == kDMSensorWallSingleProjLauncherSquareObj) || (sensorType == kDMSensorWallDoubleProjLauncherSquareObj)) {
firstProjectileAssociatedThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
- while (firstProjectileAssociatedThing != Thing::_none) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game. In the original DM and CSB dungeons, the number of times that these sensors are triggered is always controlled to be equal to the number of available objects (with a countdown sensor or a number of once only sensors) */
+ while (firstProjectileAssociatedThing != _vm->_thingNone) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. _vm->_none should be _vm->_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game. In the original DM and CSB dungeons, the number of times that these sensors are triggered is always controlled to be equal to the number of available objects (with a countdown sensor or a number of once only sensors) */
uint16 projectiveThingCell = firstProjectileAssociatedThing.getCell();
if ((firstProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->turnDirRight(cell))))
break;
firstProjectileAssociatedThing = _vm->_dungeonMan->getNextThing(firstProjectileAssociatedThing);
}
- if (firstProjectileAssociatedThing == Thing::_none) /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList */
+ if (firstProjectileAssociatedThing == _vm->_thingNone) /* BUG0_19 The game crashes when an object launcher sensor is triggered. _vm->_none should be _vm->_endOfList */
return;
_vm->_dungeonMan->unlinkThingFromList(firstProjectileAssociatedThing, Thing(0), mapX, mapY); /* The object is removed without triggering any sensor effects */
if (!launchSingleProjectile) {
secondProjectileAssociatedThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
- while (secondProjectileAssociatedThing != Thing::_none) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game */
+ while (secondProjectileAssociatedThing != _vm->_thingNone) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. _vm->_none should be _vm->_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game */
uint16 projectiveThingCell = secondProjectileAssociatedThing.getCell();
if ((secondProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->turnDirRight(cell))))
break;
secondProjectileAssociatedThing = _vm->_dungeonMan->getNextThing(secondProjectileAssociatedThing);
}
- if (secondProjectileAssociatedThing == Thing::_none) /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList */
+ if (secondProjectileAssociatedThing == _vm->_thingNone) /* BUG0_19 The game crashes when an object launcher sensor is triggered. _vm->_none should be _vm->_endOfList */
launchSingleProjectile = true;
else
- _vm->_dungeonMan->unlinkThingFromList(secondProjectileAssociatedThing, Thing::_none, mapX, mapY); /* The object is removed without triggering any sensor effects */
+ _vm->_dungeonMan->unlinkThingFromList(secondProjectileAssociatedThing, _vm->_thingNone, mapX, mapY); /* The object is removed without triggering any sensor effects */
}
} else {
firstProjectileAssociatedThing = _vm->_dungeonMan->getObjForProjectileLaucherOrObjGen(sensorData);
- if ((firstProjectileAssociatedThing) == Thing::_none)
+ if ((firstProjectileAssociatedThing) == _vm->_thingNone)
return;
secondProjectileAssociatedThing = _vm->_dungeonMan->getObjForProjectileLaucherOrObjGen(sensorData);
- if (!launchSingleProjectile && (secondProjectileAssociatedThing == Thing::_none))
+ if (!launchSingleProjectile && (secondProjectileAssociatedThing == _vm->_thingNone))
launchSingleProjectile = true;
}
if (launchSingleProjectile)
@@ -710,7 +710,7 @@ void Timeline::processEventSquareCorridor(TimelineEvent *event) {
uint16 mapX = event->_Bu._location._mapX;
uint16 mapY = event->_Bu._location._mapY;
Thing curThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
int16 curThingType = curThing.getType();
if (curThingType == kDMstringTypeText) {
TextString *textString = (TextString *)_vm->_dungeonMan->getThingData(curThing);
@@ -772,7 +772,7 @@ void Timeline::processEventsMoveGroup(TimelineEvent *event) {
uint16 mapY = event->_Bu._location._mapY;
T0252001:
- if (((_vm->_dungeonMan->_currMapIndex != _vm->_dungeonMan->_partyMapIndex) || (mapX != _vm->_dungeonMan->_partyMapX) || (mapY != _vm->_dungeonMan->_partyMapY)) && (_vm->_groupMan->groupGetThing(mapX, mapY) == Thing::_endOfList)) { /* BUG0_24 Lord Chaos may teleport into one of the Black Flames and become invisible until the Black Flame is killed. In this case, _vm->_groupMan->f175_groupGetThing returns the Black Flame thing and the Lord Chaos thing is not moved into the dungeon until the Black Flame is killed */
+ if (((_vm->_dungeonMan->_currMapIndex != _vm->_dungeonMan->_partyMapIndex) || (mapX != _vm->_dungeonMan->_partyMapX) || (mapY != _vm->_dungeonMan->_partyMapY)) && (_vm->_groupMan->groupGetThing(mapX, mapY) == _vm->_thingEndOfList)) { /* BUG0_24 Lord Chaos may teleport into one of the Black Flames and become invisible until the Black Flame is killed. In this case, _vm->_groupMan->f175_groupGetThing returns the Black Flame thing and the Lord Chaos thing is not moved into the dungeon until the Black Flame is killed */
if (event->_type == kDMEventTypeMoveGroupAudible)
_vm->_sound->requestPlay(kDMSoundIndexBuzz, mapX, mapY, kDMSoundModePlayIfPrioritized);
@@ -806,7 +806,7 @@ T0252001:
void Timeline::procesEventEnableGroupGenerator(TimelineEvent *event) {
Thing curThing = _vm->_dungeonMan->getSquareFirstThing(event->_Bu._location._mapX, event->_Bu._location._mapY);
- while (curThing != Thing::_none) {
+ while (curThing != _vm->_thingNone) {
if ((curThing.getType()) == kDMThingTypeSensor) {
Sensor *curSensor = (Sensor *)_vm->_dungeonMan->getThingData(curThing);
if (curSensor->getType() == kDMSensorDisabled) {
@@ -826,7 +826,7 @@ void Timeline::processEventEnableChampionAction(uint16 champIndex) {
curChampion->_actionDefense -= _actionDefense[curChampion->_actionDefense];
}
if (curChampion->_currHealth) {
- if ((curChampion->_actionIndex == kDMActionShoot) && (curChampion->_slots[kDMSlotReadyHand] == Thing::_none)) {
+ if ((curChampion->_actionIndex == kDMActionShoot) && (curChampion->_slots[kDMSlotReadyHand] == _vm->_thingNone)) {
int16 slotIndex = kDMSlotQuiverLine1_1;
if (_vm->_championMan->isAmmunitionCompatibleWithWeapon(champIndex, kDMSlotActionHand, slotIndex))
_vm->_championMan->addObjectInSlot((ChampionIndex)champIndex, _vm->_championMan->getObjectRemovedFromSlot(champIndex, slotIndex), kDMSlotReadyHand);
@@ -846,7 +846,7 @@ void Timeline::processEventEnableChampionAction(uint16 champIndex) {
void Timeline::processEventMoveWeaponFromQuiverToSlot(uint16 champIndex, uint16 slotIndex) {
Champion *curChampion = &_vm->_championMan->_champions[champIndex];
- if (curChampion->_slots[slotIndex] != Thing::_none)
+ if (curChampion->_slots[slotIndex] != _vm->_thingNone)
return;
if (hasWeaponMovedSlot(champIndex, curChampion, kDMSlotQuiverLine1_1, slotIndex))
@@ -925,7 +925,7 @@ void Timeline::processEventViAltarRebirth(TimelineEvent *event) {
uint16 rebirthStep = event->_Cu.A._effect;
switch (rebirthStep) { /* Rebirth is a 3 steps process (Step 2 -> Step 1 -> Step 0). Step is stored in the Effect value of the event */
case 2:
- _vm->_projexpl->createExplosion(Thing::_explRebirthStep1, 0, mapX, mapY, cell);
+ _vm->_projexpl->createExplosion(_vm->_thingExplRebirthStep1, 0, mapX, mapY, cell);
event->_mapTime += 5;
T0255002:
rebirthStep--;
@@ -934,14 +934,14 @@ T0255002:
break;
case 1: {
Thing curThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
- while (curThing != Thing::_endOfList) {
+ while (curThing != _vm->_thingEndOfList) {
if ((curThing.getCell() == cell) && (curThing.getType() == kDMThingTypeJunk)) {
int16 iconIndex = _vm->_objectMan->getIconIndex(curThing);
if (iconIndex == kDMIconIndiceJunkChampionBones) {
Junk *junkData = (Junk *)_vm->_dungeonMan->getThingData(curThing);
if (junkData->getChargeCount() == championIndex) {
_vm->_dungeonMan->unlinkThingFromList(curThing, Thing(0), mapX, mapY); /* BUG0_25 When a champion dies, no bones object is created so it is not possible to bring the champion back to life at an altar of Vi. Each time a champion is brought back to life, the bones object is removed from the dungeon but it is not marked as unused and thus becomes an orphan. After a large number of champion deaths, all JUNK things are exhausted and the game cannot create any more. This also affects the creation of JUNK things dropped by some creatures when they die (Screamer, Rockpile, Magenta Worm, Pain Rat, Red Dragon) */
- junkData->setNextThing(Thing::_none);
+ junkData->setNextThing(_vm->_thingNone);
event->_mapTime += 1;
goto T0255002;
}
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index ceaadd5088..49c7b0b14c 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -87,7 +87,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -104,7 +104,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -121,7 +121,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -138,7 +138,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -151,7 +151,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -168,7 +168,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -181,7 +181,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -198,7 +198,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformDOS,
GF_PACKED,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -213,7 +213,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -226,7 +226,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -239,7 +239,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -252,7 +252,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -265,7 +265,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -278,7 +278,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
@@ -291,7 +291,7 @@ static const DrasculaGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GUIO1(GUIO_LINKSPEECHTOSFX)
},
},
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index c879a83db7..5265324d91 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -325,6 +325,8 @@ public:
virtual ~DrasculaEngine();
virtual bool hasFeature(EngineFeature f) const;
+ virtual void syncSoundSettings();
+
Common::RandomSource *_rnd;
const DrasculaGameDescription *_gameDescription;
uint32 getFeatures() const;
@@ -488,7 +490,7 @@ public:
void addKeyToBuffer(Common::KeyState& key);
void flushKeyBuffer();
void selectVerb(int);
- void updateVolume(Audio::Mixer::SoundType soundType, int prevVolume);
+ int updateVolume(int prevVolume, int prevVolumeY);
void volumeControls();
bool saveLoadScreen();
diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 09ff3c6429..dfe012a2ef 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -196,6 +196,11 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width,
dest += xdes + ydes * 320;
src += xorg + yorg * 320;
+ assert(xorg >= 0);
+ assert(yorg >= 0);
+ assert(xorg + width <= 320);
+ assert(yorg + height <= 200);
+
int ptr = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp
index 62ec796678..70916caffe 100644
--- a/engines/drascula/sound.cpp
+++ b/engines/drascula/sound.cpp
@@ -34,13 +34,48 @@
namespace Drascula {
-void DrasculaEngine::updateVolume(Audio::Mixer::SoundType soundType, int prevVolume) {
- int vol = _mixer->getVolumeForSoundType(soundType) / 16;
- if (_mouseY < prevVolume && vol < 15)
- vol++;
- if (_mouseY > prevVolume && vol > 0)
- vol--;
- _mixer->setVolumeForSoundType(soundType, vol * 16);
+void DrasculaEngine::syncSoundSettings() {
+ // Sync the engine with the config manager
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ // We need to handle the speech mute separately here. This is because the
+ // engine code should be able to rely on all speech sounds muted when the
+ // user specified subtitles only mode, which results in "speech_mute" to
+ // be set to "true". The global mute setting has precedence over the
+ // speech mute setting though.
+ bool speechMute = mute;
+ if (!speechMute)
+ speechMute = ConfMan.getBool("speech_mute");
+
+ _mixer->muteSoundType(Audio::Mixer::kPlainSoundType, mute);
+ _mixer->muteSoundType(Audio::Mixer::kSFXSoundType, mute);
+ _mixer->muteSoundType(Audio::Mixer::kSpeechSoundType, speechMute);
+ _mixer->muteSoundType(Audio::Mixer::kMusicSoundType, mute);
+
+ int voiceVolume = ConfMan.getInt("speech_volume");
+ int musicVolume = ConfMan.getInt("music_volume");
+ // If the music and voice volume are correct, don't change anything.
+ // Otherwise compute the master volume using an approximation of sqrt(max) * 16 which would result in the master
+ // volume being the same value as the max of music and voice.
+ if (_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) != voiceVolume || _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) != musicVolume) {
+ int masterVolume = MAX(musicVolume, voiceVolume) * 2 / 3 + 86;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, masterVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, voiceVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, voiceVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, musicVolume);
+ }
+}
+
+int DrasculaEngine::updateVolume(int prevVolume, int prevVolumeY) {
+ prevVolumeY += 10;
+ if (_mouseY < prevVolumeY && prevVolume < 15)
+ prevVolume++;
+ if (_mouseY > prevVolumeY && prevVolume > 0)
+ prevVolume--;
+ return prevVolume;
}
void DrasculaEngine::volumeControls() {
@@ -53,10 +88,22 @@ void DrasculaEngine::volumeControls() {
setCursor(kCursorCrosshair);
showCursor();
+ // The engine has three volume controls: master, SFx/Speech and Music.
+ // ScummVM doesn't have a master volume, so we abuse the kPlainSoundType to store it.
+ // In drascula, we only use the kMusicSoundType and kSpeechSoundType to play sounds.
+ // For consistency with the ScummVM options dialog we also set the kSFXSoundType volume
+ // to the same value as the kMusicSoundType value, but we don't actually use it.
+
+ // The engines uses masterVolume, voiceVolume and musicVolume between 0 and 15.
+ // We store in the mixer:
+ // - masterVolume * 16 in kPlainSoundType
+ // - (masterVolume + 1) * (voiceVolume + 1) - 1 in both kSpeechSoundType and kSFXSoundType
+ // - (masterVolume + 1) * (musicVolume + 1) - 1 in kMusicSoundType
+
while (!shouldQuit()) {
int masterVolume = CLIP((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16), 0, 15);
- int voiceVolume = CLIP((_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 16), 0, 15);
- int musicVolume = CLIP((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16), 0, 15);
+ int voiceVolume = CLIP(((_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) + 1) / (masterVolume + 1) - 1), 0, 15);
+ int musicVolume = CLIP(((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 1) / (masterVolume + 1) - 1), 0, 15);
int masterVolumeY = 72 + 61 - masterVolume * 4;
int voiceVolumeY = 72 + 61 - voiceVolume * 4;
@@ -87,16 +134,25 @@ void DrasculaEngine::volumeControls() {
if (_leftMouseButton == 1) {
delay(100);
if (_mouseX > 80 && _mouseX < 121) {
- updateVolume(Audio::Mixer::kPlainSoundType, masterVolumeY);
+ masterVolume = updateVolume(masterVolume, masterVolumeY);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, masterVolume * 16);
}
- if (_mouseX > 136 && _mouseX < 178) {
- updateVolume(Audio::Mixer::kSpeechSoundType, voiceVolumeY);
- }
+ if (_mouseX > 136 && _mouseX < 178)
+ voiceVolume = updateVolume(voiceVolume, voiceVolumeY);
- if (_mouseX > 192 && _mouseX < 233) {
- updateVolume(Audio::Mixer::kMusicSoundType, musicVolumeY);
- }
+ if (_mouseX > 192 && _mouseX < 233)
+ musicVolume = updateVolume(musicVolume, musicVolumeY);
+
+ voiceVolume = (masterVolume + 1) * (voiceVolume + 1) - 1;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, voiceVolume);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, voiceVolume);
+ ConfMan.setInt("speech_volume", voiceVolume);
+ ConfMan.setInt("sfx_volume", voiceVolume);
+
+ musicVolume = (masterVolume + 1) * (musicVolume + 1) - 1;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, musicVolume);
+ ConfMan.setInt("music_volume", musicVolume);
}
}
diff --git a/engines/dreamweb/detection_tables.h b/engines/dreamweb/detection_tables.h
index 0a59543c51..fdffb689f1 100644
--- a/engines/dreamweb/detection_tables.h
+++ b/engines/dreamweb/detection_tables.h
@@ -244,6 +244,24 @@ static const DreamWebGameDescription gameDescriptions[] = {
},
},
+ // Italian CD release
+ {
+ {
+ "dreamweb",
+ "CD",
+ {
+ {"dreamweb.exe", 0, "44d1708535cdb863b9cca372ad0b05dd", 65370},
+ {"dreamweb.r00", 0, "66dcab08354232f423c590156335f819", 155448},
+ {"dreamweb.r02", 0, "87a026e9f80ed4f94169381f871ee305", 199676},
+ AD_LISTEND
+ },
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_BRIGHTPALETTE)
+ },
+ },
+
// Czech fan-made translation
// From bug #7078
{
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index f1bb8d3e7f..ae8ab14d84 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -1264,7 +1264,7 @@ bool Console::cmdMapInstrument(int argc, const char **argv) {
char *instrumentName = new char[11];
Common::strlcpy(instrumentName, argv[1], 11);
- for (uint16 i = 0; i < strlen(instrumentName); i++)
+ for (uint16 i = 0; i < Common::strnlen(instrumentName, 11); i++)
if (instrumentName[i] == '_')
instrumentName[i] = ' ';
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index f4bd437d3e..91cf189d0a 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -313,7 +313,7 @@ int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) {
if (maxsize > 1) {
memset(dest, 0, maxsize);
f->_in->readLine(dest, maxsize);
- readBytes = strlen(dest); // FIXME: sierra sci returned byte count and didn't react on NUL characters
+ readBytes = Common::strnlen(dest, maxsize); // FIXME: sierra sci returned byte count and didn't react on NUL characters
// The returned string must not have an ending LF
if (readBytes > 0) {
if (dest[readBytes - 1] == 0x0A)
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 49ad4caedb..25483b6507 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -338,7 +338,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
score = Common::String::format("%u%03u", save.highScore, save.lowScore);
}
- const uint nameLength = strlen(save.name);
+ const uint nameLength = Common::strnlen(save.name, SCI_MAX_SAVENAME_LENGTH);
const uint size = nameLength + /* \r\n */ 2 + score.size();
char *buffer = (char *)malloc(size);
memcpy(buffer, save.name, nameLength);
@@ -372,7 +372,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
fillSavegameDesc(g_sci->getSavegameName(saveNo), &save);
const Common::String avatarId = Common::String::format("%02d", save.avatarId);
- const uint nameLength = strlen(save.name);
+ const uint nameLength = Common::strnlen(save.name, SCI_MAX_SAVENAME_LENGTH);
const uint size = nameLength + /* \r\n */ 2 + avatarId.size() + 1;
char *buffer = (char *)malloc(size);
memcpy(buffer, save.name, nameLength);
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index c605ba29e1..07a1c47547 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -671,7 +671,12 @@ reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) {
// palette animation effect slower and visible, and not have the logo screen
// get skipped because the scripts don't wait between animation steps. Fixes
// bug #3537232.
- if (g_sci->getGameId() == GID_SQ4 && !g_sci->isCD() && s->currentRoomNumber() == 1)
+ // The original workaround was for the intro SQ4 logo (room#1).
+ // This problem also happens in the time pod (room#531).
+ // This problem also happens in the ending cutscene time rip (room#21).
+ // This workaround affects astro chicken's (room#290) and is also called once
+ // right after a gameover (room#376)
+ if (g_sci->getGameId() == GID_SQ4 && !g_sci->isCD())
g_sci->sleep(10);
return s->r_acc;
@@ -819,8 +824,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
int16 celNo;
int16 priority;
reg_t listSeeker;
- Common::String *listStrings = NULL;
- const char **listEntries = NULL;
+ Common::String *listStrings = nullptr;
bool isAlias = false;
rect = kControlCreateRect(x, y,
@@ -917,11 +921,9 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
if (listCount) {
// We create a pointer-list to the different strings, we also find out whats upper and cursor position
listSeeker = textReference;
- listEntries = (const char**)malloc(sizeof(char *) * listCount);
listStrings = new Common::String[listCount];
for (i = 0; i < listCount; i++) {
listStrings[i] = s->_segMan->getString(listSeeker);
- listEntries[i] = listStrings[i].c_str();
if (listSeeker.getOffset() == upperOffset)
upperPos = i;
if (listSeeker.getOffset() == cursorOffset)
@@ -931,8 +933,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
}
debugC(kDebugLevelGraphics, "drawing list control %04x:%04x to %d,%d, diff %d", PRINT_REG(controlObject), x, y, SCI_MAX_SAVENAME_LENGTH);
- g_sci->_gfxControls16->kernelDrawList(rect, controlObject, maxChars, listCount, listEntries, fontId, style, upperPos, cursorPos, isAlias, hilite);
- free(listEntries);
+ g_sci->_gfxControls16->kernelDrawList(rect, controlObject, maxChars, listCount, listStrings, fontId, style, upperPos, cursorPos, isAlias, hilite);
delete[] listStrings;
return;
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index ae91ef088a..4c5f1228de 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -305,7 +305,7 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
Common::String tempsource = g_sci->getKernel()->lookupText(reg,
arguments[paramindex + 1]);
- int slen = strlen(tempsource.c_str());
+ int slen = tempsource.size();
int extralen = strLength - slen;
assert((target - targetbuf) + extralen <= maxsize);
if (extralen < 0)
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index 26ab9b47a5..5e07ead5d7 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -32,6 +32,7 @@ struct MessageRecord {
MessageTuple tuple;
MessageTuple refTuple;
const char *string;
+ uint32 length;
byte talker;
};
@@ -77,7 +78,13 @@ public:
record.tuple = tuple;
record.refTuple = MessageTuple();
record.talker = 0;
- record.string = (const char *)_data + READ_LE_UINT16(recordPtr + 2);
+ const uint16 stringOffset = READ_LE_UINT16(recordPtr + 2);
+ const uint32 maxSize = _size - stringOffset;
+ record.string = (const char *)_data + stringOffset;
+ record.length = Common::strnlen(record.string, maxSize);
+ if (record.length == maxSize) {
+ warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data);
+ }
return true;
}
recordPtr += _recordSize;
@@ -100,7 +107,13 @@ public:
record.tuple = tuple;
record.refTuple = MessageTuple();
record.talker = recordPtr[4];
- record.string = (const char *)_data + READ_LE_UINT16(recordPtr + 5);
+ const uint16 stringOffset = READ_LE_UINT16(recordPtr + 5);
+ const uint32 maxSize = _size - stringOffset;
+ record.string = (const char *)_data + stringOffset;
+ record.length = Common::strnlen(record.string, maxSize);
+ if (record.length == maxSize) {
+ warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data);
+ }
return true;
}
recordPtr += _recordSize;
@@ -123,7 +136,13 @@ public:
record.tuple = tuple;
record.refTuple = MessageTuple(recordPtr[7], recordPtr[8], recordPtr[9]);
record.talker = recordPtr[4];
- record.string = (const char *)_data + READ_SCI11ENDIAN_UINT16(recordPtr + 5);
+ const uint16 stringOffset = READ_SCI11ENDIAN_UINT16(recordPtr + 5);
+ const uint32 maxSize = _size - stringOffset;
+ record.string = (const char *)_data + stringOffset;
+ record.length = Common::strnlen(record.string, maxSize);
+ if (record.length == maxSize) {
+ warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data);
+ }
return true;
}
recordPtr += _recordSize;
@@ -149,7 +168,13 @@ public:
record.tuple = tuple;
record.refTuple = MessageTuple(recordPtr[8], recordPtr[9], recordPtr[10]);
record.talker = recordPtr[4];
- record.string = (const char *)_data + READ_BE_UINT16(recordPtr + 6);
+ const uint16 stringOffset = READ_BE_UINT16(recordPtr + 6);
+ const uint32 maxSize = _size - stringOffset;
+ record.string = (const char *)_data + stringOffset;
+ record.length = Common::strnlen(record.string, maxSize);
+ if (record.length == maxSize) {
+ warning("Message %s appears truncated at %ld", tuple.toString().c_str(), recordPtr - _data);
+ }
return true;
}
recordPtr += _recordSize;
@@ -161,7 +186,7 @@ public:
#endif
bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &record) {
- Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMessage, stack.getModule()), 0);
+ Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMessage, stack.getModule()), false);
if (!res) {
warning("Failed to open message resource %d", stack.getModule());
@@ -238,6 +263,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re
// as the text shown in this screen is very short (one-liners).
// Just output an empty string here instead of showing an error.
record.string = "";
+ record.length = 0;
delete reader;
return true;
}
@@ -285,7 +311,7 @@ int MessageState::nextMessage(reg_t buf) {
return record.talker;
} else {
MessageTuple &t = _cursorStack.top();
- outputString(buf, Common::String::format("Msg %d: %d %d %d %d not found", _cursorStack.getModule(), t.noun, t.verb, t.cond, t.seq));
+ outputString(buf, Common::String::format("Msg %d: %s not found", _cursorStack.getModule(), t.toString().c_str()));
return 0;
}
} else {
@@ -304,7 +330,7 @@ int MessageState::messageSize(int module, MessageTuple &t) {
stack.init(module, t);
if (getRecord(stack, true, record))
- return strlen(record.string) + 1;
+ return record.length + 1;
else
return 0;
}
diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h
index 5847e4767e..a4de19bc74 100644
--- a/engines/sci/engine/message.h
+++ b/engines/sci/engine/message.h
@@ -40,6 +40,11 @@ struct MessageTuple {
MessageTuple(byte noun_ = 0, byte verb_ = 0, byte cond_ = 0, byte seq_ = 1)
: noun(noun_), verb(verb_), cond(cond_), seq(seq_) { }
+
+ Common::String toString() const {
+ return Common::String::format("noun %d, verb %d, cond %d, seq %d",
+ noun, verb, cond, seq);
+ }
};
class CursorStack : public Common::Stack<MessageTuple> {
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 561b74d354..a3a690be59 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -456,9 +456,6 @@ void Script::syncStringHeap(Common::Serializer &s) {
s.syncBytes(buf, blockSize);
buf += blockSize;
-
- if (_buf - buf == 0)
- break;
} while (1);
} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE){
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 54b925a1b6..6002cbd8e4 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -598,8 +598,12 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
case SCI_OBJ_STRINGS:
debugN("Strings\n");
while (script->data [seeker]) {
- debugN("%04x: %s\n", seeker, script->data + seeker);
- seeker += strlen((char *)script->data + seeker) + 1;
+ debugN("%04x: %s", seeker, script->data + seeker);
+ seeker += Common::strnlen((char *)script->data + seeker, script->size - seeker) + 1;
+ if (seeker > script->size) {
+ debugN("[TRUNCATED]");
+ }
+ debugN("\n");
}
seeker++; // the ending zero byte
break;
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 23d1942dd3..9ccd1098d3 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -786,7 +786,10 @@ size_t SegManager::strlen(reg_t str) {
}
if (str_r.isRaw) {
- return ::strlen((const char *)str_r.raw);
+ // There is no guarantee that raw strings are zero-terminated; for
+ // example, Phant1 reads "\r\n" from a pointer of size 2 during the
+ // chase
+ return Common::strnlen((const char *)str_r.raw, str_r.maxSize);
} else {
int i = 0;
while (getChar(str_r, i))
@@ -807,19 +810,23 @@ Common::String SegManager::getString(reg_t pointer) {
return ret;
}
- if (src_r.isRaw)
- ret = (char *)src_r.raw;
- else {
+ if (src_r.isRaw) {
+ // There is no guarantee that raw strings are zero-terminated; for
+ // example, Phant1 reads "\r\n" from a pointer of size 2 during the
+ // chase
+ const uint size = Common::strnlen((const char *)src_r.raw, src_r.maxSize);
+ ret = Common::String((const char *)src_r.raw, size);
+ } else {
uint i = 0;
- for (;;) {
- char c = getChar(src_r, i);
+ while (i < (uint)src_r.maxSize) {
+ const char c = getChar(src_r, i);
if (!c)
break;
i++;
ret += c;
- };
+ }
}
return ret;
}
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 1ec13176e4..281837d921 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -528,7 +528,7 @@ public:
*/
void snug() {
assert(_type == kArrayTypeString || _type == kArrayTypeByte);
- resize(strlen((char *)_data) + 1, true);
+ resize(Common::strnlen((char *)_data, _size) + 1, true);
}
/**
@@ -808,7 +808,7 @@ public:
}
if (flags & kArrayTrimRight) {
- source = data + strlen((char *)data) - 1;
+ source = data + Common::strnlen((char *)data, _size) - 1;
while (source > data && *source != showChar && *source <= kWhitespaceBoundary) {
*source = '\0';
--source;
@@ -844,7 +844,7 @@ public:
}
++source;
- memmove(target, source, strlen((char *)source) + 1);
+ memmove(target, source, Common::strnlen((char *)source, _size - 1) + 1);
}
}
}
diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp
index b4bd92699a..479044a3e2 100644
--- a/engines/sci/graphics/controls16.cpp
+++ b/engines/sci/graphics/controls16.cpp
@@ -52,14 +52,12 @@ GfxControls16::~GfxControls16() {
const char controlListUpArrow[2] = { 0x18, 0 };
const char controlListDownArrow[2] = { 0x19, 0 };
-void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) {
+void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) {
Common::Rect workerRect = rect;
GuiResourceId oldFontId = _text16->GetFontId();
int16 oldPenColor = _ports->_curPort->penClr;
uint16 fontSize = 0;
int16 i;
- const char *listEntry;
- int16 listEntryLen;
int16 lastYpos;
// draw basic window
@@ -92,11 +90,10 @@ void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars
// Write actual text
for (i = upperPos; i < count; i++) {
_paint16->eraseRect(workerRect);
- listEntry = entries[i];
+ const Common::String &listEntry = entries[i];
if (listEntry[0]) {
_ports->moveTo(workerRect.left, workerRect.top);
- listEntryLen = strlen(listEntry);
- _text16->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor);
+ _text16->Draw(listEntry.c_str(), 0, MIN<int16>(maxChars, listEntry.size()), oldFontId, oldPenColor);
if ((!isAlias) && (i == cursorPos)) {
_paint16->invertRect(workerRect);
}
@@ -370,7 +367,7 @@ void GfxControls16::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId v
}
}
-void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) {
+void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) {
if (!hilite) {
drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias);
rect.grow(1);
diff --git a/engines/sci/graphics/controls16.h b/engines/sci/graphics/controls16.h
index 39ffa243fb..09d5800ca0 100644
--- a/engines/sci/graphics/controls16.h
+++ b/engines/sci/graphics/controls16.h
@@ -59,13 +59,13 @@ public:
void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 alignment, int16 style, bool hilite);
void kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite);
void kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite);
- void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite);
+ void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite);
void kernelTexteditChange(reg_t controlObject, reg_t eventObject);
private:
void texteditSetBlinkTime();
- void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias);
+ void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const Common::String *entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias);
void texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos);
void texteditCursorErase();
int getPicNotValid();
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index b5dd9aee0b..903136c29d 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -200,7 +200,7 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId
if (!_font)
return 0;
- while (1) {
+ for (;;) {
curChar = (*(const byte *)textPtr);
if (_font->isDoubleByte(curChar)) {
curChar |= (*(const byte *)(textPtr + 1)) << 8;
@@ -300,7 +300,7 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId
punctuationTable = text16_shiftJIS_punctuation_SCI01;
}
- while (1) {
+ for (;;) {
// Look up if character shouldn't be the first on a new line
nonBreakingPos = 0;
while (punctuationTable[nonBreakingPos]) {
@@ -383,15 +383,15 @@ void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId org
return;
}
-void GfxText16::StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) {
- Width(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight, true);
+void GfxText16::StringWidth(const Common::String &str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) {
+ Width(str.c_str(), 0, str.size(), orgFontId, textWidth, textHeight, true);
}
-void GfxText16::ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) {
- Show(str, 0, (int16)strlen(str), orgFontId, orgPenColor);
+void GfxText16::ShowString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor) {
+ Show(str.c_str(), 0, str.size(), orgFontId, orgPenColor);
}
-void GfxText16::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) {
- Draw(str, 0, (int16)strlen(str), orgFontId, orgPenColor);
+void GfxText16::DrawString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor) {
+ Draw(str.c_str(), 0, str.size(), orgFontId, orgPenColor);
}
int16 GfxText16::Size(Common::Rect &rect, const char *text, uint16 languageSplitter, GuiResourceId fontId, int16 maxWidth) {
@@ -580,20 +580,21 @@ void GfxText16::Box(const char *text, uint16 languageSplitter, bool show, const
}
}
-void GfxText16::DrawString(const char *text) {
+void GfxText16::DrawString(const Common::String &text) {
GuiResourceId previousFontId = GetFontId();
int16 previousPenColor = _ports->_curPort->penClr;
- Draw(text, 0, strlen(text), previousFontId, previousPenColor);
+ Draw(text.c_str(), 0, text.size(), previousFontId, previousPenColor);
SetFont(previousFontId);
_ports->penColor(previousPenColor);
}
// we need to have a separate status drawing code
// In KQ4 the IV char is actually 0xA, which would otherwise get considered as linebreak and not printed
-void GfxText16::DrawStatus(const char *text) {
+void GfxText16::DrawStatus(const Common::String &str) {
uint16 curChar, charWidth;
- uint16 textLen = strlen(text);
+ const byte *text = (const byte *)str.c_str();
+ uint16 textLen = str.size();
Common::Rect rect;
GetFont();
@@ -603,7 +604,7 @@ void GfxText16::DrawStatus(const char *text) {
rect.top = _ports->_curPort->curTop;
rect.bottom = rect.top + _ports->_curPort->fontHeight;
while (textLen--) {
- curChar = (*(const byte *)text++);
+ curChar = *text++;
switch (curChar) {
case 0:
break;
diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h
index eb39fb2513..cb3deb0c60 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -53,9 +53,9 @@ public:
int16 GetLongest(const char *&text, int16 maxWidth, GuiResourceId orgFontId);
void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont);
- void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight);
- void ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor);
- void DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor);
+ void StringWidth(const Common::String &str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight);
+ void ShowString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor);
+ void DrawString(const Common::String &str, GuiResourceId orgFontId, int16 orgPenColor);
int16 Size(Common::Rect &rect, const char *text, uint16 textLanguage, GuiResourceId fontId, int16 maxWidth);
void Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor);
void Show(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor);
@@ -65,8 +65,8 @@ public:
Box(text, 0, show, rect, alignment, fontId);
}
- void DrawString(const char *text);
- void DrawStatus(const char *text);
+ void DrawString(const Common::String &str);
+ void DrawStatus(const Common::String &str);
GfxFont *_font;
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index a0f958167d..ea8722aefd 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -207,8 +207,12 @@ bool Vocabulary::loadSuffixes() {
while ((seeker < resource->size - 1) && (resource->data[seeker + 1] != 0xff)) {
suffix_t suffix;
+ int maxSize = resource->size - seeker;
suffix.alt_suffix = (const char *)resource->data + seeker;
- suffix.alt_suffix_length = strlen(suffix.alt_suffix);
+ suffix.alt_suffix_length = Common::strnlen(suffix.alt_suffix, maxSize);
+ if (suffix.alt_suffix_length == maxSize) {
+ error("Vocabulary alt appears truncated for suffix %d in resource %d at %u", _parserSuffixes.size(), resource->getNumber(), seeker);
+ }
seeker += suffix.alt_suffix_length + 1; // Hit end of string
suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker);
@@ -217,8 +221,12 @@ bool Vocabulary::loadSuffixes() {
// Beginning of next string - skip leading '*'
seeker++;
+ maxSize = resource->size - seeker;
suffix.word_suffix = (const char *)resource->data + seeker;
- suffix.word_suffix_length = strlen(suffix.word_suffix);
+ suffix.word_suffix_length = Common::strnlen(suffix.word_suffix, maxSize);
+ if (suffix.word_suffix_length == maxSize) {
+ error("Vocabulary word appears truncated for suffix %d in resource %d at %u", _parserSuffixes.size(), resource->getNumber(), seeker);
+ }
seeker += suffix.word_suffix_length + 1;
suffix.class_mask = (int16)READ_BE_UINT16(resource->data + seeker);
@@ -288,12 +296,20 @@ bool Vocabulary::loadAltInputs() {
AltInput t;
t._input = data;
- uint32 l = strlen(data);
+ uint32 maxSize = data_end - data;
+ uint32 l = Common::strnlen(data, maxSize);
+ if (l == maxSize) {
+ error("Alt input from %d appears truncated at %ld", resource->getNumber(), (const byte *)data - resource->data);
+ }
t._inputLength = l;
data += l + 1;
t._replacement = data;
- l = strlen(data);
+ maxSize = data_end - data;
+ l = Common::strnlen(data, maxSize);
+ if (l == maxSize) {
+ error("Alt input replacement from %d appears truncated at %ld", resource->getNumber(), (const byte *)data - resource->data);
+ }
data += l + 1;
if (data < data_end && strncmp(data, t._input, t._inputLength) == 0)
@@ -316,7 +332,7 @@ void Vocabulary::freeAltInputs() {
_altInputs.clear();
}
-bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) {
+bool Vocabulary::checkAltInput(Common::String &text, uint16 &cursorPos) {
if (_altInputs.empty())
return false;
if (SELECTOR(parseLang) == -1)
@@ -330,7 +346,7 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) {
do {
changed = false;
- const char* t = text.c_str();
+ const char *t = text.c_str();
uint32 tlen = text.size();
for (uint32 p = 0; p < tlen && !changed; ++p) {
@@ -345,10 +361,11 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) {
continue;
if (strncmp(i->_input, t+p, i->_inputLength) == 0) {
// replace
+ const uint32 maxSize = text.size() - cursorPos;
if (cursorPos > p + i->_inputLength) {
- cursorPos += strlen(i->_replacement) - i->_inputLength;
+ cursorPos += Common::strnlen(i->_replacement, maxSize) - i->_inputLength;
} else if (cursorPos > p) {
- cursorPos = p + strlen(i->_replacement);
+ cursorPos = p + Common::strnlen(i->_replacement, maxSize);
}
for (uint32 j = 0; j < i->_inputLength; ++j)
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 77c3d4e637..aaa1c8ccfe 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -2234,7 +2234,7 @@ bool ResourceManager::checkResourceDataForSignature(Resource *resource, const by
if (signatureSize > resource->size)
return false;
- const uint32 signatureDWord = *((const uint32 *)signature);
+ const uint32 signatureDWord = READ_UINT32(signature);
signature += 4; signatureSize -= 4;
const uint32 searchLimit = resource->size - signatureSize + 1;
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 8465526243..5b7e14406a 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -937,7 +937,6 @@ L2A33:;
}
if ((_moving & 0x0F) == 3) {
-L2C36:;
setTmpFromActor();
if (!_walkDirX) {
@@ -980,7 +979,6 @@ L2C36:;
// 2ADA
if ((_moving & 0x0F) == 4) {
-L2CA3:;
setTmpFromActor();
if (!_walkDirY) {
@@ -1045,7 +1043,7 @@ L2CA3:;
directionUpdate();
animateActor(newDirToOldDir(_facing));
- goto L2C36;
+ return;
} else {
// 2B39
@@ -1064,7 +1062,7 @@ L2CA3:;
directionUpdate();
animateActor(newDirToOldDir(_facing));
- goto L2CA3;
+ return;
}
}
}
@@ -2416,6 +2414,7 @@ void Actor_v0::startAnimActor(int f) {
return;
_speaking = 1;
+ speakCheck();
return;
}
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 756e0b44de..822e32d9c4 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -31,6 +31,10 @@
namespace Scumm {
+ // Helper functions for ManiacMansion workarounds
+#define MM_SCRIPT(script) (script + (_game.version == 0 ? 0 : 5))
+#define MM_VALUE(v0,v1) (_game.version == 0 ? v0 : v1)
+
#define OPCODE(i, x) _opcodes[i]._OPCODE(ScummEngine_v2, x)
void ScummEngine_v2::setupOpcodes() {
@@ -1178,29 +1182,57 @@ void ScummEngine_v2::o2_startScript() {
// (which makes Ted go answer the door bell) is simply ignored. This
// way, the door bell still chimes, but Ted ignores it.
if (_game.id == GID_MANIAC) {
- if (_game.version >= 1 && script == 87) {
- if (isScriptRunning(88) || isScriptRunning(89))
- return;
- }
- // Script numbers are different in V0
- if (_game.version == 0 && script == 82) {
- if (isScriptRunning(83) || isScriptRunning(84))
+ if (script == MM_SCRIPT(82)) {
+ if (isScriptRunning(MM_SCRIPT(83)) || isScriptRunning(MM_SCRIPT(84)))
return;
}
}
+ // WORKAROUND bug #4556: Purple Tentacle can appear in the lab, after being
+ // chased out and end up stuck in the room. This bug is triggered if the player
+ // enters the lab within 45 minutes of first entering the mansion and has chased Purple Tentacle
+ // out. Eventually the cutscene with Purple Tentacle chasing Sandy in the lab
+ // will play. This script leaves Purple Tentacle in the room causing him to become
+ // a permanent resident.
+ // Our fix is simply to prevent the Cutscene playing, if the lab has already been stormed
+ if (_game.id == GID_MANIAC) {
+ if (_game.version >= 1 && script == 155) {
+ if (VAR(120) == 1)
+ return;
+ }
+ // Script numbers are different in V0
+ if (_game.version == 0 && script == 150) {
+ if (VAR(104) == 1)
+ return;
+ }
+ }
+
runScript(script, 0, 0, 0);
}
void ScummEngine_v2::stopScriptCommon(int script) {
+
+ // WORKAROUND bug #4112: If you enter the lab while Dr. Fred has the powered turned off
+ // to repair the Zom-B-Matic, the script will be stopped and the power will never turn
+ // back on. This fix forces the power on, when the player enters the lab,
+ // if the script which turned it off is running
+ if (_game.id == GID_MANIAC && _roomResource == 4 && isScriptRunning(MM_SCRIPT(138))) {
+
+ if (vm.slot[_currentScript].number == MM_VALUE(130, 163)) {
+
+ if (script == MM_SCRIPT(138)) {
+
+ int obj = MM_VALUE(124, 157);
+ putState(obj, getState(obj) & ~kObjectState_08);
+ }
+ }
+ }
+
if (_game.id == GID_MANIAC && _roomResource == 26 && vm.slot[_currentScript].number == 10001) {
// FIXME: Nasty hack for bug #915575
// Don't let the exit script for room 26 stop the script (116), when
// switching to the dungeon (script 89)
- if (_game.version >= 1 && script == 116 && isScriptRunning(89))
- return;
- // Script numbers are different in V0
- if (_game.version == 0 && script == 111 && isScriptRunning(84))
+ if (script == MM_SCRIPT(111) && isScriptRunning(MM_SCRIPT(84)))
return;
}
diff --git a/engines/sword25/util/lua_unpersist.cpp b/engines/sword25/util/lua_unpersist.cpp
index 678ddb52db..9c304503b9 100644
--- a/engines/sword25/util/lua_unpersist.cpp
+++ b/engines/sword25/util/lua_unpersist.cpp
@@ -116,16 +116,13 @@ static void registerObjectInIndexTable(UnSerializationInfo *info, int index) {
// >>>>> permTbl indexTbl ...... obj
// Make sure there is enough room on the stack
- lua_checkstack(info->luaState, 2);
-
- lua_pushlightuserdata(info->luaState, (void *)index);
- // >>>>> permTbl indexTbl ...... obj index
+ lua_checkstack(info->luaState, 1);
- lua_pushvalue(info->luaState, -2);
- // >>>>> permTbl indexTbl ...... obj index obj
+ lua_pushvalue(info->luaState, -1);
+ // >>>>> permTbl indexTbl ...... obj obj
// Push the k/v pair into the indexTbl
- lua_settable(info->luaState, 2);
+ lua_rawseti(info->luaState, 2, index);
// >>>>> permTbl indexTbl ...... obj
}
@@ -198,10 +195,7 @@ static void unpersist(UnSerializationInfo *info) {
} else {
// Fetch the object from the indexTbl
- lua_pushlightuserdata(info->luaState, (void *)index);
- // >>>>> permTbl indexTbl ...... index
-
- lua_gettable(info->luaState, 2);
+ lua_rawgeti(info->luaState, 2, index);
// >>>>> permTbl indexTbl ...... ?obj?
assert(!lua_isnil(info->luaState, -1));
diff --git a/engines/titanic/carry/arm.cpp b/engines/titanic/carry/arm.cpp
index 5105ea81b4..23b0710c30 100644
--- a/engines/titanic/carry/arm.cpp
+++ b/engines/titanic/carry/arm.cpp
@@ -35,55 +35,41 @@ BEGIN_MESSAGE_MAP(CArm, CCarry)
ON_MESSAGE(MouseDragMoveMsg)
END_MESSAGE_MAP()
-CArm::CArm() : CCarry(), _string6("Key"),
- _field138(0), _field158(0), _field16C(3), _field170(0),
+CArm::CArm() : CCarry(), _heldItemName("Key"),
+ _puzzleUnused(0), _armUnlocked(false), _arboretumFrame(3), _unlockedFrame(0),
_armRect(220, 208, 409, 350) {
}
void CArm::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeQuotedLine(_string6, indent);
- file->writeNumberLine(_field138, indent);
- file->writeNumberLine(_hookedRect.left, indent);
- file->writeNumberLine(_hookedRect.top, indent);
- file->writeNumberLine(_hookedRect.right, indent);
- file->writeNumberLine(_hookedRect.bottom, indent);
-
- file->writeQuotedLine(_string7, indent);
- file->writeNumberLine(_field158, indent);
- file->writeNumberLine(_armRect.left, indent);
- file->writeNumberLine(_armRect.top, indent);
- file->writeNumberLine(_armRect.right, indent);
- file->writeNumberLine(_armRect.bottom, indent);
- file->writeNumberLine(_field16C, indent);
- file->writeNumberLine(_field170, indent);
+ file->writeQuotedLine(_heldItemName, indent);
+ file->writeNumberLine(_puzzleUnused, indent);
+ file->writeRect(_hookedRect, indent);
+ file->writeQuotedLine(_hookedTarget, indent);
+ file->writeNumberLine(_armUnlocked, indent);
+ file->writeRect(_armRect, indent);
+ file->writeNumberLine(_arboretumFrame, indent);
+ file->writeNumberLine(_unlockedFrame, indent);
CCarry::save(file, indent);
}
void CArm::load(SimpleFile *file) {
file->readNumber();
- _string6 = file->readString();
- _field138 = file->readNumber();
- _hookedRect.left = file->readNumber();
- _hookedRect.top = file->readNumber();
- _hookedRect.right = file->readNumber();
- _hookedRect.bottom = file->readNumber();
-
- _string7 = file->readString();
- _field158 = file->readNumber();
- _armRect.left = file->readNumber();
- _armRect.top = file->readNumber();
- _armRect.right = file->readNumber();
- _armRect.bottom = file->readNumber();
- _field16C = file->readNumber();
- _field170 = file->readNumber();
+ _heldItemName = file->readString();
+ _puzzleUnused = file->readNumber();
+ _hookedRect = file->readRect();
+ _hookedTarget = file->readString();
+ _armUnlocked = file->readNumber();
+ _armRect = file->readRect();
+ _arboretumFrame = file->readNumber();
+ _unlockedFrame = file->readNumber();
CCarry::load(file);
}
bool CArm::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) {
- _field138 = 0;
+ _puzzleUnused = 0;
_canTake = true;
CString name = getName();
@@ -101,13 +87,13 @@ bool CArm::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) {
}
bool CArm::TranslateObjectMsg(CTranslateObjectMsg *msg) {
- Point newPos(_bounds.left - msg->_delta.x, _bounds.top - msg->_delta.y);
+ Point newPos(_bounds.left + msg->_delta.x, _bounds.top + msg->_delta.y);
setPosition(newPos);
return true;
}
bool CArm::UseWithOtherMsg(CUseWithOtherMsg *msg) {
- if (_string6 != "None") {
+ if (_heldItemName != "None") {
CShowTextMsg textMsg(ARM_ALREADY_HOLDING);
textMsg.execute("PET");
return false;
@@ -116,8 +102,8 @@ bool CArm::UseWithOtherMsg(CUseWithOtherMsg *msg) {
hookedMsg._rect.translate(_bounds.left, _bounds.top);
hookedMsg.execute("GondolierLeftLever");
- if (hookedMsg._result) {
- _string7 = "GondolierLeftLever";
+ if (hookedMsg._isHooked) {
+ _hookedTarget = "GondolierLeftLever";
} else {
petAddToInventory();
}
@@ -126,11 +112,13 @@ bool CArm::UseWithOtherMsg(CUseWithOtherMsg *msg) {
hookedMsg._rect.translate(_bounds.left, _bounds.top);
hookedMsg.execute("GondolierRightLever");
- if (hookedMsg._result) {
- _string7 = "GondolierRightLever";
+ if (hookedMsg._isHooked) {
+ _hookedTarget = "GondolierRightLever";
} else {
petAddToInventory();
}
+ } else {
+ petAddToInventory();
}
return true;
@@ -142,13 +130,13 @@ bool CArm::MouseDragStartMsg(CMouseDragStartMsg *msg) {
textMsg.execute("PET");
} else if (checkStartDragging(msg)) {
hideMouse();
- _tempPos = msg->_mousePos - _bounds;
- setPosition(msg->_mousePos - _tempPos);
+ _centroid = msg->_mousePos - _bounds;
+ setPosition(msg->_mousePos - _centroid);
- if (!_string7.empty()) {
+ if (!_hookedTarget.empty()) {
CActMsg actMsg("Unhook");
- actMsg.execute(_string7);
- _string7.clear();
+ actMsg.execute(_hookedTarget);
+ _hookedTarget.clear();
}
loadFrame(_visibleFrame);
@@ -161,39 +149,39 @@ bool CArm::MouseDragStartMsg(CMouseDragStartMsg *msg) {
bool CArm::MaitreDHappyMsg(CMaitreDHappyMsg *msg) {
CGameObject *petItem;
if (find(getName(), &petItem, FIND_PET)) {
- if (!_field158)
+ if (!_armUnlocked)
playSound("z#47.wav");
- if (_string6 == "Key" || _string6 == "AuditoryCentre") {
- CGameObject *child = dynamic_cast<CGameObject *>(getFirstChild());
- if (child) {
- child->setVisible(true);
- petAddToInventory();
+ if (_heldItemName == "Key" || _heldItemName == "AuditoryCentre") {
+ CGameObject *heldItem = dynamic_cast<CGameObject *>(getFirstChild());
+ if (heldItem) {
+ heldItem->setVisible(true);
+ heldItem->petAddToInventory();
}
- _visibleFrame = _field170;
+ _visibleFrame = _unlockedFrame;
loadFrame(_visibleFrame);
- _string6 = "None";
+ _heldItemName = "None";
petInvChange();
}
}
- _field158 = 1;
+ _armUnlocked = true;
_canTake = true;
return true;
}
bool CArm::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
- if (_field158) {
- if (_string6 == "Key" || _string6 == "AuditoryCentre") {
+ if (_armUnlocked) {
+ if (_heldItemName == "Key" || _heldItemName == "AuditoryCentre") {
CCarry *child = dynamic_cast<CCarry *>(getFirstChild());
if (child) {
- _visibleFrame = _field170;
+ _visibleFrame = _unlockedFrame;
loadFrame(_visibleFrame);
child->setVisible(true);
child->petAddToInventory();
}
- _string6 = "None";
+ _heldItemName = "None";
}
}
@@ -201,11 +189,11 @@ bool CArm::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
}
bool CArm::MouseDragMoveMsg(CMouseDragMoveMsg *msg) {
- setPosition(msg->_mousePos - _tempPos);
+ setPosition(msg->_mousePos - _centroid);
- if (_string6 != "None" && compareViewNameTo("FrozenArboretum.Node 5.S")) {
+ if (_heldItemName == "None" && compareViewNameTo("FrozenArboretum.Node 5.S")) {
loadFrame(_armRect.contains(msg->_mousePos) ?
- _field16C : _visibleFrame);
+ _arboretumFrame : _visibleFrame);
}
return true;
diff --git a/engines/titanic/carry/arm.h b/engines/titanic/carry/arm.h
index fc8bba1f08..3eec4b6995 100644
--- a/engines/titanic/carry/arm.h
+++ b/engines/titanic/carry/arm.h
@@ -40,14 +40,14 @@ class CArm : public CCarry {
bool PETGainedObjectMsg(CPETGainedObjectMsg *msg);
bool MouseDragMoveMsg(CMouseDragMoveMsg *msg);
private:
- CString _string6;
- int _field138;
+ CString _heldItemName;
+ int _puzzleUnused;
Rect _hookedRect;
- CString _string7;
- int _field158;
+ CString _hookedTarget;
+ bool _armUnlocked;
Rect _armRect;
- int _field16C;
- int _field170;
+ int _arboretumFrame;
+ int _unlockedFrame;
public:
CLASSDEF;
CArm();
diff --git a/engines/titanic/carry/brain.cpp b/engines/titanic/carry/brain.cpp
index b00f026718..73970c404c 100644
--- a/engines/titanic/carry/brain.cpp
+++ b/engines/titanic/carry/brain.cpp
@@ -33,14 +33,14 @@ BEGIN_MESSAGE_MAP(CBrain, CCarry)
ON_MESSAGE(PETGainedObjectMsg)
END_MESSAGE_MAP()
-CBrain::CBrain() : CCarry(), _field134(0), _field138(0) {
+CBrain::CBrain() : CCarry(), _pieceAdded(false), _perchGained(false) {
}
void CBrain::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writePoint(_pos1, indent);
- file->writeNumberLine(_field134, indent);
- file->writeNumberLine(_field138, indent);
+ file->writeNumberLine(_pieceAdded, indent);
+ file->writeNumberLine(_perchGained, indent);
CCarry::save(file, indent);
}
@@ -48,36 +48,38 @@ void CBrain::save(SimpleFile *file, int indent) {
void CBrain::load(SimpleFile *file) {
file->readNumber();
_pos1 = file->readPoint();
- _field134 = file->readNumber();
- _field138 = file->readNumber();
+ _pieceAdded = file->readNumber();
+ _perchGained = file->readNumber();
CCarry::load(file);
}
bool CBrain::UseWithOtherMsg(CUseWithOtherMsg *msg) {
CBrainSlot *slot = dynamic_cast<CBrainSlot *>(msg->_other);
- if (slot) {
- if (slot->getName() == "CentralCore") {
- setVisible(false);
- petMoveToHiddenRoom();
- CAddHeadPieceMsg headpieceMsg(getName());
- headpieceMsg.execute("CentralCoreSlot");
- }
- else if (!slot->_value1 && slot->getName() == "CentralCoreSlot") {
- setVisible(false);
- petMoveToHiddenRoom();
- CAddHeadPieceMsg headpieceMsg(getName());
- headpieceMsg.execute(msg->_other);
- playSound("z#116.wav");
- setPosition(Point(0, 0));
- setVisible(false);
- _field134 = 1;
- }
+ if (!slot)
+ return CCarry::UseWithOtherMsg(msg);
- return true;
+ if (isEquals("CentralCore")) {
+ setVisible(false);
+ petMoveToHiddenRoom();
+ CAddHeadPieceMsg headpieceMsg(getName());
+ headpieceMsg.execute("CentralCoreSlot");
+ } else if (!slot->_occupied && slot->getName() != "CentralCoreSlot") {
+ // Brain card goes into vacant slot
+ setVisible(false);
+ petMoveToHiddenRoom();
+ CAddHeadPieceMsg headpieceMsg(getName());
+ headpieceMsg.execute(msg->_other);
+ playSound("z#116.wav");
+ setPosition(Point(0, 0));
+ setVisible(false);
+ _pieceAdded = true;
} else {
- return CCarry::UseWithOtherMsg(msg);
+ // Trying to put brain card into an already occupied slot
+ petAddToInventory();
}
+
+ return true;
}
bool CBrain::VisibleMsg(CVisibleMsg *msg) {
@@ -89,11 +91,11 @@ bool CBrain::MouseDragStartMsg(CMouseDragStartMsg *msg) {
if (!checkStartDragging(msg))
return false;
- if (_field134) {
+ if (_pieceAdded) {
CTakeHeadPieceMsg headpieceMsg(getName());
headpieceMsg.execute("TitaniaControl");
- _field134 = 0;
+ _pieceAdded = false;
setVisible(true);
moveToView();
@@ -105,10 +107,10 @@ bool CBrain::MouseDragStartMsg(CMouseDragStartMsg *msg) {
}
bool CBrain::PassOnDragStartMsg(CPassOnDragStartMsg *msg) {
- if (_field134) {
+ if (_pieceAdded) {
CTakeHeadPieceMsg headpieceMsg(getName());
headpieceMsg.execute("TitaniaControl");
- _field134 = 0;
+ _pieceAdded = false;
setVisible(true);
moveToView();
@@ -120,10 +122,10 @@ bool CBrain::PassOnDragStartMsg(CPassOnDragStartMsg *msg) {
}
bool CBrain::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
- if (!_field138) {
+ if (!_perchGained) {
if (getName() == "Perch") {
- stateInc38();
- _field138 = 1;
+ incParrotResponse();
+ _perchGained = true;
}
}
diff --git a/engines/titanic/carry/brain.h b/engines/titanic/carry/brain.h
index bcba161e27..4c41378702 100644
--- a/engines/titanic/carry/brain.h
+++ b/engines/titanic/carry/brain.h
@@ -39,8 +39,8 @@ class CBrain : public CCarry {
bool PETGainedObjectMsg(CPETGainedObjectMsg *msg);
private:
Point _pos1;
- int _field134;
- int _field138;
+ bool _pieceAdded;
+ bool _perchGained;
public:
CLASSDEF;
CBrain();
diff --git a/engines/titanic/carry/carry.cpp b/engines/titanic/carry/carry.cpp
index f6403b18b9..fd5b593fa3 100644
--- a/engines/titanic/carry/carry.cpp
+++ b/engines/titanic/carry/carry.cpp
@@ -44,30 +44,29 @@ BEGIN_MESSAGE_MAP(CCarry, CGameObject)
ON_MESSAGE(PassOnDragStartMsg)
END_MESSAGE_MAP()
-CCarry::CCarry() : CGameObject(), _fieldDC(0), _canTake(true),
- _field100(0), _field104(0), _field108(0), _field10C(0),
- _itemFrame(0), _enterFrame(0), _enterFrameSet(false), _visibleFrame(0),
- _string1("None"),
- _fullViewName("NULL"),
- _string3(g_vm->_strings[DOESNT_DO_ANYTHING]),
- _string4(g_vm->_strings[DOESNT_WANT_THIS]) {
+CCarry::CCarry() : CGameObject(), _unused5(0), _canTake(true),
+ _unusedR(0), _unusedG(0), _unusedB(0), _itemFrame(0),
+ _enterFrame(0), _enterFrameSet(false), _visibleFrame(0),
+ _npcUse("None"), _fullViewName("NULL"),
+ _doesNothingMsg(g_vm->_strings[DOESNT_DO_ANYTHING]),
+ _doesntWantMsg(g_vm->_strings[DOESNT_WANT_THIS]) {
}
void CCarry::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeQuotedLine(_string1, indent);
+ file->writeQuotedLine(_npcUse, indent);
file->writePoint(_origPos, indent);
file->writeQuotedLine(_fullViewName, indent);
- file->writeNumberLine(_fieldDC, indent);
+ file->writeNumberLine(_unused5, indent);
file->writeNumberLine(_canTake, indent);
- file->writeQuotedLine(_string3, indent);
- file->writeQuotedLine(_string4, indent);
- file->writePoint(_tempPos, indent);
- file->writeNumberLine(_field104, indent);
- file->writeNumberLine(_field108, indent);
- file->writeNumberLine(_field10C, indent);
+ file->writeQuotedLine(_doesNothingMsg, indent);
+ file->writeQuotedLine(_doesntWantMsg, indent);
+ file->writePoint(_centroid, indent);
+ file->writeNumberLine(_unusedR, indent);
+ file->writeNumberLine(_unusedG, indent);
+ file->writeNumberLine(_unusedB, indent);
file->writeNumberLine(_itemFrame, indent);
- file->writeQuotedLine(_string5, indent);
+ file->writeQuotedLine(_unused6, indent);
file->writeNumberLine(_enterFrame, indent);
file->writeNumberLine(_enterFrameSet, indent);
file->writeNumberLine(_visibleFrame, indent);
@@ -77,19 +76,19 @@ void CCarry::save(SimpleFile *file, int indent) {
void CCarry::load(SimpleFile *file) {
file->readNumber();
- _string1 = file->readString();
+ _npcUse = file->readString();
_origPos = file->readPoint();
_fullViewName = file->readString();
- _fieldDC = file->readNumber();
+ _unused5 = file->readNumber();
_canTake = file->readNumber();
- _string3 = file->readString();
- _string4 = file->readString();
- _tempPos = file->readPoint();
- _field104 = file->readNumber();
- _field108 = file->readNumber();
- _field10C = file->readNumber();
+ _doesNothingMsg = file->readString();
+ _doesntWantMsg = file->readString();
+ _centroid = file->readPoint();
+ _unusedR = file->readNumber();
+ _unusedG = file->readNumber();
+ _unusedB = file->readNumber();
_itemFrame = file->readNumber();
- _string5 = file->readString();
+ _unused6 = file->readString();
_enterFrame = file->readNumber();
_enterFrameSet = file->readNumber();
_visibleFrame = file->readNumber();
@@ -118,7 +117,7 @@ bool CCarry::MouseDragStartMsg(CMouseDragStartMsg *msg) {
}
bool CCarry::MouseDragMoveMsg(CMouseDragMoveMsg *msg) {
- setPosition(msg->_mousePos - _tempPos);
+ setPosition(msg->_mousePos - _centroid);
return true;
}
@@ -167,7 +166,7 @@ bool CCarry::UseWithCharMsg(CUseWithCharMsg *msg) {
carryMsg._item = this;
carryMsg.execute(succubus);
} else {
- CShowTextMsg textMsg(_string4);
+ CShowTextMsg textMsg(_doesntWantMsg);
textMsg.execute("PET");
petAddToInventory();
}
@@ -180,7 +179,7 @@ bool CCarry::LeaveViewMsg(CLeaveViewMsg *msg) {
}
bool CCarry::UseWithOtherMsg(CUseWithOtherMsg *msg) {
- CShowTextMsg textMsg(_string3);
+ CShowTextMsg textMsg(_doesNothingMsg);
textMsg.execute("PET");
if (!compareViewNameTo(_fullViewName) || _bounds.top >= 360) {
@@ -233,13 +232,13 @@ bool CCarry::PassOnDragStartMsg(CPassOnDragStartMsg *msg) {
loadFrame(_visibleFrame);
if (msg->_value3) {
- _tempPos.x = _bounds.width() / 2;
- _tempPos.y = _bounds.height() / 2;
+ _centroid.x = _bounds.width() / 2;
+ _centroid.y = _bounds.height() / 2;
} else {
- _tempPos = msg->_mousePos - _bounds;
+ _centroid = msg->_mousePos - _bounds;
}
- setPosition(getMousePos() - _tempPos);
+ setPosition(getMousePos() - _centroid);
return true;
}
diff --git a/engines/titanic/carry/carry.h b/engines/titanic/carry/carry.h
index cb53df47a5..e9069da925 100644
--- a/engines/titanic/carry/carry.h
+++ b/engines/titanic/carry/carry.h
@@ -43,22 +43,20 @@ class CCarry : public CGameObject {
bool MoveToStartPosMsg(CMoveToStartPosMsg *msg);
bool EnterViewMsg(CEnterViewMsg *msg);
bool PassOnDragStartMsg(CPassOnDragStartMsg *msg);
-protected:
- int _fieldDC;
- CString _string3;
- CString _string4;
- Point _tempPos;
- int _field100;
- int _field104;
- int _field108;
- int _field10C;
+private:
+ int _unused5;
+ CString _doesNothingMsg;
+ CString _doesntWantMsg;
+ int _unusedR, _unusedG, _unusedB;
int _itemFrame;
- CString _string5;
+ CString _unused6;
int _enterFrame;
bool _enterFrameSet;
+protected:
+ Point _centroid;
int _visibleFrame;
public:
- CString _string1;
+ CString _npcUse;
bool _canTake;
Point _origPos;
CString _fullViewName;
diff --git a/engines/titanic/carry/carry_parrot.cpp b/engines/titanic/carry/carry_parrot.cpp
index 3a2f2c9368..4bb3a96bfb 100644
--- a/engines/titanic/carry/carry_parrot.cpp
+++ b/engines/titanic/carry/carry_parrot.cpp
@@ -113,7 +113,7 @@ bool CCarryParrot::MouseDragEndMsg(CMouseDragEndMsg *msg) {
CTreeItem *perchedParrot = findUnder(getRoot(), "PerchedParrot");
detach();
addUnder(perchedParrot);
- sound8(true);
+ stopSoundChannel(true);
CPutParrotBackMsg backMsg(msg->_mousePos.x);
backMsg.execute(perchedParrot);
@@ -122,7 +122,7 @@ bool CCarryParrot::MouseDragEndMsg(CMouseDragEndMsg *msg) {
_canTake = false;
CParrot::_state = PARROT_ESCAPED;
playSound("z#475.wav");
- sound8(true);
+ stopSoundChannel(true);
moveUnder(findRoom());
CActMsg actMsg("Shut");
@@ -137,7 +137,7 @@ bool CCarryParrot::MouseDragEndMsg(CMouseDragEndMsg *msg) {
setVisible(false);
_canTake = false;
playSound("z#475.wav");
- sound8(true);
+ stopSoundChannel(true);
moveUnder(findRoom());
}
}
diff --git a/engines/titanic/carry/ear.cpp b/engines/titanic/carry/ear.cpp
index 580ebd662f..c5196dc557 100644
--- a/engines/titanic/carry/ear.cpp
+++ b/engines/titanic/carry/ear.cpp
@@ -59,9 +59,11 @@ bool CEar::UseWithOtherMsg(CUseWithOtherMsg *msg) {
CAddHeadPieceMsg addMsg(getName());
if (addMsg._value != "NULL")
addMsg.execute(addMsg._value == "Ear1" ? "Ear1Slot" : "Ear2Slot");
- }
- return CCarry::UseWithOtherMsg(msg);
+ return true;
+ } else {
+ return CCarry::UseWithOtherMsg(msg);
+ }
}
} // End of namespace Titanic
diff --git a/engines/titanic/carry/head_piece.cpp b/engines/titanic/carry/head_piece.cpp
index 1ce1d5ba1e..fa025158a5 100644
--- a/engines/titanic/carry/head_piece.cpp
+++ b/engines/titanic/carry/head_piece.cpp
@@ -60,7 +60,7 @@ bool CHeadPiece::SenseWorkingMsg(CSenseWorkingMsg *msg) {
bool CHeadPiece::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
_visibleFrame = 1;
if (!_field13C) {
- stateInc38();
+ incParrotResponse();
_field13C = true;
}
diff --git a/engines/titanic/carry/magazine.cpp b/engines/titanic/carry/magazine.cpp
index e68c63f8f9..94e853bda9 100644
--- a/engines/titanic/carry/magazine.cpp
+++ b/engines/titanic/carry/magazine.cpp
@@ -52,19 +52,18 @@ void CMagazine::load(SimpleFile *file) {
}
bool CMagazine::UseWithCharMsg(CUseWithCharMsg *msg) {
+ // WORKAROUND: Slight difference to original to ensure that when the
+ // magazine is used on an incorrect char, it's returned to inventory
CDeskbot *deskbot = dynamic_cast<CDeskbot *>(msg->_character);
- if (deskbot) {
- if (deskbot->_deskbotActive) {
- setVisible(false);
- setPosition(Point(1000, 1000));
- CActMsg actMsg("2ndClassUpgrade");
- actMsg.execute("Deskbot");
- }
-
+ if (deskbot && deskbot->_deskbotActive) {
+ setVisible(false);
+ setPosition(Point(1000, 1000));
+ CActMsg actMsg("2ndClassUpgrade");
+ actMsg.execute("Deskbot");
return true;
- } else {
- return CCarry::UseWithCharMsg(msg);
}
+
+ return CCarry::UseWithCharMsg(msg);
}
bool CMagazine::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) {
@@ -77,17 +76,20 @@ bool CMagazine::VisibleMsg(CVisibleMsg *msg) {
}
bool CMagazine::UseWithOtherMsg(CUseWithOtherMsg *msg) {
+ // WORKAROUND: Slight difference to original to ensure that when the
+ // magazine is used on an incorrect object, it's returned to inventory
if (msg->_other->getName() == "SwitchOnDeskbot") {
- // TODO: other _field108 if
- if (false) {
+ CDeskbot *deskbot = dynamic_cast<CDeskbot *>(msg->_other);
+ if (deskbot && deskbot->_deskbotActive) {
setVisible(false);
setPosition(Point(1000, 1000));
CActMsg actMsg("2ndClassUpgrade");
actMsg.execute("Deskbot");
+ return true;
}
}
- return true;
+ return CCarry::UseWithOtherMsg(msg);
}
} // End of namespace Titanic
diff --git a/engines/titanic/carry/mouth.cpp b/engines/titanic/carry/mouth.cpp
index e48929a391..d750fc969e 100644
--- a/engines/titanic/carry/mouth.cpp
+++ b/engines/titanic/carry/mouth.cpp
@@ -70,7 +70,7 @@ bool CMouth::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
loadFrame(2);
setVisible(true);
if (!_field13C) {
- stateInc38();
+ incParrotResponse();
_field13C = true;
}
diff --git a/engines/titanic/carry/phonograph_cylinder.cpp b/engines/titanic/carry/phonograph_cylinder.cpp
index 777aa8be5b..fa260ef876 100644
--- a/engines/titanic/carry/phonograph_cylinder.cpp
+++ b/engines/titanic/carry/phonograph_cylinder.cpp
@@ -35,15 +35,15 @@ BEGIN_MESSAGE_MAP(CPhonographCylinder, CCarry)
END_MESSAGE_MAP()
CPhonographCylinder::CPhonographCylinder() : CCarry(),
- _bellsMuteControl(false), _bellsPitchControl(false),
- _bellsSpeedControl(false), _bellsDirectionControl(false),
+ _bellsMuteControl(false), _bellsPitchControl(0),
+ _bellsSpeedControl(0), _bellsDirectionControl(false),
_bellsInversionControl(false), _snakeMuteControl(false),
- _snakeSpeedControl(false), _snakePitchControl(false),
+ _snakeSpeedControl(0), _snakePitchControl(0),
_snakeInversionControl(false), _snakeDirectionControl(false),
- _pianoMuteControl(false), _pianoSpeedControl(false),
- _pianoPitchControl(false), _pianoInversionControl(false),
+ _pianoMuteControl(false), _pianoSpeedControl(0),
+ _pianoPitchControl(0), _pianoInversionControl(false),
_pianoDirectionControl(false), _bassMuteControl(false),
- _bassSpeedControl(false), _bassPitchControl(false),
+ _bassSpeedControl(0), _bassPitchControl(0),
_bassInversionControl(false) {
}
@@ -104,6 +104,7 @@ void CPhonographCylinder::load(SimpleFile *file) {
bool CPhonographCylinder::UseWithOtherMsg(CUseWithOtherMsg *msg) {
CPhonograph *phonograph = dynamic_cast<CPhonograph *>(msg->_other);
if (phonograph) {
+ // Below is redundant, since original never actually executes message
CSetVarMsg varMsg("m_RecordStatus", 1);
return true;
} else {
diff --git a/engines/titanic/carry/phonograph_cylinder.h b/engines/titanic/carry/phonograph_cylinder.h
index bbb1524cb5..086dedd2fe 100644
--- a/engines/titanic/carry/phonograph_cylinder.h
+++ b/engines/titanic/carry/phonograph_cylinder.h
@@ -36,24 +36,24 @@ class CPhonographCylinder : public CCarry {
bool ErasePhonographCylinderMsg(CErasePhonographCylinderMsg *msg);
private:
CString _itemName;
+ int _bellsPitchControl;
+ int _bellsSpeedControl;
bool _bellsMuteControl;
- bool _bellsPitchControl;
- bool _bellsSpeedControl;
bool _bellsDirectionControl;
bool _bellsInversionControl;
+ int _snakeSpeedControl;
+ int _snakePitchControl;
bool _snakeMuteControl;
- bool _snakeSpeedControl;
- bool _snakePitchControl;
bool _snakeInversionControl;
bool _snakeDirectionControl;
+ int _pianoSpeedControl;
+ int _pianoPitchControl;
bool _pianoMuteControl;
- bool _pianoSpeedControl;
- bool _pianoPitchControl;
bool _pianoInversionControl;
bool _pianoDirectionControl;
+ int _bassSpeedControl;
+ int _bassPitchControl;
bool _bassMuteControl;
- bool _bassSpeedControl;
- bool _bassPitchControl;
bool _bassInversionControl;
bool _bassDirectionControl;
public:
diff --git a/engines/titanic/carry/phonograph_ear.cpp b/engines/titanic/carry/phonograph_ear.cpp
index df0445d164..48ed85d685 100644
--- a/engines/titanic/carry/phonograph_ear.cpp
+++ b/engines/titanic/carry/phonograph_ear.cpp
@@ -32,13 +32,13 @@ END_MESSAGE_MAP()
void CPhonographEar::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_field140, indent);
+ file->writeNumberLine(_replacementEar, indent);
CEar::save(file, indent);
}
void CPhonographEar::load(SimpleFile *file) {
file->readNumber();
- _field140 = file->readNumber();
+ _replacementEar = file->readNumber();
CEar::load(file);
}
@@ -48,8 +48,9 @@ bool CPhonographEar::CorrectMusicPlayedMsg(CCorrectMusicPlayedMsg *msg) {
}
bool CPhonographEar::PETGainedObjectMsg(CPETGainedObjectMsg *msg) {
- if (_field140) {
- _field140 = false;
+ if (_replacementEar) {
+ // Start a timer to add a replacement ear to the Phonograph
+ _replacementEar = false;
addTimer(1000);
}
diff --git a/engines/titanic/carry/phonograph_ear.h b/engines/titanic/carry/phonograph_ear.h
index b5db015f90..df0700c5d1 100644
--- a/engines/titanic/carry/phonograph_ear.h
+++ b/engines/titanic/carry/phonograph_ear.h
@@ -33,10 +33,10 @@ class CPhonographEar : public CEar {
bool PETGainedObjectMsg(CPETGainedObjectMsg *msg);
bool TimerMsg(CTimerMsg *msg);
private:
- bool _field140;
+ bool _replacementEar;
public:
CLASSDEF;
- CPhonographEar() : CEar(), _field140(true) {}
+ CPhonographEar() : CEar(), _replacementEar(true) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/core/background.cpp b/engines/titanic/core/background.cpp
index 9f22f1e992..d6419f23db 100644
--- a/engines/titanic/core/background.cpp
+++ b/engines/titanic/core/background.cpp
@@ -58,7 +58,7 @@ void CBackground::load(SimpleFile *file) {
bool CBackground::StatusChangeMsg(CStatusChangeMsg *msg) {
setVisible(true);
if (_isBlocking) {
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
} else {
playMovie(_startFrame, _endFrame, 0);
}
diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp
index af7020532c..314746e496 100644
--- a/engines/titanic/core/game_object.cpp
+++ b/engines/titanic/core/game_object.cpp
@@ -56,26 +56,25 @@ void CGameObject::deinit() {
CGameObject::CGameObject(): CNamedItem() {
_bounds = Rect(0, 0, 15, 15);
- _field34 = 0;
- _field38 = 0;
- _field3C = 0;
+ _unused1 = 0;
+ _unused2 = 0;
+ _unused3 = 0;
_nonvisual = false;
- _field44 = 0xF0;
- _field48 = 0xF0;
- _field4C = 0xFF;
+ _toggleR = 0xF0;
+ _toggleG = 0xF0;
+ _toggleB = 0xFF;
_isPendingMail = false;
_destRoomFlags = 0;
_roomFlags = 0;
_visible = true;
- _field60 = 0;
+ _handleMouseFlag = false;
_cursorId = CURSOR_ARROW;
_initialFrame = 0;
_frameNumber = -1;
_text = nullptr;
_textBorder = _textBorderRight = 0;
- _field9C = 0;
_surface = nullptr;
- _fieldB8 = 0;
+ _unused4 = 0;
}
CGameObject::~CGameObject() {
@@ -105,19 +104,19 @@ void CGameObject::save(SimpleFile *file, int indent) {
file->writeNumberLine(getMovieFrame(), indent + 1);
file->writeNumberLine(_cursorId, indent + 1);
_movieClips.save(file, indent + 1);
- file->writeNumberLine(_field60, indent + 1);
+ file->writeNumberLine(_handleMouseFlag, indent + 1);
file->writeNumberLine(_nonvisual, indent + 1);
file->writeQuotedLine(_resource, indent + 1);
file->writeBounds(_bounds, indent + 1);
- file->writeFloatLine(_field34, indent + 1);
- file->writeFloatLine(_field38, indent + 1);
- file->writeFloatLine(_field3C, indent + 1);
+ file->writeFloatLine(_unused1, indent + 1);
+ file->writeFloatLine(_unused2, indent + 1);
+ file->writeFloatLine(_unused3, indent + 1);
- file->writeNumberLine(_field44, indent + 1);
- file->writeNumberLine(_field48, indent + 1);
- file->writeNumberLine(_field4C, indent + 1);
- file->writeNumberLine(_fieldB8, indent + 1);
+ file->writeNumberLine(_toggleR, indent + 1);
+ file->writeNumberLine(_toggleG, indent + 1);
+ file->writeNumberLine(_toggleB, indent + 1);
+ file->writeNumberLine(_unused4, indent + 1);
file->writeNumberLine(_visible, indent + 1);
file->writeNumberLine(_isPendingMail, indent + 1);
file->writeNumberLine(_destRoomFlags, indent + 1);
@@ -153,7 +152,7 @@ void CGameObject::load(SimpleFile *file) {
// Deliberate fall-through
case 4:
- _field60 = file->readNumber();
+ _handleMouseFlag = file->readNumber();
// Deliberate fall-through
case 3:
@@ -166,13 +165,13 @@ void CGameObject::load(SimpleFile *file) {
case 1:
_bounds = file->readBounds();
- _field34 = file->readFloat();
- _field38 = file->readFloat();
- _field3C = file->readFloat();
- _field44 = file->readNumber();
- _field48 = file->readNumber();
- _field4C = file->readNumber();
- _fieldB8 = file->readNumber();
+ _unused1 = file->readFloat();
+ _unused2 = file->readFloat();
+ _unused3 = file->readFloat();
+ _toggleR = file->readNumber();
+ _toggleG = file->readNumber();
+ _toggleB = file->readNumber();
+ _unused4 = file->readNumber();
_visible = file->readNumber() != 0;
_isPendingMail = file->readNumber();
_destRoomFlags = file->readNumber();
@@ -543,15 +542,11 @@ void CGameObject::setGlobalSoundVolume(int mode, uint seconds, int handleIndex)
}
}
-void CGameObject::sound8(bool flag) const {
- getGameManager()->_sound.stopChannel(flag ? 3 : 0);
+void CGameObject::stopSoundChannel(bool channel3) {
+ getGameManager()->_sound.stopChannel(channel3 ? 3 : 0);
}
void CGameObject::setVisible(bool val) {
- if (_name.contains("ylinder")) {
- warning("TODO");
- }
-
if (val != _visible) {
_visible = val;
makeDirty();
@@ -611,7 +606,7 @@ void CGameObject::playMovie(uint flags) {
CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
if (_surface) {
_surface->playMovie(flags, obj);
- if (flags & MOVIE_GAMESTATE)
+ if (flags & MOVIE_WAIT_FOR_FINISH)
getGameManager()->_gameState.addMovie(_surface->_movie);
}
}
@@ -627,7 +622,7 @@ void CGameObject::playMovie(int startFrame, int endFrame, uint flags) {
CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
if (_surface) {
_surface->playMovie(startFrame, endFrame, flags, obj);
- if (flags & MOVIE_GAMESTATE)
+ if (flags & MOVIE_WAIT_FOR_FINISH)
getGameManager()->_gameState.addMovie(_surface->_movie);
}
}
@@ -644,7 +639,7 @@ void CGameObject::playMovie(int startFrame, int endFrame, int initialFrame, uint
CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
if (_surface) {
_surface->playMovie(startFrame, endFrame, initialFrame, flags, obj);
- if (flags & MOVIE_GAMESTATE)
+ if (flags & MOVIE_WAIT_FOR_FINISH)
getGameManager()->_gameState.addMovie(_surface->_movie);
}
}
@@ -1058,12 +1053,12 @@ bool CGameObject::stateGetParrotMet() const {
return getGameManager()->_gameState.getParrotMet();
}
-void CGameObject::stateInc38() {
- getGameManager()->_gameState.inc38();
+void CGameObject::incParrotResponse() {
+ getGameManager()->_gameState.incParrotResponse();
}
-int CGameObject::stateGet38() const {
- return getGameManager()->_gameState._field38;
+int CGameObject::getParrotResponse() const {
+ return getGameManager()->_gameState._parrotResponseIndex;
}
void CGameObject::quitGame() {
@@ -1373,11 +1368,11 @@ void CGameObject::createCredits() {
_credits->load(this, screenManager, _bounds);
}
-void CGameObject::fn10(int v1, int v2, int v3) {
+void CGameObject::setToggleColor(byte r, byte g, byte b) {
makeDirty();
- _field44 = v1;
- _field48 = v2;
- _field4C = v3;
+ _toggleR = r;
+ _toggleG = g;
+ _toggleB = b;
}
void CGameObject::movieSetAudioTiming(bool flag) {
@@ -1429,8 +1424,8 @@ bool CGameObject::compareRoomFlags(RoomFlagsComparison compareType, uint flags1,
}
}
-void CGameObject::setState1C(bool flag) {
- getGameManager()->_gameState._field1C = flag;
+void CGameObject::stateSetSoundMakerAllowed(bool flag) {
+ getGameManager()->_gameState._soundMakerAllowed = flag;
}
void CGameObject::addMail(uint destRoomFlags) {
@@ -1648,9 +1643,9 @@ void CGameObject::starFn1(int v) {
starControl->fn1(v);
}
-bool CGameObject::starFn2() {
+bool CGameObject::starIsSolved() const {
CStarControl *starControl = getStarControl();
- return starControl ? starControl->fn4() : false;
+ return starControl ? starControl->isSolved() : false;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/titanic/core/game_object.h b/engines/titanic/core/game_object.h
index 30b3321128..b214cf8c9e 100644
--- a/engines/titanic/core/game_object.h
+++ b/engines/titanic/core/game_object.h
@@ -77,13 +77,11 @@ private:
protected:
static CCreditText *_credits;
protected:
- double _field34;
- double _field38;
- double _field3C;
+ double _unused1;
+ double _unused2;
+ double _unused3;
bool _nonvisual;
- int _field44;
- int _field48;
- int _field4C;
+ byte _toggleR, _toggleG, _toggleB;
CMovieClipList _movieClips;
int _initialFrame;
CMovieRangeInfoList _movieRangeInfoList;
@@ -91,11 +89,10 @@ protected:
CTextControl *_text;
uint _textBorder;
uint _textBorderRight;
- int _field9C;
Common::Point _savedPos;
CVideoSurface *_surface;
CString _resource;
- int _fieldB8;
+ int _unused4;
protected:
/**
* Saves the current position the object is located at
@@ -277,7 +274,10 @@ protected:
*/
void setGlobalSoundVolume(int mode, uint seconds, int handleIndex);
- void sound8(bool flag) const;
+ /**
+ * Stops sound channel 3 or 0
+ */
+ void stopSoundChannel(bool channel3);
/**
* Adds a timer
@@ -463,11 +463,10 @@ protected:
void setPassengerClass(PassengerClass newClass);
/**
- * Overrides whether the object's movie has audio timing
+ * Sets color RGB for toggles
+ * @remarks The color set isn't actually used anywhere
*/
- void movieSetAudioTiming(bool flag);
-
- void fn10(int v1, int v2, int v3);
+ void setToggleColor(byte r, byte g, byte b);
/**
* Gets the duration of a specified clip in milliseconds
@@ -528,7 +527,7 @@ public:
bool _isPendingMail;
uint _destRoomFlags;
uint _roomFlags;
- int _field60;
+ bool _handleMouseFlag;
CursorId _cursorId;
bool _visible;
public:
@@ -638,6 +637,11 @@ public:
void stopMovie();
/**
+ * Overrides whether the object's movie has audio timing
+ */
+ void movieSetAudioTiming(bool flag);
+
+ /**
* Get the current movie frame
*/
int getMovieFrame() const;
@@ -942,7 +946,11 @@ public:
CStarControl *getStarControl() const;
void starFn1(int v);
- bool starFn2();
+
+ /**
+ * Returns true if the starmap puzzle has been solved
+ */
+ bool starIsSolved() const;
/*--- CTrueTalkManager Methods ---*/
@@ -987,7 +995,10 @@ public:
/*--- CGameState Methods ---*/
- void setState1C(bool flag);
+ /**
+ * Sets whether a background sound maker is allowed for the rooms if available
+ */
+ void stateSetSoundMakerAllowed(bool flag);
/**
* Change to the next season
@@ -1009,8 +1020,15 @@ public:
*/
bool stateGetParrotMet() const;
- void stateInc38();
- int stateGet38() const;
+ /**
+ * Moves the parrot to the next idle response
+ */
+ void incParrotResponse();
+
+ /**
+ * Gets the index to use for parrot idle responses
+ */
+ int getParrotResponse() const;
/**
* Gets the game state node changed counter
diff --git a/engines/titanic/core/saveable_object.cpp b/engines/titanic/core/saveable_object.cpp
index 8bb8a92b7f..0257f6a087 100644
--- a/engines/titanic/core/saveable_object.cpp
+++ b/engines/titanic/core/saveable_object.cpp
@@ -955,6 +955,7 @@ DEFFN(CUseWithCharMsg);
DEFFN(CUseWithOtherMsg);
DEFFN(CVirtualKeyCharMsg);
DEFFN(CVisibleMsg);
+DEFFN(CCheckCodeWheelsMsg);
DEFFN(CEnterBombRoom);
DEFFN(CEnterBridge);
@@ -1538,6 +1539,7 @@ void CSaveableObject::initClassList() {
ADDFN(CUseWithOtherMsg, CMessage);
ADDFN(CVirtualKeyCharMsg, CMessage);
ADDFN(CVisibleMsg, CMessage);
+ ADDFN(CCheckCodeWheelsMsg, CMessage);
ADDFN(CMovePlayerTo, CGameObject);
ADDFN(CMovePlayerToFrom, CGameObject);
diff --git a/engines/titanic/core/tree_item.cpp b/engines/titanic/core/tree_item.cpp
index 97d06d7bbe..b9b9aca67f 100644
--- a/engines/titanic/core/tree_item.cpp
+++ b/engines/titanic/core/tree_item.cpp
@@ -274,7 +274,7 @@ CNamedItem *CTreeItem::findByName(const CString &name, bool subMatch) {
itemName.toLowercase();
if (subMatch) {
- if (itemName.left(name.size()).compareTo(nameLower))
+ if (!itemName.left(nameLower.size()).compareTo(nameLower))
return dynamic_cast<CNamedItem *>(treeItem);
} else {
if (!itemName.compareTo(nameLower))
diff --git a/engines/titanic/core/turn_on_turn_off.cpp b/engines/titanic/core/turn_on_turn_off.cpp
index a6051c7c6f..3c1e623b6e 100644
--- a/engines/titanic/core/turn_on_turn_off.cpp
+++ b/engines/titanic/core/turn_on_turn_off.cpp
@@ -58,7 +58,7 @@ void CTurnOnTurnOff::load(SimpleFile *file) {
bool CTurnOnTurnOff::TurnOn(CTurnOn *msg) {
if (!_isOn) {
if (_isBlocking)
- playMovie(_startFrameOn, _endFrameOn, MOVIE_GAMESTATE);
+ playMovie(_startFrameOn, _endFrameOn, MOVIE_WAIT_FOR_FINISH);
else
playMovie(_startFrameOn, _endFrameOn, MOVIE_NOTIFY_OBJECT);
_isOn = true;
@@ -70,7 +70,7 @@ bool CTurnOnTurnOff::TurnOn(CTurnOn *msg) {
bool CTurnOnTurnOff::TurnOff(CTurnOff *msg) {
if (_isOn) {
if (_isBlocking)
- playMovie(_startFrameOff, _endFrameOff, MOVIE_GAMESTATE);
+ playMovie(_startFrameOff, _endFrameOff, MOVIE_WAIT_FOR_FINISH);
else
playMovie(_startFrameOff, _endFrameOff, MOVIE_NOTIFY_OBJECT);
_isOn = false;
diff --git a/engines/titanic/core/view_item.cpp b/engines/titanic/core/view_item.cpp
index 9109bcc5b2..15d187e194 100644
--- a/engines/titanic/core/view_item.cpp
+++ b/engines/titanic/core/view_item.cpp
@@ -260,7 +260,7 @@ bool CViewItem::handleMouseMsg(CMouseMsg *msg, bool flag) {
CGameObject *gameObject = dynamic_cast<CGameObject *>(treeItem);
if (gameObject) {
if (gameObject->checkPoint(msg->_mousePos, false, true) &&
- (!flag || !gameObject->_field60)) {
+ (!flag || !gameObject->_handleMouseFlag)) {
if (gameObjects.size() < 256)
gameObjects.push_back(gameObject);
}
diff --git a/engines/titanic/game/arboretum_gate.cpp b/engines/titanic/game/arboretum_gate.cpp
index 2a79c31339..903f5efb54 100644
--- a/engines/titanic/game/arboretum_gate.cpp
+++ b/engines/titanic/game/arboretum_gate.cpp
@@ -275,27 +275,27 @@ bool CArboretumGate::TurnOff(CTurnOff *msg) {
if (!_disabled) {
switch (_seasonNum) {
case SEASON_SUMMER:
- playMovie(_startFrameSummerOff, _endFrameSummerOff, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameSummerOff, _endFrameSummerOff, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
break;
case SEASON_AUTUMN:
if (_gotSpeechCentre) {
- playMovie(_startFrameAutumnOff2, _endFrameAutumnOff2, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameAutumnOff2, _endFrameAutumnOff2, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
} else {
- playMovie(_startFrameAutumnOff1, _endFrameAutumnOff1, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameAutumnOff1, _endFrameAutumnOff1, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
break;
case SEASON_WINTER:
if (_gotSpeechCentre) {
- playMovie(_startFrameWinterOff2, _endFrameWinterOff2, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameWinterOff2, _endFrameWinterOff2, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
} else {
- playMovie(_startFrameWinterOff1, _endFrameWinterOff1, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameWinterOff1, _endFrameWinterOff1, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
break;
case SEASON_SPRING:
- playMovie(_startFrameSpringOff, _endFrameSpringOff, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameSpringOff, _endFrameSpringOff, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
break;
default:
@@ -303,7 +303,7 @@ bool CArboretumGate::TurnOff(CTurnOff *msg) {
}
_disabled = true;
- CArboretumGateMsg gateMsg;
+ CArboretumGateMsg gateMsg(1);
gateMsg.execute("Arboretum", nullptr, MSGFLAG_SCAN);
}
@@ -318,27 +318,27 @@ bool CArboretumGate::TurnOn(CTurnOn *msg) {
switch (_seasonNum) {
case SEASON_SUMMER:
- playMovie(_startFrameSummerOn, _endFrameSummerOn, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameSummerOn, _endFrameSummerOn, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
break;
case SEASON_AUTUMN:
if (_gotSpeechCentre) {
- playMovie(_startFrameAutumnOn2, _endFrameAutumnOn2, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameAutumnOn2, _endFrameAutumnOn2, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
} else {
- playMovie(_startFrameAutumnOn1, _endFrameAutumnOn1, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameAutumnOn1, _endFrameAutumnOn1, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
break;
case SEASON_WINTER:
if (_gotSpeechCentre) {
- playMovie(_startFrameWinterOn2, _endFrameWinterOn2, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameWinterOn2, _endFrameWinterOn2, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
} else {
- playMovie(_startFrameWinterOn1, _endFrameWinterOn1, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameWinterOn1, _endFrameWinterOn1, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
break;
case SEASON_SPRING:
- playMovie(_startFrameSpringOn, _endFrameSpringOn, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(_startFrameSpringOn, _endFrameSpringOn, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
break;
default:
diff --git a/engines/titanic/game/bomb.cpp b/engines/titanic/game/bomb.cpp
index f3f1129e22..17c10c5082 100644
--- a/engines/titanic/game/bomb.cpp
+++ b/engines/titanic/game/bomb.cpp
@@ -21,6 +21,7 @@
*/
#include "titanic/game/bomb.h"
+#include "titanic/game/code_wheel.h"
namespace Titanic {
@@ -36,19 +37,19 @@ BEGIN_MESSAGE_MAP(CBomb, CBackground)
ON_MESSAGE(SetFrameMsg)
END_MESSAGE_MAP()
-static const char *const WAVE_NAMES1[] = {
- "z#353.wav", "z#339.wav", "z#325.wav", "z#311.wav", "z#297.wav",
+const int CORRECT_WHEELS = 23;
+
+static const char *const HUNDREDS_WAVS[] = {
+ "", "z#353.wav", "z#339.wav", "z#325.wav", "z#311.wav", "z#297.wav",
"z#283.wav", "z#269.wav", "z#255.wav", "z#241.wav"
};
-static const char *const WAVE_NAMES2[] = {
+static const char *const HUNDREDS_AND_WAVS[] = {
"", "z#352.wav", "z#338.wav", "z#324.wav", "z#310.wav", "z#296.wav",
- "z#281.wav", "z#268.wav", "z#254.wav", "z#240.wav", "", "z#351.wav",
- "z#337.wav", "z#323.wav", "z#309.wav", "z#295.wav", "z#282.wav",
- "z#267.wav", "z#253.wav", "z#239.wav"
+ "z#281.wav", "z#268.wav", "z#254.wav", "z#240.wav"
};
-static const char *const WAVE_NAMES3[100] = {
+static const char *const COUNTDOWN_WAVS[100] = {
"bombcountdown_c0.wav", "z#355.wav", "z#341.wav", "z#327.wav", "z#313.wav",
"z#299.wav", "z#285.wav", "z#271.wav", "z#257.wav", "z#243.wav",
"z#354.wav", "z#350.wav", "z#349.wav", "z#348.wav", "z#347.wav",
@@ -72,28 +73,28 @@ static const char *const WAVE_NAMES3[100] = {
};
CBomb::CBomb() : CBackground() {
- _fieldE0 = 0;
- _fieldE4 = 0;
- _fieldE8 = 17;
- _fieldEC = 9;
- _fieldF0 = 0;
+ _active = false;
+ _numCorrectWheels = 0;
+ _tappedCtr = 17;
+ _hammerCtr = 9;
+ _commentCtr = 0;
_countdown = 999;
_soundHandle = 0;
- _fieldFC = 0;
+ _unusedHandle = 0;
_startingTicks = 0;
_volume = 60;
}
void CBomb::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldE0, indent);
- file->writeNumberLine(_fieldE4, indent);
- file->writeNumberLine(_fieldE8, indent);
- file->writeNumberLine(_fieldEC, indent);
- file->writeNumberLine(_fieldF0, indent);
+ file->writeNumberLine(_active, indent);
+ file->writeNumberLine(_numCorrectWheels, indent);
+ file->writeNumberLine(_tappedCtr, indent);
+ file->writeNumberLine(_hammerCtr, indent);
+ file->writeNumberLine(_commentCtr, indent);
file->writeNumberLine(_countdown, indent);
file->writeNumberLine(_soundHandle, indent);
- file->writeNumberLine(_fieldFC, indent);
+ file->writeNumberLine(_unusedHandle, indent);
file->writeNumberLine(_startingTicks, indent);
file->writeNumberLine(_volume, indent);
@@ -102,14 +103,14 @@ void CBomb::save(SimpleFile *file, int indent) {
void CBomb::load(SimpleFile *file) {
file->readNumber();
- _fieldE0 = file->readNumber();
- _fieldE4 = file->readNumber();
- _fieldE8 = file->readNumber();
- _fieldEC = file->readNumber();
- _fieldF0 = file->readNumber();
+ _active = file->readNumber();
+ _numCorrectWheels = file->readNumber();
+ _tappedCtr = file->readNumber();
+ _hammerCtr = file->readNumber();
+ _commentCtr = file->readNumber();
_countdown = file->readNumber();
_soundHandle = file->readNumber();
- _fieldFC = file->readNumber();
+ _unusedHandle = file->readNumber();
_startingTicks = file->readNumber();
_volume = file->readNumber();
@@ -117,34 +118,39 @@ void CBomb::load(SimpleFile *file) {
}
bool CBomb::StatusChangeMsg(CStatusChangeMsg *msg) {
- _fieldE4 += msg->_newStatus;
+ // Check whether the wheels are corect
+ CCheckCodeWheelsMsg checkMsg;
+ checkMsg.execute(findRoom(), nullptr, MSGFLAG_SCAN);
+
+ _numCorrectWheels = checkMsg._isCorrect ? CORRECT_WHEELS : 0;
- if (_fieldE4 == 23) {
+ if (_numCorrectWheels == CORRECT_WHEELS) {
+ // Nobody likes a smartass
startAnimTimer("Disarmed", 2000);
lockMouse();
}
- _fieldF0 %= 1000;
- if (!(_fieldF0 % 20) && _countdown < 995) {
+ _commentCtr = (_commentCtr % 1000) + 1;
+ if (!(_commentCtr % 20) && _countdown < 995) {
int val = getRandomNumber(5) + 25;
- if (_fieldF0 < 20 || _fieldF0 > 80)
+ if (_commentCtr < 20 || _commentCtr > 80)
val = 28;
CString name;
- switch (val - 25) {
- case 0:
+ switch (val) {
+ case 25:
name = "z#372.wav";
break;
- case 1:
+ case 26:
name = "z#371.wav";
break;
- case 2:
+ case 27:
name = "z#370.wav";
break;
- case 3:
+ case 28:
name = "z#369.wav";
break;
- case 4:
+ case 29:
name = "z#368.wav";
break;
default:
@@ -159,20 +165,22 @@ bool CBomb::StatusChangeMsg(CStatusChangeMsg *msg) {
}
bool CBomb::EnterViewMsg(CEnterViewMsg *msg) {
- _fieldE4 = 2;
+ // WORKAROUND: Don't keep resetting wheels
return true;
}
bool CBomb::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
playSound("z#62.wav");
- if (_fieldE0) {
+ if (_active) {
stopSound(_soundHandle);
- if (_fieldE4 < 23) {
- _fieldE8 = MIN(_fieldE8 + 1, 23);
+ //stopSound(_unusedHandle);
+
+ if (_numCorrectWheels < CORRECT_WHEELS) {
+ _tappedCtr = MIN(_tappedCtr + 1, 23);
CString name;
- switch (_fieldE8) {
+ switch (_tappedCtr) {
case 18:
name = "z#380.wav";
break;
@@ -198,7 +206,7 @@ bool CBomb::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
} else {
_soundHandle = playSound("z#389.wav", _volume);
- _fieldE0 = true;
+ _active = true;
CActMsg actMsg("Arm Bomb");
actMsg.execute("EndExplodeShip");
}
@@ -207,9 +215,9 @@ bool CBomb::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CBomb::EnterRoomMsg(CEnterRoomMsg *msg) {
- _fieldE8 = 17;
- _fieldEC = 9;
- _fieldF0 = 0;
+ _tappedCtr = 17;
+ _hammerCtr = 9;
+ _commentCtr = 0;
_startingTicks = getTicksCount();
return true;
}
@@ -219,11 +227,11 @@ bool CBomb::ActMsg(CActMsg *msg) {
playSound("z#63.wav");
stopSound(_soundHandle);
- if (_fieldEC < 17)
- ++_fieldEC;
+ if (_hammerCtr < 17)
+ ++_hammerCtr;
CString name;
- switch (_fieldEC) {
+ switch (_hammerCtr) {
case 10:
name = "z#388.wav";
break;
@@ -258,9 +266,19 @@ bool CBomb::ActMsg(CActMsg *msg) {
}
bool CBomb::TurnOn(CTurnOn *msg) {
- if (!_fieldE0) {
+ if (!_active) {
_soundHandle = playSound("z#389.wav", _volume);
- _fieldE0 = true;
+ _active = true;
+
+ // WORKAROUND: Only reset the code wheels back to 'O' value
+ // when first arming the bomb, not whenever the bomb view is entered
+ _numCorrectWheels = 2;
+ CRoomItem *room = findRoom();
+ for (CTreeItem *treeItem = room; treeItem; treeItem = treeItem->scan(room)) {
+ CodeWheel *codeWheel = dynamic_cast<CodeWheel *>(treeItem);
+ if (codeWheel)
+ codeWheel->reset();
+ }
CActMsg actMsg("Arm Bomb");
actMsg.execute("EndExplodeShip");
@@ -282,7 +300,7 @@ bool CBomb::TimerMsg(CTimerMsg *msg) {
CActMsg actMsg1("Disarm Bomb");
actMsg1.execute("EndExplodeShip");
- _fieldE0 = false;
+ _active = false;
CActMsg actMsg2("Titania.Node 5.N");
actMsg2.execute("BombNav");
actMsg2.execute("EnterBombNav");
@@ -294,49 +312,54 @@ bool CBomb::TimerMsg(CTimerMsg *msg) {
if (compareRoomNameTo("Titania")) {
if (msg->_actionVal == 1 && getRandomNumber(9) == 0) {
- if (!_fieldE0)
+ if (!_active)
return true;
CParrotSpeakMsg speakMsg("Bomb", "BombCountdown");
speakMsg.execute("PerchedParrot");
}
- if (_fieldE0) {
- if (isSoundActive(_soundHandle)) {
+ if (_active) {
+ if (!isSoundActive(_soundHandle)) {
if (msg->_actionVal == 0) {
addTimer(1, 1000, 0);
} else {
_soundHandle = 0;
- int section = _countdown / 100;
- int index = _countdown % 100;
+ int hundreds = _countdown / 100;
+ int remainder = _countdown % 100;
if (_countdown >= 100) {
- CString name1 = index ? WAVE_NAMES2[section] :
- WAVE_NAMES1[section];
- playSound(name1, _volume);
+ // Play "x hundred and" or just "x hundred"
+ CString hName = remainder ? HUNDREDS_AND_WAVS[hundreds] : HUNDREDS_WAVS[hundreds];
+ _soundHandle = playSound(hName, _volume);
}
- CString name2 = WAVE_NAMES3[index];
+ CString ctrName = COUNTDOWN_WAVS[remainder];
if (_countdown == 10) {
- name2 = "z#229.wav";
+ ctrName = "z#229.wav";
_countdown = 998;
}
+ // Play the sub-hundred portion of the countdown amount
if (_soundHandle > 0) {
- _soundHandle = queueSound(name2, _soundHandle, _volume);
+ _soundHandle = queueSound(ctrName, _soundHandle, _volume);
} else {
- _soundHandle = playSound(name2, _volume);
+ _soundHandle = playSound(ctrName, _volume);
}
+ // Reduce countdown and schedule another timer
--_countdown;
addTimer(0, 1000, 0);
}
} else {
+ // Bomb speech currently active, so schedule the method'
+ // to re-trigger after 100ms to check if speech is finished
addTimer(0, 100, 0);
}
}
} else {
- if (_fieldE0) {
+ // In rooms other than the bomb room
+ if (_active) {
--_countdown;
addTimer(6000);
@@ -350,7 +373,7 @@ bool CBomb::TimerMsg(CTimerMsg *msg) {
bool CBomb::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) {
if (msg->_stateNum == 10)
- msg->_stateVal = _fieldE0;
+ msg->_stateVal = _active ? 1 : 0;
return true;
}
diff --git a/engines/titanic/game/bomb.h b/engines/titanic/game/bomb.h
index f78c42cff0..c474abf554 100644
--- a/engines/titanic/game/bomb.h
+++ b/engines/titanic/game/bomb.h
@@ -40,14 +40,14 @@ class CBomb : public CBackground {
bool SetFrameMsg(CSetFrameMsg *msg);
DECLARE_MESSAGE_MAP;
private:
- int _fieldE0;
- int _fieldE4;
- int _fieldE8;
- int _fieldEC;
- int _fieldF0;
+ bool _active;
+ int _numCorrectWheels;
+ int _tappedCtr;
+ int _hammerCtr;
+ int _commentCtr;
int _countdown;
int _soundHandle;
- int _fieldFC;
+ int _unusedHandle;
int _startingTicks;
int _volume;
public:
diff --git a/engines/titanic/game/brain_slot.cpp b/engines/titanic/game/brain_slot.cpp
index 1518d9b0b3..c0eb145d59 100644
--- a/engines/titanic/game/brain_slot.cpp
+++ b/engines/titanic/game/brain_slot.cpp
@@ -33,14 +33,14 @@ BEGIN_MESSAGE_MAP(CBrainSlot, CGameObject)
ON_MESSAGE(MouseDragStartMsg)
END_MESSAGE_MAP()
-int CBrainSlot::_added;
+int CBrainSlot::_numAdded;
bool CBrainSlot::_woken;
void CBrainSlot::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_value1, indent);
+ file->writeNumberLine(_occupied, indent);
file->writeQuotedLine(_target, indent);
- file->writeNumberLine(_added, indent);
+ file->writeNumberLine(_numAdded, indent);
file->writeNumberLine(_woken, indent);
CGameObject::save(file, indent);
@@ -48,9 +48,9 @@ void CBrainSlot::save(SimpleFile *file, int indent) {
void CBrainSlot::load(SimpleFile *file) {
file->readNumber();
- _value1 = file->readNumber();
+ _occupied = file->readNumber();
_target = file->readString();
- _added = file->readNumber();
+ _numAdded = file->readNumber();
_woken = file->readNumber();
CGameObject::load(file);
@@ -58,12 +58,12 @@ void CBrainSlot::load(SimpleFile *file) {
bool CBrainSlot::SetFrameMsg(CSetFrameMsg *msg) {
loadFrame(msg->_frameNumber);
- _value1 = 1;
+ _occupied = true;
return true;
}
bool CBrainSlot::AddHeadPieceMsg(CAddHeadPieceMsg *msg) {
- _added = 1;
+ _numAdded++;
_cursorId = CURSOR_HAND;
CAddHeadPieceMsg addMsg("NULL");
@@ -87,21 +87,21 @@ bool CBrainSlot::AddHeadPieceMsg(CAddHeadPieceMsg *msg) {
if (addMsg._value != "NULL")
addMsg.execute("TitaniaControl");
- if (addMsg._value == "OlfactoryCentre")
+ if (msg->_value == "OlfactoryCentre")
loadFrame(2);
- else if (addMsg._value == "AuditoryCentre")
+ else if (msg->_value == "AuditoryCentre")
loadFrame(1);
- else if (addMsg._value == "SpeechCentre")
+ else if (msg->_value == "SpeechCentre")
loadFrame(3);
- else if (addMsg._value == "VisionCentre")
+ else if (msg->_value == "VisionCentre")
loadFrame(4);
- else if (addMsg._value == "CentralCore") {
+ else if (msg->_value == "CentralCore") {
CActMsg actMsg("Insert Central Core");
actMsg.execute("CentralCoreSlot");
}
_target = msg->_value;
- _value1 = 1;
+ _occupied = true;
return true;
}
@@ -124,7 +124,7 @@ bool CBrainSlot::ActMsg(CActMsg *msg) {
}
bool CBrainSlot::MouseDragStartMsg(CMouseDragStartMsg *msg) {
- if (!_value1 || _woken || !checkPoint(msg->_mousePos, false, true))
+ if (!_occupied || _woken || !checkPoint(msg->_mousePos, false, true))
return false;
_cursorId = CURSOR_ARROW;
@@ -134,14 +134,14 @@ bool CBrainSlot::MouseDragStartMsg(CMouseDragStartMsg *msg) {
takeMsg.execute("TitaniaControl");
loadFrame(isEquals("CentralCoreSlot") ? 21 : 0);
- _value1 = 0;
+ _occupied = false;
CPassOnDragStartMsg passMsg;
passMsg._mousePos = msg->_mousePos;
passMsg.execute(_target);
msg->_dragItem = getRoot()->findByName(_target);
- _added = 0;
+ _numAdded--;
return true;
}
diff --git a/engines/titanic/game/brain_slot.h b/engines/titanic/game/brain_slot.h
index 4d500cc59a..a85036303e 100644
--- a/engines/titanic/game/brain_slot.h
+++ b/engines/titanic/game/brain_slot.h
@@ -35,14 +35,14 @@ class CBrainSlot : public CGameObject {
bool ActMsg(CActMsg *msg);
bool MouseDragStartMsg(CMouseDragStartMsg *msg);
public:
- static int _added;
+ static int _numAdded;
static bool _woken;
public:
- int _value1;
+ bool _occupied;
CString _target;
public:
CLASSDEF;
- CBrainSlot() : CGameObject(), _value1(0) {}
+ CBrainSlot() : CGameObject(), _occupied(false) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/game/bridge_view.cpp b/engines/titanic/game/bridge_view.cpp
index 5b2b8809d9..e8d70c8c43 100644
--- a/engines/titanic/game/bridge_view.cpp
+++ b/engines/titanic/game/bridge_view.cpp
@@ -31,13 +31,13 @@ END_MESSAGE_MAP()
void CBridgeView::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_mode, indent);
+ file->writeNumberLine(_action, indent);
CBackground::save(file, indent);
}
void CBridgeView::load(SimpleFile *file) {
file->readNumber();
- _mode = file->readNumber();
+ _action = (BridgeAction)file->readNumber();
CBackground::load(file);
}
@@ -47,13 +47,13 @@ bool CBridgeView::ActMsg(CActMsg *msg) {
volumeMsg._secondsTransition = 1;
if (msg->_action == "End") {
- _mode = 4;
+ _action = BA_ENDING2;
petLockInput();
petHide();
setVisible(true);
playMovie(MOVIE_NOTIFY_OBJECT);
} else if (msg->_action == "Go") {
- _mode = 1;
+ _action = BA_GO;
setVisible(true);
volumeMsg._volume = 100;
volumeMsg.execute("EngineSounds");
@@ -65,11 +65,11 @@ bool CBridgeView::ActMsg(CActMsg *msg) {
onMsg.execute("EngineSounds");
if (msg->_action == "Cruise") {
- _mode = 2;
+ _action = BA_CRUISE;
setVisible(true);
playMovie(MOVIE_NOTIFY_OBJECT);
- } else if (msg->_action == "GoENd") {
- _mode = 3;
+ } else if (msg->_action == "GoEnd") {
+ _action = BA_ENDING1;
setVisible(true);
CChangeMusicMsg musicMsg;
musicMsg._flags = 1;
@@ -86,21 +86,21 @@ bool CBridgeView::MovieEndMsg(CMovieEndMsg *msg) {
CTurnOff offMsg;
offMsg.execute("EngineSounds");
- switch (_mode) {
- case 0:
- case 1:
+ switch (_action) {
+ case BA_GO:
+ case BA_CRUISE:
setVisible(false);
decTransitions();
break;
- case 2: {
+ case BA_ENDING1: {
setVisible(false);
CActMsg actMsg("End");
actMsg.execute("HomeSequence");
break;
}
- case 3:
+ case BA_ENDING2:
setVisible(false);
changeView("TheEnd.Node 3.N");
break;
diff --git a/engines/titanic/game/bridge_view.h b/engines/titanic/game/bridge_view.h
index 45cfa3f4c8..01bd6310ce 100644
--- a/engines/titanic/game/bridge_view.h
+++ b/engines/titanic/game/bridge_view.h
@@ -27,15 +27,19 @@
namespace Titanic {
+enum BridgeAction {
+ BA_NONE = 0, BA_GO = 1, BA_CRUISE = 2, BA_ENDING1 = 3, BA_ENDING2 = 4
+};
+
class CBridgeView : public CBackground {
DECLARE_MESSAGE_MAP;
bool ActMsg(CActMsg *msg);
bool MovieEndMsg(CMovieEndMsg *msg);
public:
- int _mode;
+ BridgeAction _action;
public:
CLASSDEF;
- CBridgeView() : CBackground(), _mode(0) {}
+ CBridgeView() : CBackground(), _action(BA_NONE) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/game/captains_wheel.cpp b/engines/titanic/game/captains_wheel.cpp
index 72d3cf70d9..1f0b177a67 100644
--- a/engines/titanic/game/captains_wheel.cpp
+++ b/engines/titanic/game/captains_wheel.cpp
@@ -34,17 +34,17 @@ BEGIN_MESSAGE_MAP(CCaptainsWheel, CBackground)
END_MESSAGE_MAP()
CCaptainsWheel::CCaptainsWheel() : CBackground(),
- _fieldE0(0), _fieldE4(0), _fieldE8(0), _fieldEC(0),
- _fieldF0(0), _fieldF4(0) {
+ _stopEnabled(false), _actionNum(0), _fieldE8(0),
+ _cruiseEnabled(false), _goEnabled(false), _fieldF4(0) {
}
void CCaptainsWheel::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldE0, indent);
- file->writeNumberLine(_fieldE4, indent);
+ file->writeNumberLine(_stopEnabled, indent);
+ file->writeNumberLine(_actionNum, indent);
file->writeNumberLine(_fieldE8, indent);
- file->writeNumberLine(_fieldEC, indent);
- file->writeNumberLine(_fieldF0, indent);
+ file->writeNumberLine(_cruiseEnabled, indent);
+ file->writeNumberLine(_goEnabled, indent);
file->writeNumberLine(_fieldF4, indent);
CBackground::save(file, indent);
@@ -52,19 +52,19 @@ void CCaptainsWheel::save(SimpleFile *file, int indent) {
void CCaptainsWheel::load(SimpleFile *file) {
file->readNumber();
- _fieldE0 = file->readNumber();
- _fieldE4 = file->readNumber();
+ _stopEnabled = file->readNumber();
+ _actionNum = file->readNumber();
_fieldE8 = file->readNumber();
- _fieldEC = file->readNumber();
- _fieldF0 = file->readNumber();
+ _cruiseEnabled = file->readNumber();
+ _goEnabled = file->readNumber();
_fieldF4 = file->readNumber();
CBackground::load(file);
}
bool CCaptainsWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- if (_fieldE0) {
- _fieldE0 = false;
+ if (_stopEnabled) {
+ _stopEnabled = false;
CTurnOff offMsg;
offMsg.execute(this);
playMovie(162, 168, 0);
@@ -76,11 +76,11 @@ bool CCaptainsWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CCaptainsWheel::LeaveViewMsg(CLeaveViewMsg *msg) {
- if (_fieldE0) {
- _fieldE0 = false;
+ if (_stopEnabled) {
+ _stopEnabled = false;
CTurnOff offMsg;
offMsg.execute(this);
- playMovie(162, 168, MOVIE_GAMESTATE);
+ playMovie(162, 168, MOVIE_WAIT_FOR_FINISH);
}
return true;
@@ -88,34 +88,34 @@ bool CCaptainsWheel::LeaveViewMsg(CLeaveViewMsg *msg) {
bool CCaptainsWheel::ActMsg(CActMsg *msg) {
if (msg->_action == "Spin") {
- if (_fieldE0) {
+ if (_stopEnabled) {
CTurnOn onMsg;
onMsg.execute("RatchetySound");
- playMovie(8, 142, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(8, 142, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
} else if (msg->_action == "Honk") {
- if (_fieldE0) {
- playMovie(150, 160, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ if (_stopEnabled) {
+ playMovie(150, 160, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
} else if (msg->_action == "Go") {
- if (!_fieldE0) {
+ if (!_stopEnabled) {
incTransitions();
- _fieldE0 = false;
- _fieldE4 = 1;
+ _stopEnabled = false;
+ _actionNum = 1;
CTurnOff offMsg;
offMsg.execute(this);
- playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
} else if (msg->_action == "Cruise") {
- if (_fieldE0) {
+ if (_stopEnabled) {
incTransitions();
- _fieldE0 = false;
- _fieldE4 = 2;
+ _stopEnabled = false;
+ _actionNum = 2;
CTurnOff offMsg;
offMsg.execute(this);
- playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
} else if (msg->_action == "SetDestin") {
playSound("a#44.wav");
@@ -124,9 +124,9 @@ bool CCaptainsWheel::ActMsg(CActMsg *msg) {
volumeMsg.execute("EngineSounds");
CTurnOn onMsg;
onMsg.execute("EngineSounds");
- _fieldF0 = 1;
+ _goEnabled = true;
} else if (msg->_action == "ClearDestin") {
- _fieldF0 = 0;
+ _goEnabled = false;
}
return true;
@@ -152,17 +152,17 @@ bool CCaptainsWheel::TurnOn(CTurnOn *msg) {
signalMsg.execute("WheelSpin");
signalMsg.execute("SeagullHorn");
- if (_fieldE0) {
+ if (_stopEnabled) {
signalMsg.execute("WheelStopButt");
signalMsg.execute("StopHotSpot");
}
- if (_fieldEC) {
+ if (_cruiseEnabled) {
signalMsg.execute("WheelCruiseButt");
signalMsg.execute("CruiseHotSpot");
}
- if (_fieldF0) {
+ if (_goEnabled) {
signalMsg.execute("WheelGoButt");
signalMsg.execute("GoHotSpot");
}
@@ -172,7 +172,7 @@ bool CCaptainsWheel::TurnOn(CTurnOn *msg) {
bool CCaptainsWheel::MovieEndMsg(CMovieEndMsg *msg) {
if (msg->_endFrame == 8) {
- _fieldE0 = true;
+ _stopEnabled = true;
CTurnOn onMsg;
onMsg.execute(this);
}
@@ -183,9 +183,9 @@ bool CCaptainsWheel::MovieEndMsg(CMovieEndMsg *msg) {
}
if (msg->_endFrame == 168) {
- switch (_fieldE4) {
+ switch (_actionNum) {
case 1: {
- CActMsg actMsg(starFn2() ? "GoEnd" : "Go");
+ CActMsg actMsg(starIsSolved() ? "GoEnd" : "Go");
actMsg.execute("GoSequence");
break;
}
@@ -200,7 +200,7 @@ bool CCaptainsWheel::MovieEndMsg(CMovieEndMsg *msg) {
break;
}
- _fieldE4 = 0;
+ _actionNum = 0;
}
return true;
diff --git a/engines/titanic/game/captains_wheel.h b/engines/titanic/game/captains_wheel.h
index 3aca45c21f..7dce1ac6ee 100644
--- a/engines/titanic/game/captains_wheel.h
+++ b/engines/titanic/game/captains_wheel.h
@@ -36,11 +36,11 @@ class CCaptainsWheel : public CBackground {
bool TurnOn(CTurnOn *msg);
bool MovieEndMsg(CMovieEndMsg *msg);
public:
- int _fieldE0;
- int _fieldE4;
+ bool _stopEnabled;
+ int _actionNum;
int _fieldE8;
- int _fieldEC;
- int _fieldF0;
+ bool _cruiseEnabled;
+ bool _goEnabled;
int _fieldF4;
public:
CLASSDEF;
diff --git a/engines/titanic/game/cdrom.cpp b/engines/titanic/game/cdrom.cpp
index 0d1cd3a6f2..d8d31ecc1a 100644
--- a/engines/titanic/game/cdrom.cpp
+++ b/engines/titanic/game/cdrom.cpp
@@ -38,21 +38,21 @@ CCDROM::CCDROM() : CGameObject() {
void CCDROM::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writePoint(_tempPos, indent);
+ file->writePoint(_centroid, indent);
CGameObject::save(file, indent);
}
void CCDROM::load(SimpleFile *file) {
file->readNumber();
- _tempPos = file->readPoint();
+ _centroid = file->readPoint();
CGameObject::load(file);
}
bool CCDROM::MouseDragStartMsg(CMouseDragStartMsg *msg) {
if (checkStartDragging(msg)) {
hideMouse();
- _tempPos = msg->_mousePos - _bounds;
- setPosition(msg->_mousePos - _tempPos);
+ _centroid = msg->_mousePos - _bounds;
+ setPosition(msg->_mousePos - _centroid);
return true;
} else {
return false;
@@ -77,7 +77,7 @@ bool CCDROM::MouseDragEndMsg(CMouseDragEndMsg *msg) {
}
bool CCDROM::MouseDragMoveMsg(CMouseDragMoveMsg *msg) {
- setPosition(msg->_mousePos - _tempPos);
+ setPosition(msg->_mousePos - _centroid);
return true;
}
diff --git a/engines/titanic/game/cdrom.h b/engines/titanic/game/cdrom.h
index 017914830c..12175f6450 100644
--- a/engines/titanic/game/cdrom.h
+++ b/engines/titanic/game/cdrom.h
@@ -36,7 +36,7 @@ class CCDROM : public CGameObject {
bool MouseDragMoveMsg(CMouseDragMoveMsg *msg);
bool ActMsg(CActMsg *msg);
private:
- Point _tempPos;
+ Point _centroid;
public:
CLASSDEF;
CCDROM();
diff --git a/engines/titanic/game/chicken_dispensor.cpp b/engines/titanic/game/chicken_dispensor.cpp
index 8a56f43fff..89873dcc4d 100644
--- a/engines/titanic/game/chicken_dispensor.cpp
+++ b/engines/titanic/game/chicken_dispensor.cpp
@@ -89,10 +89,10 @@ bool CChickenDispensor::StatusChangeMsg(CStatusChangeMsg *msg) {
setVisible(true);
if (_disabled) {
- playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("z#400.wav");
} else {
- playMovie(12, 16, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(12, 16, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
break;
@@ -186,7 +186,7 @@ bool CChickenDispensor::MouseDragStartMsg(CMouseDragStartMsg *msg) {
bool CChickenDispensor::TurnOff(CTurnOff *msg) {
if (getMovieFrame() != 16)
setVisible(false);
- playMovie(16, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(16, 12, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_dispensed = false;
return true;
diff --git a/engines/titanic/game/code_wheel.cpp b/engines/titanic/game/code_wheel.cpp
index 441fddec02..1df99ae749 100644
--- a/engines/titanic/game/code_wheel.cpp
+++ b/engines/titanic/game/code_wheel.cpp
@@ -30,17 +30,25 @@ BEGIN_MESSAGE_MAP(CodeWheel, CBomb)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(MouseButtonUpMsg)
ON_MESSAGE(MovieEndMsg)
+ ON_MESSAGE(CheckCodeWheelsMsg)
END_MESSAGE_MAP()
-CodeWheel::CodeWheel() : CBomb(), _field108(0), _state(4),
- _field110(0), _field114(0), _field118(0) {
+static const int START_FRAMES[15] = {
+ 0, 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66
+};
+static const int END_FRAMES[15] = {
+ 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66, 70
+};
+
+CodeWheel::CodeWheel() : CBomb(), _correctValue(0), _value(4),
+ _matched(false), _field114(0), _field118(0) {
}
void CodeWheel::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_field108, indent);
- file->writeNumberLine(_state, indent);
- file->writeNumberLine(_field110, indent);
+ file->writeNumberLine(_correctValue, indent);
+ file->writeNumberLine(_value, indent);
+ file->writeNumberLine(_matched, indent);
if (g_vm->isGerman()) {
file->writeNumberLine(_field114, indent);
file->writeNumberLine(_field118, indent);
@@ -51,9 +59,9 @@ void CodeWheel::save(SimpleFile *file, int indent) {
void CodeWheel::load(SimpleFile *file) {
file->readNumber();
- _field108 = file->readNumber();
- _state = file->readNumber();
- _field110 = file->readNumber();
+ _correctValue = file->readNumber();
+ _value = file->readNumber();
+ _matched = file->readNumber();
if (g_vm->isGerman()) {
_field114 = file->readNumber();
_field118 = file->readNumber();
@@ -63,29 +71,24 @@ void CodeWheel::load(SimpleFile *file) {
}
bool CodeWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- static const int START_FRAMES[15] = {
- 0, 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66
- };
- static const int END_FRAMES[15] = {
- 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66, 70
- };
-
int yp = _bounds.top + _bounds.height() / 2;
+ _matched = false;
+
if (msg->_mousePos.y > yp) {
- if (_state == _field108)
- _field110 = true;
+ if (_value == _correctValue)
+ _matched = true;
- _state = (_state + 1) % 15;
- playMovie(START_FRAMES[_state], END_FRAMES[_state],
- MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ _value = (_value + 1) % 15;
+ playMovie(START_FRAMES[_value], END_FRAMES[_value],
+ MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
} else {
- if (_state == _field108)
- _field110 = true;
+ if (_value == _correctValue)
+ _matched = true;
- playMovie(START_FRAMES[14 - _state] + 68, END_FRAMES[14 - _state] + 68,
- MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(START_FRAMES[14 - _value] + 68, END_FRAMES[14 - _value] + 68,
+ MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
- _state = (_state <= 0) ? 14 : _state - 1;
+ _value = (_value <= 0) ? 14 : _value - 1;
}
playSound("z#59.wav");
@@ -93,8 +96,8 @@ bool CodeWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CodeWheel::EnterViewMsg(CEnterViewMsg *msg) {
- loadFrame(24);
- _state = 4;
+ // WORKAROUND: Don't keep resetting code wheels back to default
+ loadFrame(END_FRAMES[_value]);
return true;
}
@@ -104,15 +107,18 @@ bool CodeWheel::MouseButtonUpMsg(CMouseButtonUpMsg *msg) {
bool CodeWheel::MovieEndMsg(CMovieEndMsg *msg) {
sleep(200);
+
+ // Signal that a code wheel has changed
CStatusChangeMsg changeMsg;
- changeMsg._newStatus = 0;
- if (_field110)
- changeMsg._newStatus = -1;
- if (_field108 == _state)
- changeMsg._newStatus = 1;
changeMsg.execute("Bomb");
return true;
}
+bool CodeWheel::CheckCodeWheelsMsg(CCheckCodeWheelsMsg *msg) {
+ if (_value != _correctValue)
+ msg->_isCorrect = false;
+ return true;
+}
+
} // End of namespace Titanic
diff --git a/engines/titanic/game/code_wheel.h b/engines/titanic/game/code_wheel.h
index de246f56c4..3d19eeb53c 100644
--- a/engines/titanic/game/code_wheel.h
+++ b/engines/titanic/game/code_wheel.h
@@ -33,10 +33,11 @@ class CodeWheel : public CBomb {
bool EnterViewMsg(CEnterViewMsg *msg);
bool MouseButtonUpMsg(CMouseButtonUpMsg *msg);
bool MovieEndMsg(CMovieEndMsg *msg);
+ bool CheckCodeWheelsMsg(CCheckCodeWheelsMsg *msg);
private:
- int _field108;
- int _state;
- int _field110;
+ int _correctValue;
+ int _value;
+ bool _matched;
// German specific fields
int _field114;
int _field118;
@@ -53,6 +54,11 @@ public:
* Load the data for the class from file
*/
virtual void load(SimpleFile *file);
+
+ /**
+ * Resets a code wheel back to the default 'O' value
+ */
+ void reset() { _value = 4; }
};
} // End of namespace Titanic
diff --git a/engines/titanic/game/computer_screen.cpp b/engines/titanic/game/computer_screen.cpp
index 98bef6eb63..7d549d0497 100644
--- a/engines/titanic/game/computer_screen.cpp
+++ b/engines/titanic/game/computer_screen.cpp
@@ -47,10 +47,10 @@ void CComputerScreen::load(SimpleFile *file) {
bool CComputerScreen::ActMsg(CActMsg *msg) {
if (msg->_action == "newCD1" || msg->_action == "newCD2") {
- playMovie(27, 53, MOVIE_GAMESTATE);
- playMovie(19, 26, MOVIE_GAMESTATE);
+ playMovie(27, 53, MOVIE_WAIT_FOR_FINISH);
+ playMovie(19, 26, MOVIE_WAIT_FOR_FINISH);
} else if (msg->_action == "newSTCD") {
- playMovie(0, 18, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(0, 18, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
return true;
diff --git a/engines/titanic/game/end_explode_ship.cpp b/engines/titanic/game/end_explode_ship.cpp
index 10c80f5863..6253a4df02 100644
--- a/engines/titanic/game/end_explode_ship.cpp
+++ b/engines/titanic/game/end_explode_ship.cpp
@@ -33,25 +33,25 @@ END_MESSAGE_MAP()
void CEndExplodeShip::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_value1, indent);
- file->writeNumberLine(_value2, indent);
+ file->writeNumberLine(_isExploding, indent);
+ file->writeNumberLine(_unused5, indent);
CGameObject::save(file, indent);
}
void CEndExplodeShip::load(SimpleFile *file) {
file->readNumber();
- _value1 = file->readNumber();
- _value2 = file->readNumber();
+ _isExploding = file->readNumber();
+ _unused5 = file->readNumber();
CGameObject::load(file);
}
bool CEndExplodeShip::ActMsg(CActMsg *msg) {
if (msg->_action == "Arm Bomb") {
- _value1 = 1;
+ _isExploding = true;
} else if (msg->_action == "Disarm Bomb") {
- _value1 = 0;
+ _isExploding = false;
} else if (msg->_action == "TakeOff") {
loadSound("a#31.wav");
loadSound("a#14.wav");
@@ -67,12 +67,12 @@ bool CEndExplodeShip::TimerMsg(CTimerMsg *msg) {
setVisible(true);
playMovie(0, 449, 0);
movieEvent(58);
- playMovie(516, _value1 ? 550 : 551, MOVIE_NOTIFY_OBJECT);
+ playMovie(516, _isExploding ? 550 : 551, MOVIE_NOTIFY_OBJECT);
}
if (msg->_actionVal == 3) {
setGlobalSoundVolume(-4, 2, -1);
- CActMsg actMsg(_value1 ? "ExplodeCredits" : "Credits");
+ CActMsg actMsg(_isExploding ? "ExplodeCredits" : "Credits");
actMsg.execute("EndGameCredits");
}
diff --git a/engines/titanic/game/end_explode_ship.h b/engines/titanic/game/end_explode_ship.h
index c48f822af8..592741e5c0 100644
--- a/engines/titanic/game/end_explode_ship.h
+++ b/engines/titanic/game/end_explode_ship.h
@@ -34,10 +34,11 @@ class CEndExplodeShip : public CGameObject {
bool MovieEndMsg(CMovieEndMsg *msg);
bool MovieFrameMsg(CMovieFrameMsg *msg);
public:
- int _value1, _value2;
+ bool _isExploding;
+ int _unused5;
public:
CLASSDEF;
- CEndExplodeShip() : CGameObject(), _value1(0), _value2(0) {}
+ CEndExplodeShip() : CGameObject(), _isExploding(false), _unused5(0) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/game/end_game_credits.cpp b/engines/titanic/game/end_game_credits.cpp
index 4edcef0a17..c816f22706 100644
--- a/engines/titanic/game/end_game_credits.cpp
+++ b/engines/titanic/game/end_game_credits.cpp
@@ -31,7 +31,7 @@ BEGIN_MESSAGE_MAP(CEndGameCredits, CGameObject)
ON_MESSAGE(TimerMsg)
END_MESSAGE_MAP()
-CEndGameCredits::CEndGameCredits() : CGameObject(), _flag(0),
+CEndGameCredits::CEndGameCredits() : CGameObject(), _flag(false),
_frameRange(0, 28) {
}
@@ -75,6 +75,7 @@ bool CEndGameCredits::MovieEndMsg(CMovieEndMsg *msg) {
visibleMsg.execute("CreditsBackdrop");
}
+ addTimer(4000, 0);
return true;
}
diff --git a/engines/titanic/game/end_sequence_control.cpp b/engines/titanic/game/end_sequence_control.cpp
index 033a7752a3..0f3a97c3a2 100644
--- a/engines/titanic/game/end_sequence_control.cpp
+++ b/engines/titanic/game/end_sequence_control.cpp
@@ -77,7 +77,7 @@ bool CEndSequenceControl::EnterRoomMsg(CEnterRoomMsg *msg) {
bool CEndSequenceControl::EnterViewMsg(CEnterViewMsg *msg) {
movieSetAudioTiming(true);
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
return true;
}
diff --git a/engines/titanic/game/fan_control.cpp b/engines/titanic/game/fan_control.cpp
index ca664764ea..7ed22fd560 100644
--- a/engines/titanic/game/fan_control.cpp
+++ b/engines/titanic/game/fan_control.cpp
@@ -121,7 +121,7 @@ bool CFanControl::StatusChangeMsg(CStatusChangeMsg *msg) {
// It's puret time
incTransitions();
_starlingsDying = true;
- playMovie(12, 18, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(12, 18, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else {
playMovie(12, 18, 0);
}
diff --git a/engines/titanic/game/games_console.cpp b/engines/titanic/game/games_console.cpp
index 40311f70ee..6c13f4b862 100644
--- a/engines/titanic/game/games_console.cpp
+++ b/engines/titanic/game/games_console.cpp
@@ -56,7 +56,7 @@ bool CGamesConsole::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
bool CGamesConsole::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_active) {
_active = false;
- playMovie(23, 44, MOVIE_GAMESTATE);
+ playMovie(23, 44, MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/glass_smasher.cpp b/engines/titanic/game/glass_smasher.cpp
index 2123f2dfd0..7de034c2ee 100644
--- a/engines/titanic/game/glass_smasher.cpp
+++ b/engines/titanic/game/glass_smasher.cpp
@@ -42,7 +42,7 @@ void CGlassSmasher::load(SimpleFile *file) {
bool CGlassSmasher::StatusChangeMsg(CStatusChangeMsg *msg) {
setVisible(true);
playSound("b#40.wav");
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
return true;
}
diff --git a/engines/titanic/game/gondolier/gondolier_base.cpp b/engines/titanic/game/gondolier/gondolier_base.cpp
index f3dc31c9f5..8b753ec264 100644
--- a/engines/titanic/game/gondolier/gondolier_base.cpp
+++ b/engines/titanic/game/gondolier/gondolier_base.cpp
@@ -28,45 +28,45 @@ BEGIN_MESSAGE_MAP(CGondolierBase, CGameObject)
ON_MESSAGE(PuzzleSolvedMsg)
END_MESSAGE_MAP()
-int CGondolierBase::_v1;
+bool CGondolierBase::_chestOpen;
bool CGondolierBase::_puzzleSolved;
int CGondolierBase::_volume1;
int CGondolierBase::_v4;
-int CGondolierBase::_v5;
int CGondolierBase::_volume2;
int CGondolierBase::_v7;
-int CGondolierBase::_v8;
-int CGondolierBase::_v9;
-int CGondolierBase::_v10;
+bool CGondolierBase::_rightSliderHooked;
+bool CGondolierBase::_leftSliderHooked;
+bool CGondolierBase::_priorLeftSliderHooked;
+bool CGondolierBase::_priorRightSliderHooked;
void CGondolierBase::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_v1, indent);
+ file->writeNumberLine(_chestOpen, indent);
file->writeNumberLine(_puzzleSolved, indent);
file->writeNumberLine(_volume1, indent);
file->writeNumberLine(_v4, indent);
- file->writeNumberLine(_v5, indent);
+ file->writeNumberLine(_rightSliderHooked, indent);
file->writeNumberLine(_volume2, indent);
file->writeNumberLine(_v7, indent);
- file->writeNumberLine(_v8, indent);
- file->writeNumberLine(_v9, indent);
- file->writeNumberLine(_v10, indent);
+ file->writeNumberLine(_leftSliderHooked, indent);
+ file->writeNumberLine(_priorLeftSliderHooked, indent);
+ file->writeNumberLine(_priorRightSliderHooked, indent);
CGameObject::save(file, indent);
}
void CGondolierBase::load(SimpleFile *file) {
file->readNumber();
- _v1 = file->readNumber();
+ _chestOpen = file->readNumber();
_puzzleSolved = file->readNumber();
_volume1 = file->readNumber();
_v4 = file->readNumber();
- _v5 = file->readNumber();
+ _rightSliderHooked = file->readNumber();
_volume2 = file->readNumber();
_v7 = file->readNumber();
- _v8 = file->readNumber();
- _v9 = file->readNumber();
- _v10 = file->readNumber();
+ _leftSliderHooked = file->readNumber();
+ _priorLeftSliderHooked = file->readNumber();
+ _priorRightSliderHooked = file->readNumber();
CGameObject::load(file);
}
diff --git a/engines/titanic/game/gondolier/gondolier_base.h b/engines/titanic/game/gondolier/gondolier_base.h
index 06d77ba85f..3b5df9f371 100644
--- a/engines/titanic/game/gondolier/gondolier_base.h
+++ b/engines/titanic/game/gondolier/gondolier_base.h
@@ -31,16 +31,16 @@ class CGondolierBase : public CGameObject {
DECLARE_MESSAGE_MAP;
bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg);
protected:
- static int _v1;
+ static bool _chestOpen;
static bool _puzzleSolved;
static int _volume1;
static int _v4;
- static int _v5;
static int _volume2;
static int _v7;
- static int _v8;
- static int _v9;
- static int _v10;
+ static bool _leftSliderHooked;
+ static bool _rightSliderHooked;
+ static bool _priorLeftSliderHooked;
+ static bool _priorRightSliderHooked;
public:
CLASSDEF;
diff --git a/engines/titanic/game/gondolier/gondolier_chest.cpp b/engines/titanic/game/gondolier/gondolier_chest.cpp
index cf6656732b..6058b582f7 100644
--- a/engines/titanic/game/gondolier/gondolier_chest.cpp
+++ b/engines/titanic/game/gondolier/gondolier_chest.cpp
@@ -41,13 +41,13 @@ void CGondolierChest::load(SimpleFile *file) {
}
bool CGondolierChest::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- if (!_v1)
+ if (!_chestOpen)
playMovie(0, 14, MOVIE_NOTIFY_OBJECT);
else if (msg->_mousePos.y < 330)
return false;
- else if (!_v8 && !_v5) {
+ else if (!_leftSliderHooked && !_rightSliderHooked) {
playMovie(14, 29, 0);
- _v1 = 0;
+ _chestOpen = false;
}
return true;
@@ -55,7 +55,7 @@ bool CGondolierChest::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
bool CGondolierChest::MovieEndMsg(CMovieEndMsg *msg) {
if (msg->_endFrame == 14)
- _v1 = 1;
+ _chestOpen = true;
return true;
}
diff --git a/engines/titanic/game/gondolier/gondolier_mixer.cpp b/engines/titanic/game/gondolier/gondolier_mixer.cpp
index fc71ddd357..205d1f42da 100644
--- a/engines/titanic/game/gondolier/gondolier_mixer.cpp
+++ b/engines/titanic/game/gondolier/gondolier_mixer.cpp
@@ -141,7 +141,7 @@ bool CGondolierMixer::SignalObject(CSignalObject *msg) {
if (msg->_strValue == "Fly") {
_v4 = CLIP(msg->_numValue, 0, 10);
- if (!_v8) {
+ if (!_leftSliderHooked) {
_v7 = 10 - _v4;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = _v7;
@@ -152,7 +152,7 @@ bool CGondolierMixer::SignalObject(CSignalObject *msg) {
if (msg->_strValue == "Tos") {
_v7 = CLIP(msg->_numValue, 0, 10);
- if (!_v5) {
+ if (!_rightSliderHooked) {
_v4 = 10 - _v7;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = _v4;
@@ -160,7 +160,7 @@ bool CGondolierMixer::SignalObject(CSignalObject *msg) {
}
}
- if (!_v4 && !_v7 && _v5 && _v8) {
+ if (!_v4 && !_v7 && _rightSliderHooked && _leftSliderHooked) {
_puzzleSolved = true;
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
diff --git a/engines/titanic/game/gondolier/gondolier_slider.cpp b/engines/titanic/game/gondolier/gondolier_slider.cpp
index e7ca61de9c..b5edac57d4 100644
--- a/engines/titanic/game/gondolier/gondolier_slider.cpp
+++ b/engines/titanic/game/gondolier/gondolier_slider.cpp
@@ -24,7 +24,10 @@
namespace Titanic {
-static const int ARRAY[11] = { 0, 0, 1, 4, 9, 15, 21, 27, 32, 35, 36 };
+/**
+ * Y offsets within slider for each successive thumbnail position
+ */
+static const int Y_OFFSETS[11] = { 0, 0, 1, 4, 9, 15, 21, 27, 32, 35, 36 };
BEGIN_MESSAGE_MAP(CGondolierSlider, CGondolierBase)
ON_MESSAGE(MouseButtonDownMsg)
@@ -40,86 +43,66 @@ BEGIN_MESSAGE_MAP(CGondolierSlider, CGondolierBase)
END_MESSAGE_MAP()
CGondolierSlider::CGondolierSlider() : CGondolierBase(),
- _fieldBC(0), _fieldC0(0), _fieldC4(0), _fieldC8(0),
- _arrayIndex(0), _string1("NULL"), _fieldFC(0), _field118(0) {
+ _sliderIndex(0), _stringUnused("NULL"), _sliderNum(0), _dragging(false) {
}
void CGondolierSlider::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldBC, indent);
- file->writeNumberLine(_fieldC0, indent);
- file->writeNumberLine(_fieldC4, indent);
- file->writeNumberLine(_fieldC8, indent);
- file->writeNumberLine(_sliderRect1.left, indent);
- file->writeNumberLine(_sliderRect1.top, indent);
- file->writeNumberLine(_sliderRect1.right, indent);
- file->writeNumberLine(_sliderRect1.bottom, indent);
- file->writeNumberLine(_sliderRect2.left, indent);
- file->writeNumberLine(_sliderRect2.top, indent);
- file->writeNumberLine(_sliderRect2.right, indent);
- file->writeNumberLine(_sliderRect2.bottom, indent);
- file->writeNumberLine(_sliderRect1.left, indent);
- file->writeQuotedLine(_string1, indent);
- file->writeNumberLine(_fieldFC, indent);
- file->writeQuotedLine(_string2, indent);
- file->writeQuotedLine(_string3, indent);
- file->writeNumberLine(_field118, indent);
+ file->writeRect(_rectUnused, indent);
+ file->writeRect(_thumbRect, indent);
+ file->writeRect(_defaultThumbRect, indent);
+ file->writeNumberLine(_sliderIndex, indent);
+ file->writeQuotedLine(_stringUnused, indent);
+ file->writeNumberLine(_sliderNum, indent);
+ file->writeQuotedLine(_armName, indent);
+ file->writeQuotedLine(_signalTarget, indent);
+ file->writeNumberLine(_dragging, indent);
CGondolierBase::save(file, indent);
}
void CGondolierSlider::load(SimpleFile *file) {
file->readNumber();
- _fieldBC = file->readNumber();
- _fieldC0 = file->readNumber();
- _fieldC4 = file->readNumber();
- _fieldC8 = file->readNumber();
- _sliderRect1.left = file->readNumber();
- _sliderRect1.top = file->readNumber();
- _sliderRect1.right = file->readNumber();
- _sliderRect1.bottom = file->readNumber();
- _sliderRect2.left = file->readNumber();
- _sliderRect2.top = file->readNumber();
- _sliderRect2.right = file->readNumber();
- _sliderRect2.bottom = file->readNumber();
- _arrayIndex = file->readNumber();
- _string1 = file->readString();
- _fieldFC = file->readNumber();
- _string2 = file->readString();
- _string3 = file->readString();
- _field118 = file->readNumber();
+ _rectUnused = file->readRect();
+ _thumbRect = file->readRect();
+ _defaultThumbRect = file->readRect();
+ _sliderIndex = file->readNumber();
+ _stringUnused = file->readString();
+ _sliderNum = file->readNumber();
+ _armName = file->readString();
+ _signalTarget = file->readString();
+ _dragging = file->readNumber();
CGondolierBase::load(file);
}
bool CGondolierSlider::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- if (!_v1)
+ if (!_chestOpen)
return false;
- if (_fieldFC ? _v5 : _v8)
+ if (_sliderNum ? _rightSliderHooked : _leftSliderHooked)
return false;
- return _sliderRect1.contains(msg->_mousePos);
+ return _thumbRect.contains(msg->_mousePos);
}
bool CGondolierSlider::MouseDragMoveMsg(CMouseDragMoveMsg *msg) {
- if (!(_fieldFC ? _v5 : _v8)) {
+ if (!(_sliderNum ? _rightSliderHooked : _leftSliderHooked)) {
int minVal = 0x7FFFFFFF;
int foundIndex = -1;
- int yp = (_sliderRect2.top + _sliderRect2.bottom) / 2
+ int yp = (_defaultThumbRect.top + _defaultThumbRect.bottom) / 2
+ _bounds.top - msg->_mousePos.y;
for (int idx = 0; idx < 11; ++idx) {
- int yv = yp + ARRAY[idx];
- if (yv < 0)
- yv = -yv;
- if (yv < minVal) {
- minVal = yv;
+ int yDiff = ABS(yp + Y_OFFSETS[idx]);
+
+ if (yDiff < minVal) {
+ minVal = yDiff;
foundIndex = idx;
}
}
if (foundIndex >= 0) {
- _arrayIndex = foundIndex;
+ _sliderIndex = foundIndex;
CSignalObject signalMsg;
signalMsg.execute(this);
}
@@ -135,70 +118,70 @@ bool CGondolierSlider::EnterViewMsg(CEnterViewMsg *msg) {
}
bool CGondolierSlider::MouseDragStartMsg(CMouseDragStartMsg *msg) {
- if (!_v1)
+ if (!_chestOpen)
return false;
- if (_fieldFC ? _v5 : _v8)
+ if (_sliderNum ? _rightSliderHooked : _leftSliderHooked)
return false;
- _field118 = checkStartDragging(msg);
- return _field118;
+ _dragging = checkStartDragging(msg);
+ return _dragging;
}
bool CGondolierSlider::StatusChangeMsg(CStatusChangeMsg *msg) {
- _arrayIndex = CLIP(10 - msg->_newStatus, 0, 10);
- _sliderRect1 = _sliderRect2;
- _sliderRect1.translate(_bounds.left, _bounds.top);
- _sliderRect1.translate(0, ARRAY[_arrayIndex]);
+ _sliderIndex = CLIP(10 - msg->_newStatus, 0, 10);
+ _thumbRect = _defaultThumbRect;
+ _thumbRect.translate(_bounds.left, _bounds.top);
+ _thumbRect.translate(0, Y_OFFSETS[_sliderIndex]);
- loadFrame(_arrayIndex);
+ loadFrame(_sliderIndex);
return true;
}
bool CGondolierSlider::MouseDragEndMsg(CMouseDragEndMsg *msg) {
- _field118 = false;
+ _dragging = false;
return true;
}
bool CGondolierSlider::IsHookedOnMsg(CIsHookedOnMsg *msg) {
- if (_fieldFC ? _v5 : _v8)
+ if (_sliderNum ? _rightSliderHooked : _leftSliderHooked)
return false;
- if (!_sliderRect1.intersects(msg->_rect)) {
- _string2 = CString();
- msg->_result = false;
+ if (!_thumbRect.intersects(msg->_rect)) {
+ _armName = CString();
+ msg->_isHooked = false;
} else {
- _string2 = _string1;
- if (_fieldFC) {
- _v5 = _v9 = 1;
+ _armName = msg->_armName;
+ if (_sliderNum) {
+ _rightSliderHooked = _priorLeftSliderHooked = true;
} else {
- _v8 = _v10 = 1;
+ _leftSliderHooked = _priorRightSliderHooked = true;
}
- msg->_result = true;
+ msg->_isHooked = true;
}
return true;
}
bool CGondolierSlider::FrameMsg(CFrameMsg *msg) {
- if (_fieldFC ? _v5 : _v8) {
- if (_arrayIndex < 10) {
- ++_arrayIndex;
+ if (_sliderNum ? _rightSliderHooked : _leftSliderHooked) {
+ if (_sliderIndex < 10) {
+ ++_sliderIndex;
CSignalObject signalMsg;
signalMsg.execute(this);
int yp = 0;
- if (_arrayIndex > 0)
- yp = ARRAY[_arrayIndex] - ARRAY[_arrayIndex - 1];
+ if (_sliderIndex > 0)
+ yp = Y_OFFSETS[_sliderIndex] - Y_OFFSETS[_sliderIndex - 1];
- if (!_string2.empty()) {
+ if (!_armName.empty()) {
CTranslateObjectMsg transMsg;
transMsg._delta = Point(0, yp);
- transMsg.execute(_string2);
+ transMsg.execute(_armName);
}
}
- } else if (_fieldFC ? _v10 : _v9) {
- if (!_field118 && !_puzzleSolved && _arrayIndex > 0) {
+ } else if (_sliderNum ? _priorRightSliderHooked : _priorLeftSliderHooked) {
+ if (!_dragging && !_puzzleSolved && _sliderIndex > 0) {
CSignalObject signalMsg;
signalMsg.execute(this);
}
@@ -208,28 +191,28 @@ bool CGondolierSlider::FrameMsg(CFrameMsg *msg) {
}
bool CGondolierSlider::SignalObject(CSignalObject *msg) {
- _arrayIndex = CLIP(_arrayIndex, 0, 10);
- _sliderRect1 = _sliderRect2;
- _sliderRect1.translate(_bounds.left, _bounds.top);
- _sliderRect1.translate(0, ARRAY[_arrayIndex]);
- loadFrame(_arrayIndex);
+ _sliderIndex = CLIP(_sliderIndex, 0, 10);
+ _thumbRect = _defaultThumbRect;
+ _thumbRect.translate(_bounds.left, _bounds.top);
+ _thumbRect.translate(0, Y_OFFSETS[_sliderIndex]);
+ loadFrame(_sliderIndex);
CSignalObject signalMsg;
- signalMsg._numValue = 10 - _arrayIndex;
- signalMsg._strValue = _fieldFC ? "Fly" : "Tos";
- signalMsg.execute(_string3);
+ signalMsg._numValue = 10 - _sliderIndex;
+ signalMsg._strValue = _sliderNum ? "Fly" : "Tos";
+ signalMsg.execute(_signalTarget);
return true;
}
bool CGondolierSlider::ActMsg(CActMsg *msg) {
if (msg->_action == "Unhook") {
- if (_fieldFC) {
- _v5 = _v9 = 0;
- _v10 = _v8;
+ if (_sliderNum) {
+ _rightSliderHooked = _priorLeftSliderHooked = false;
+ _priorRightSliderHooked = _leftSliderHooked;
} else {
- _v8 = _v10 = 0;
- _v9 = _v5;
+ _leftSliderHooked = _priorRightSliderHooked = false;
+ _priorLeftSliderHooked = _rightSliderHooked;
}
}
diff --git a/engines/titanic/game/gondolier/gondolier_slider.h b/engines/titanic/game/gondolier/gondolier_slider.h
index d1562f5b2d..0679c0d993 100644
--- a/engines/titanic/game/gondolier/gondolier_slider.h
+++ b/engines/titanic/game/gondolier/gondolier_slider.h
@@ -40,18 +40,15 @@ class CGondolierSlider : public CGondolierBase {
bool SignalObject(CSignalObject *msg);
bool ActMsg(CActMsg *msg);
private:
- int _fieldBC;
- int _fieldC0;
- int _fieldC4;
- int _fieldC8;
- Rect _sliderRect1;
- Rect _sliderRect2;
- int _arrayIndex;
- CString _string1;
- int _fieldFC;
- CString _string2;
- CString _string3;
- bool _field118;
+ Rect _rectUnused;
+ Rect _thumbRect;
+ Rect _defaultThumbRect;
+ int _sliderIndex;
+ CString _stringUnused;
+ int _sliderNum;
+ CString _armName;
+ CString _signalTarget;
+ bool _dragging;
public:
CLASSDEF;
CGondolierSlider();
diff --git a/engines/titanic/game/hammer_dispensor.cpp b/engines/titanic/game/hammer_dispensor.cpp
index 2450868b14..82aeec12cb 100644
--- a/engines/titanic/game/hammer_dispensor.cpp
+++ b/engines/titanic/game/hammer_dispensor.cpp
@@ -77,9 +77,9 @@ bool CHammerDispensor::EnterViewMsg(CEnterViewMsg *msg) {
bool CHammerDispensor::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_isOpen)
- playMovie(32, 50, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(32, 50, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
else
- playMovie(0, 7, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(0, 7, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_panUp = true;
_isOpen = false;
diff --git a/engines/titanic/game/head_slot.cpp b/engines/titanic/game/head_slot.cpp
index 06c366abd6..f8a65715ad 100644
--- a/engines/titanic/game/head_slot.cpp
+++ b/engines/titanic/game/head_slot.cpp
@@ -37,77 +37,77 @@ BEGIN_MESSAGE_MAP(CHeadSlot, CGameObject)
ON_MESSAGE(MouseDragStartMsg)
END_MESSAGE_MAP()
-int CHeadSlot::_v1;
+bool CHeadSlot::_titaniaWoken;
-CHeadSlot::CHeadSlot() : CGameObject(), _string1("NotWorking"), _string2("NULL"),
- _fieldBC(0), _fieldD8(0), _fieldDC(27), _fieldE0(56),
- _fieldE4(82), _fieldE8(112), _fieldEC(false) {
+CHeadSlot::CHeadSlot() : CGameObject(), _senseState("NotWorking"), _target("NULL"),
+ _occupied(false), _timerDuration(0), _frameNum1(27), _frameNum2(56),
+ _frameNum3(82), _frameNum4(112), _workingFlag(false) {
}
void CHeadSlot::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldBC, indent);
- file->writeQuotedLine(_string1, indent);
- file->writeQuotedLine(_string2, indent);
- file->writeNumberLine(_fieldD8, indent);
- file->writeNumberLine(_fieldDC, indent);
- file->writeNumberLine(_fieldE0, indent);
- file->writeNumberLine(_fieldE4, indent);
- file->writeNumberLine(_fieldE8, indent);
- file->writeNumberLine(_v1, indent);
- file->writeNumberLine(_fieldEC, indent);
+ file->writeNumberLine(_occupied, indent);
+ file->writeQuotedLine(_senseState, indent);
+ file->writeQuotedLine(_target, indent);
+ file->writeNumberLine(_timerDuration, indent);
+ file->writeNumberLine(_frameNum1, indent);
+ file->writeNumberLine(_frameNum2, indent);
+ file->writeNumberLine(_frameNum3, indent);
+ file->writeNumberLine(_frameNum4, indent);
+ file->writeNumberLine(_titaniaWoken, indent);
+ file->writeNumberLine(_workingFlag, indent);
CGameObject::save(file, indent);
}
void CHeadSlot::load(SimpleFile *file) {
file->readNumber();
- _fieldBC = file->readNumber();
- _string1 = file->readString();
- _string2 = file->readString();
- _fieldD8 = file->readNumber();
- _fieldDC = file->readNumber();
- _fieldE0 = file->readNumber();
- _fieldE4 = file->readNumber();
- _fieldE8 = file->readNumber();
- _v1 = file->readNumber();
- _fieldEC = file->readNumber();
+ _occupied = file->readNumber();
+ _senseState = file->readString();
+ _target = file->readString();
+ _timerDuration = file->readNumber();
+ _frameNum1 = file->readNumber();
+ _frameNum2 = file->readNumber();
+ _frameNum3 = file->readNumber();
+ _frameNum4 = file->readNumber();
+ _titaniaWoken = file->readNumber();
+ _workingFlag = file->readNumber();
CGameObject::load(file);
}
bool CHeadSlot::AddHeadPieceMsg(CAddHeadPieceMsg *msg) {
setVisible(true);
- _fieldBC = 1;
- _string2 = msg->_value;
- playMovie(_fieldDC, _fieldE8, 0);
+ _occupied = true;
+ _target = msg->_value;
+ playMovie(_frameNum1, _frameNum4, 0);
_cursorId = CURSOR_HAND;
msg->execute("TitaniaControl");
return true;
}
bool CHeadSlot::SenseWorkingMsg(CSenseWorkingMsg *msg) {
- if (_fieldEC)
- playMovie(_fieldE4, _fieldE8, 0);
+ if (_workingFlag)
+ playMovie(_frameNum3, _frameNum4, 0);
- _string1 = msg->_value;
- _fieldEC = false;
+ _senseState = msg->_value;
+ _workingFlag = false;
return true;
}
bool CHeadSlot::EnterViewMsg(CEnterViewMsg *msg) {
setVisible(true);
- if (_v1)
+ if (_titaniaWoken)
_cursorId = CURSOR_ARROW;
- if (_v1 == 1 || _string1 == "Working") {
- playMovie(_fieldE0, _fieldE4, MOVIE_GAMESTATE);
- _fieldEC = true;
- } else if (_fieldBC) {
- playMovie(_fieldE0, _fieldE8, MOVIE_GAMESTATE);
- _fieldEC = false;
+ if (_titaniaWoken || _senseState == "Working") {
+ playMovie(_frameNum2, _frameNum3, MOVIE_WAIT_FOR_FINISH);
+ _workingFlag = true;
+ } else if (_occupied) {
+ playMovie(_frameNum2, _frameNum4, MOVIE_WAIT_FOR_FINISH);
+ _workingFlag = false;
} else {
- playMovie(0, _fieldDC, MOVIE_GAMESTATE);
+ playMovie(0, _frameNum1, MOVIE_WAIT_FOR_FINISH);
}
addTimer(5000 + getRandomNumber(3000));
@@ -118,16 +118,15 @@ bool CHeadSlot::LeaveViewMsg(CLeaveViewMsg *msg) {
if (getName() == "YepItsASlot") {
stopMovie();
- if (_fieldBC) {
- loadFrame(_fieldE0);
- playMovie(_fieldE0, _fieldE8, MOVIE_GAMESTATE);
- _fieldEC = false;
+ if (_occupied) {
+ loadFrame(_frameNum2);
+ playMovie(_frameNum2, _frameNum4, MOVIE_WAIT_FOR_FINISH);
} else {
- loadFrame(_fieldDC);
- playMovie(_fieldDC, _fieldE0, MOVIE_GAMESTATE);
+ loadFrame(_frameNum1);
+ playMovie(_frameNum1, _frameNum2, MOVIE_WAIT_FOR_FINISH);
}
- _fieldEC = false;
+ _workingFlag = false;
}
return true;
@@ -138,19 +137,19 @@ bool CHeadSlot::LoadSuccessMsg(CLoadSuccessMsg *msg) {
}
bool CHeadSlot::TimerMsg(CTimerMsg *msg) {
- if (compareViewNameTo("Titania.Node 15.S") && CBrainSlot::_added == 5
- && _fieldBC == 1) {
- if (_string1 == "Working" && !_fieldEC) {
- playMovie(_fieldE0, _fieldE4, 0);
- _fieldEC = true;
- } else if (_string1 == "Random") {
- playMovie(_fieldE0, _fieldE8, 0);
+ if (compareViewNameTo("Titania.Node 15.S") && CBrainSlot::_numAdded == 5
+ && _occupied) {
+ if (_senseState == "Working" && !_workingFlag) {
+ playMovie(_frameNum2, _frameNum3, 0);
+ _workingFlag = true;
+ } else if (_senseState == "Random") {
+ playMovie(_frameNum2, _frameNum4, 0);
}
}
if (compareViewNameTo("Titania.Node 15.S")) {
- _fieldD8 = 7000 + getRandomNumber(5000);
- addTimer(_fieldD8);
+ _timerDuration = 7000 + getRandomNumber(5000);
+ addTimer(_timerDuration);
}
return true;
@@ -158,27 +157,29 @@ bool CHeadSlot::TimerMsg(CTimerMsg *msg) {
bool CHeadSlot::ActMsg(CActMsg *msg) {
if (msg->_action == "Woken")
- _v1 = 1;
+ _titaniaWoken = true;
return true;
}
bool CHeadSlot::MouseDragStartMsg(CMouseDragStartMsg *msg) {
- if (_fieldBC && !_v1 && checkPoint(msg->_mousePos, false, true)) {
+ if (_occupied && !_titaniaWoken && checkPoint(msg->_mousePos, false, true)) {
CPassOnDragStartMsg passMsg;
passMsg._mousePos = msg->_mousePos;
- passMsg.execute(_string2);
+ passMsg.execute(_target);
- msg->_dragItem = getRoot()->findByName(_string2);
+ msg->_dragItem = getRoot()->findByName(_target);
_cursorId = CURSOR_ARROW;
- _fieldBC = 0;
- _fieldEC = false;
- _string2 = "NULL";
+ _occupied = false;
+ _workingFlag = false;
+ _target = "NULL";
stopMovie();
loadFrame(0);
- playMovie(0, _fieldDC, 0);
+ playMovie(0, _frameNum1, 0);
+
+ return true;
}
- return true;
+ return false;
}
} // End of namespace Titanic
diff --git a/engines/titanic/game/head_slot.h b/engines/titanic/game/head_slot.h
index 2767db3b61..1474e03ff3 100644
--- a/engines/titanic/game/head_slot.h
+++ b/engines/titanic/game/head_slot.h
@@ -38,17 +38,17 @@ class CHeadSlot : public CGameObject {
bool ActMsg(CActMsg *msg);
bool MouseDragStartMsg(CMouseDragStartMsg *msg);
public:
- static int _v1;
+ static bool _titaniaWoken;
public:
- int _fieldBC;
- CString _string1;
- CString _string2;
- int _fieldD8;
- int _fieldDC;
- int _fieldE0;
- int _fieldE4;
- int _fieldE8;
- bool _fieldEC;
+ bool _occupied;
+ CString _senseState;
+ CString _target;
+ int _timerDuration;
+ int _frameNum1;
+ int _frameNum2;
+ int _frameNum3;
+ int _frameNum4;
+ bool _workingFlag;
public:
CLASSDEF;
CHeadSlot();
diff --git a/engines/titanic/game/head_smash_event.cpp b/engines/titanic/game/head_smash_event.cpp
index 5ec3d299d5..dd5e516b0d 100644
--- a/engines/titanic/game/head_smash_event.cpp
+++ b/engines/titanic/game/head_smash_event.cpp
@@ -42,7 +42,7 @@ void CHeadSmashEvent::load(SimpleFile *file) {
bool CHeadSmashEvent::ActMsg(CActMsg *msg) {
if (msg->_action == "PlayToEnd") {
setVisible(true);
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/long_stick_dispenser.cpp b/engines/titanic/game/long_stick_dispenser.cpp
index bf2dae53be..c340cae75b 100644
--- a/engines/titanic/game/long_stick_dispenser.cpp
+++ b/engines/titanic/game/long_stick_dispenser.cpp
@@ -109,9 +109,9 @@ bool CLongStickDispenser::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
bool CLongStickDispenser::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_fieldC0 == 1) {
if (_fieldC4) {
- playMovie(19, 38, MOVIE_GAMESTATE);
+ playMovie(19, 38, MOVIE_WAIT_FOR_FINISH);
} else {
- playMovie(0, 18, MOVIE_GAMESTATE);
+ playMovie(0, 18, MOVIE_WAIT_FOR_FINISH);
_fieldBC = 1;
}
diff --git a/engines/titanic/game/music_console_button.cpp b/engines/titanic/game/music_console_button.cpp
index 40492aafe4..872202891c 100644
--- a/engines/titanic/game/music_console_button.cpp
+++ b/engines/titanic/game/music_console_button.cpp
@@ -57,9 +57,10 @@ bool CMusicConsoleButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
CMusicHasStartedMsg startedMsg;
startedMsg.execute("Music Room Phonograph");
- if (CMusicRoom::_musicHandler->checkSound(1)
- && CMusicRoom::_musicHandler->checkSound(2)
- && CMusicRoom::_musicHandler->checkSound(3)) {
+ if (CMusicRoom::_musicHandler->checkInstrument(SNAKE)
+ && CMusicRoom::_musicHandler->checkInstrument(PIANO)
+ && CMusicRoom::_musicHandler->checkInstrument(BASS)) {
+ // All three instruments have the correct settings
CCorrectMusicPlayedMsg correctMsg;
correctMsg.execute(findRoom());
}
@@ -70,6 +71,7 @@ bool CMusicConsoleButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
bool CMusicConsoleButton::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_isActive) {
+ // Stop playing the active music
CStopMusicMsg stopMsg(this);
stopMsg.execute(this);
stopMovie();
@@ -83,49 +85,49 @@ bool CMusicConsoleButton::SetMusicControlsMsg(CSetMusicControlsMsg *msg) {
CMusicRoom *musicRoom = getMusicRoom();
CQueryMusicControlSettingMsg queryMsg;
- queryMsg.execute("Bells Mute Control");
- musicRoom->setMuteControl(BELLS, queryMsg._value == 1 ? 1 : 0);
queryMsg.execute("Bells Pitch Control");
musicRoom->setPitchControl(BELLS, queryMsg._value);
queryMsg.execute("Bells Speed Control");
musicRoom->setSpeedControl(BELLS, queryMsg._value);
queryMsg.execute("Bells Inversion Control");
- musicRoom->setInversionControl(BELLS, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setInversionControl(BELLS, queryMsg._value == 1);
queryMsg.execute("Bells Direction Control");
- musicRoom->setDirectionControl(BELLS, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setDirectionControl(BELLS, queryMsg._value == 1);
+ queryMsg.execute("Bells Mute Control");
+ musicRoom->setMuteControl(BELLS, queryMsg._value == 1);
- queryMsg.execute("Snake Mute Control");
- musicRoom->setMuteControl(SNAKE, queryMsg._value == 1 ? 1 : 0);
queryMsg.execute("Snake Pitch Control");
musicRoom->setPitchControl(SNAKE, queryMsg._value);
queryMsg.execute("Snake Speed Control");
musicRoom->setSpeedControl(SNAKE, queryMsg._value);
queryMsg.execute("Snake Inversion Control");
- musicRoom->setInversionControl(SNAKE, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setInversionControl(SNAKE, queryMsg._value == 1);
queryMsg.execute("Snake Direction Control");
- musicRoom->setDirectionControl(SNAKE, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setDirectionControl(SNAKE, queryMsg._value == 1);
+ queryMsg.execute("Snake Mute Control");
+ musicRoom->setMuteControl(SNAKE, queryMsg._value == 1);
- queryMsg.execute("Piano Mute Control");
- musicRoom->setMuteControl(PIANO, queryMsg._value == 1 ? 1 : 0);
queryMsg.execute("Piano Pitch Control");
musicRoom->setPitchControl(PIANO, queryMsg._value);
queryMsg.execute("Piano Speed Control");
musicRoom->setSpeedControl(PIANO, queryMsg._value);
queryMsg.execute("Piano Inversion Control");
- musicRoom->setInversionControl(PIANO, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setInversionControl(PIANO, queryMsg._value == 1);
queryMsg.execute("Piano Direction Control");
- musicRoom->setDirectionControl(PIANO, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setDirectionControl(PIANO, queryMsg._value == 1);
+ queryMsg.execute("Piano Mute Control");
+ musicRoom->setMuteControl(PIANO, queryMsg._value == 1);
- queryMsg.execute("Bass Mute Control");
- musicRoom->setMuteControl(BASS, queryMsg._value == 1 ? 1 : 0);
queryMsg.execute("Bass Pitch Control");
musicRoom->setPitchControl(BASS, queryMsg._value);
queryMsg.execute("Bass Speed Control");
musicRoom->setSpeedControl(BASS, queryMsg._value);
queryMsg.execute("Bass Inversion Control");
- musicRoom->setInversionControl(BASS, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setInversionControl(BASS, queryMsg._value == 1);
queryMsg.execute("Bass Direction Control");
- musicRoom->setDirectionControl(BASS, queryMsg._value == 0 ? 1 : 0);
+ musicRoom->setDirectionControl(BASS, queryMsg._value == 1);
+ queryMsg.execute("Bass Mute Control");
+ musicRoom->setMuteControl(BASS, queryMsg._value == 1);
return true;
}
diff --git a/engines/titanic/game/music_room_stop_phonograph_button.cpp b/engines/titanic/game/music_room_stop_phonograph_button.cpp
index dee2c0883e..0a72406b0f 100644
--- a/engines/titanic/game/music_room_stop_phonograph_button.cpp
+++ b/engines/titanic/game/music_room_stop_phonograph_button.cpp
@@ -49,7 +49,7 @@ bool CMusicRoomStopPhonographButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg
CPhonographStopMsg stopMsg;
stopMsg.execute(getParent(), nullptr, MSGFLAG_SCAN);
- if (stopMsg._value2) {
+ if (stopMsg._cylinderPresent) {
_ticks = getTicksCount();
} else {
CEjectCylinderMsg ejectMsg;
diff --git a/engines/titanic/game/nut_replacer.cpp b/engines/titanic/game/nut_replacer.cpp
index 6b05d1d0e9..3b1247fd8c 100644
--- a/engines/titanic/game/nut_replacer.cpp
+++ b/engines/titanic/game/nut_replacer.cpp
@@ -41,7 +41,7 @@ void CNutReplacer::load(SimpleFile *file) {
bool CNutReplacer::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) {
setVisible(true);
- playMovie(MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
return true;
}
diff --git a/engines/titanic/game/parrot/parrot_nut_eater.cpp b/engines/titanic/game/parrot/parrot_nut_eater.cpp
index b9697d7b61..7196d76ccb 100644
--- a/engines/titanic/game/parrot/parrot_nut_eater.cpp
+++ b/engines/titanic/game/parrot/parrot_nut_eater.cpp
@@ -67,7 +67,7 @@ bool CParrotNutEater::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) {
bool CParrotNutEater::NutPuzzleMsg(CNutPuzzleMsg *msg) {
if (msg->_value == "Jiggle") {
setVisible(true);
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent(68);
movieEvent(132);
playSound("z#215.wav");
diff --git a/engines/titanic/game/phonograph.cpp b/engines/titanic/game/phonograph.cpp
index 408cfa3413..b86fa0b6e0 100644
--- a/engines/titanic/game/phonograph.cpp
+++ b/engines/titanic/game/phonograph.cpp
@@ -34,32 +34,32 @@ BEGIN_MESSAGE_MAP(CPhonograph, CMusicPlayer)
END_MESSAGE_MAP()
CPhonograph::CPhonograph() : CMusicPlayer(),
- _fieldE0(false), _fieldE4(0), _fieldE8(0), _fieldEC(0),
- _fieldF0(0), _fieldF4(0) {
+ _isPlaying(false), _isRecording(false), _isDisabled(false),
+ _playUnpressedFrame(false), _playPressedFrame(false), _unused5(0) {
}
void CPhonograph::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeQuotedLine(_string2, indent);
- file->writeNumberLine(_fieldE0, indent);
- file->writeNumberLine(_fieldE4, indent);
- file->writeNumberLine(_fieldE8, indent);
- file->writeNumberLine(_fieldEC, indent);
- file->writeNumberLine(_fieldF0, indent);
- file->writeNumberLine(_fieldF4, indent);
+ file->writeQuotedLine(_unused, indent);
+ file->writeNumberLine(_isPlaying, indent);
+ file->writeNumberLine(_isRecording, indent);
+ file->writeNumberLine(_isDisabled, indent);
+ file->writeNumberLine(_playUnpressedFrame, indent);
+ file->writeNumberLine(_playPressedFrame, indent);
+ file->writeNumberLine(_unused5, indent);
CMusicPlayer::save(file, indent);
}
void CPhonograph::load(SimpleFile *file) {
file->readNumber();
- _string2 = file->readString();
- _fieldE0 = file->readNumber();
- _fieldE4 = file->readNumber();
- _fieldE8 = file->readNumber();
- _fieldEC = file->readNumber();
- _fieldF0 = file->readNumber();
- _fieldF4 = file->readNumber();
+ _unused = file->readString();
+ _isPlaying = file->readNumber();
+ _isRecording = file->readNumber();
+ _isDisabled = file->readNumber();
+ _playUnpressedFrame = file->readNumber();
+ _playPressedFrame = file->readNumber();
+ _unused5 = file->readNumber();
CMusicPlayer::load(file);
}
@@ -67,8 +67,8 @@ void CPhonograph::load(SimpleFile *file) {
bool CPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) {
CQueryCylinderHolderMsg holderMsg;
holderMsg.execute(this);
- if (!holderMsg._value2) {
- _fieldE0 = false;
+ if (!holderMsg._isPresent) {
+ _isPlaying = false;
return true;
}
@@ -76,16 +76,16 @@ bool CPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) {
cylinderMsg.execute(holderMsg._target);
if (cylinderMsg._name.empty()) {
- _fieldE0 = false;
+ _isPlaying = false;
} else if (cylinderMsg._name.hasPrefix("STMusic")) {
CStartMusicMsg startMsg(this);
startMsg.execute(this);
- _fieldE0 = true;
+ _isPlaying = true;
msg->_value = 1;
} else {
- stopGlobalSound(0, -1);
+ stopGlobalSound(false, -1);
playGlobalSound(cylinderMsg._name, -2, true, true, 0);
- _fieldE0 = true;
+ _isPlaying = true;
msg->_value = 1;
}
@@ -95,45 +95,45 @@ bool CPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) {
bool CPhonograph::PhonographStopMsg(CPhonographStopMsg *msg) {
CQueryCylinderHolderMsg holderMsg;
holderMsg.execute(this);
- if (!holderMsg._value2)
+ if (!holderMsg._isPresent)
return true;
- _fieldE0 = false;
CQueryCylinderMsg cylinderMsg;
cylinderMsg.execute(holderMsg._target);
- if (_fieldE0) {
+ if (_isPlaying) {
if (!cylinderMsg._name.empty()) {
if (cylinderMsg._name.hasPrefix("STMusic")) {
CStopMusicMsg stopMsg;
stopMsg.execute(this);
} else {
- stopGlobalSound(msg->_value1, -1);
+ stopGlobalSound(msg->_leavingRoom, -1);
}
- msg->_value2 = 1;
+ msg->_cylinderPresent = true;
}
- if (!msg->_value3)
- _fieldE0 = false;
- } else if (_fieldE4) {
- _fieldE4 = false;
- msg->_value2 = 1;
+ if (!msg->_dontStop)
+ _isPlaying = false;
+ } else if (_isRecording) {
+ _isRecording = false;
+ msg->_cylinderPresent = true;
}
return true;
}
bool CPhonograph::PhonographRecordMsg(CPhonographRecordMsg *msg) {
- if (!_fieldE0 && !_fieldE4 && !_fieldE8) {
+ if (!_isPlaying && !_isRecording && !_isDisabled) {
CQueryCylinderHolderMsg holderMsg;
holderMsg.execute(this);
- if (holderMsg._value2) {
- _fieldE4 = true;
+ if (holderMsg._isPresent) {
+ _isRecording = true;
+ msg->_canRecord = true;
CErasePhonographCylinderMsg eraseMsg;
eraseMsg.execute(holderMsg._target);
} else {
- _fieldE4 = false;
+ _isRecording = false;
}
}
@@ -141,7 +141,7 @@ bool CPhonograph::PhonographRecordMsg(CPhonographRecordMsg *msg) {
}
bool CPhonograph::EnterRoomMsg(CEnterRoomMsg *msg) {
- if (_fieldE0) {
+ if (_isPlaying) {
CPhonographPlayMsg playMsg;
playMsg.execute(this);
}
@@ -150,9 +150,9 @@ bool CPhonograph::EnterRoomMsg(CEnterRoomMsg *msg) {
}
bool CPhonograph::LeaveRoomMsg(CLeaveRoomMsg *msg) {
- if (_fieldE0) {
+ if (_isPlaying) {
CPhonographStopMsg stopMsg;
- stopMsg._value1 = 1;
+ stopMsg._leavingRoom = true;
stopMsg.execute(this);
}
@@ -160,14 +160,14 @@ bool CPhonograph::LeaveRoomMsg(CLeaveRoomMsg *msg) {
}
bool CPhonograph::MusicHasStartedMsg(CMusicHasStartedMsg *msg) {
- if (_fieldE4) {
+ if (_isRecording) {
CQueryCylinderHolderMsg holderMsg;
holderMsg.execute(this);
- if (holderMsg._value2) {
+ if (holderMsg._isPresent) {
CRecordOntoCylinderMsg recordMsg;
recordMsg.execute(holderMsg._target);
} else {
- _fieldE4 = false;
+ _isRecording = false;
}
}
diff --git a/engines/titanic/game/phonograph.h b/engines/titanic/game/phonograph.h
index b13a5ea910..6630a18f27 100644
--- a/engines/titanic/game/phonograph.h
+++ b/engines/titanic/game/phonograph.h
@@ -37,13 +37,13 @@ class CPhonograph : public CMusicPlayer {
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
bool MusicHasStartedMsg(CMusicHasStartedMsg *msg);
protected:
- CString _string2;
- bool _fieldE0;
- int _fieldE4;
- int _fieldE8;
- int _fieldEC;
- int _fieldF0;
- int _fieldF4;
+ CString _unused;
+ bool _isPlaying;
+ bool _isRecording;
+ bool _isDisabled;
+ int _playUnpressedFrame;
+ int _playPressedFrame;
+ int _unused5;
public:
CLASSDEF;
CPhonograph();
diff --git a/engines/titanic/game/phonograph_lid.cpp b/engines/titanic/game/phonograph_lid.cpp
index e4e5f4882c..cde9415e02 100644
--- a/engines/titanic/game/phonograph_lid.cpp
+++ b/engines/titanic/game/phonograph_lid.cpp
@@ -76,7 +76,7 @@ bool CPhonographLid::LockPhonographMsg(CLockPhonographMsg *msg) {
bool CPhonographLid::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_open) {
- playMovie(27, 55, MOVIE_GAMESTATE);
+ playMovie(27, 55, MOVIE_WAIT_FOR_FINISH);
_open = false;
}
diff --git a/engines/titanic/game/play_music_button.cpp b/engines/titanic/game/play_music_button.cpp
index 21fd3c336a..d4d7e1cd35 100644
--- a/engines/titanic/game/play_music_button.cpp
+++ b/engines/titanic/game/play_music_button.cpp
@@ -54,7 +54,7 @@ bool CPlayMusicButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
loadFrame(0);
_flag = false;
} else {
- musicRoom->startMusic(100);
+ musicRoom->setupMusic(100);
playMovie(MOVIE_REPEAT);
_ticks = getTicksCount();
_flag = true;
@@ -64,7 +64,7 @@ bool CPlayMusicButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CPlayMusicButton::FrameMsg(CFrameMsg *msg) {
- if (_flag && !CMusicRoom::_musicHandler->poll()) {
+ if (_flag && !CMusicRoom::_musicHandler->update()) {
CMusicRoom *musicRoom = getMusicRoom();
musicRoom->stopMusic();
stopMovie();
diff --git a/engines/titanic/game/play_on_act.cpp b/engines/titanic/game/play_on_act.cpp
index 9c368c335d..ffed45c11f 100644
--- a/engines/titanic/game/play_on_act.cpp
+++ b/engines/titanic/game/play_on_act.cpp
@@ -45,7 +45,7 @@ bool CPlayOnAct::ActMsg(CActMsg *msg) {
playMovie(0);
} else if (msg->_action == "PlayToEnd") {
setVisible(true);
- playMovie(MOVIE_GAMESTATE);
+ playMovie(MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/port_hole.cpp b/engines/titanic/game/port_hole.cpp
index 25807b1b1d..9111561588 100644
--- a/engines/titanic/game/port_hole.cpp
+++ b/engines/titanic/game/port_hole.cpp
@@ -79,7 +79,7 @@ bool CPortHole::MovieEndMsg(CMovieEndMsg *msg) {
bool CPortHole::LeaveViewMsg(CLeaveViewMsg *msg) {
if (_open) {
playSound(_closeSoundName);
- playMovie(14, 26, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(14, 26, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_open = false;
}
diff --git a/engines/titanic/game/record_phonograph_button.cpp b/engines/titanic/game/record_phonograph_button.cpp
index 1ffaec4228..1bd2060193 100644
--- a/engines/titanic/game/record_phonograph_button.cpp
+++ b/engines/titanic/game/record_phonograph_button.cpp
@@ -45,7 +45,7 @@ bool CRecordPhonographButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
CPhonographRecordMsg recordMsg;
recordMsg.execute(getParent());
- if (recordMsg._value) {
+ if (recordMsg._canRecord) {
playSound("z#58.wav");
loadFrame(1);
_active = true;
diff --git a/engines/titanic/game/replacement_ear.cpp b/engines/titanic/game/replacement_ear.cpp
index e8bd384207..d1274e92db 100644
--- a/engines/titanic/game/replacement_ear.cpp
+++ b/engines/titanic/game/replacement_ear.cpp
@@ -40,7 +40,7 @@ void CReplacementEar::load(SimpleFile *file) {
bool CReplacementEar::VisibleMsg(CVisibleMsg *msg) {
setVisible(true);
- playMovie(MOVIE_GAMESTATE);
+ playMovie(MOVIE_WAIT_FOR_FINISH);
playSound("z#64.wav");
return true;
}
diff --git a/engines/titanic/game/restaurant_cylinder_holder.cpp b/engines/titanic/game/restaurant_cylinder_holder.cpp
index 5fb8c97cde..eddd4d2288 100644
--- a/engines/titanic/game/restaurant_cylinder_holder.cpp
+++ b/engines/titanic/game/restaurant_cylinder_holder.cpp
@@ -34,13 +34,13 @@ BEGIN_MESSAGE_MAP(CRestaurantCylinderHolder, CDropTarget)
END_MESSAGE_MAP()
CRestaurantCylinderHolder::CRestaurantCylinderHolder() : CDropTarget(),
- _field118(0), _field11C(0), _field12C(0), _field130(0),
+ _isOpen(false), _field11C(0), _field12C(0), _field130(0),
_ejectSoundName("z#61.wav"), _defaultCursorId(CURSOR_ARROW) {
}
void CRestaurantCylinderHolder::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_field118, indent);
+ file->writeNumberLine(_isOpen, indent);
file->writeNumberLine(_field11C, indent);
file->writeQuotedLine(_target, indent);
file->writeNumberLine(_field12C, indent);
@@ -53,7 +53,7 @@ void CRestaurantCylinderHolder::save(SimpleFile *file, int indent) {
void CRestaurantCylinderHolder::load(SimpleFile *file) {
file->readNumber();
- _field118 = file->readNumber();
+ _isOpen = file->readNumber();
_field11C = file->readNumber();
_target = file->readString();
_field12C = file->readNumber();
@@ -66,15 +66,15 @@ void CRestaurantCylinderHolder::load(SimpleFile *file) {
bool CRestaurantCylinderHolder::EjectCylinderMsg(CEjectCylinderMsg *msg) {
_field11C = true;
- bool hasCylinder = findByName("Phonograph Cylinder") != nullptr;
+ bool hasCylinder = findByName("Phonograph Cylinder", true) != nullptr;
- if (_field118) {
+ if (_isOpen) {
playClip(hasCylinder ? "CloseHolder_Full" : "CloseHolder_Empty",
- MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_dropEnabled = true;
} else {
playClip(hasCylinder ? "OpenHolder_Full" : "OpenHolder_Empty",
- MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
playSound(_ejectSoundName, 50);
@@ -82,7 +82,7 @@ bool CRestaurantCylinderHolder::EjectCylinderMsg(CEjectCylinderMsg *msg) {
}
bool CRestaurantCylinderHolder::EnterViewMsg(CEnterViewMsg *msg) {
- if (_field118) {
+ if (_isOpen) {
CTreeItem *cylinder = findByName("Phonograph Cylinder", true);
if (cylinder) {
loadFrame(_dropFrame);
@@ -101,14 +101,14 @@ bool CRestaurantCylinderHolder::EnterViewMsg(CEnterViewMsg *msg) {
bool CRestaurantCylinderHolder::MovieEndMsg(CMovieEndMsg *msg) {
_field11C = false;
- if (_field118) {
- _field118 = false;
+ if (_isOpen) {
+ _isOpen = false;
_cursorId = _defaultCursorId;
CPhonographReadyToPlayMsg readyMsg;
readyMsg.execute(_target);
} else {
- _field118 = true;
+ _isOpen = true;
_dropEnabled = false;
_cursorId = findByName("Phonograph Cylinder") ? _dropCursorId : _dragCursorId;
}
@@ -121,9 +121,9 @@ bool CRestaurantCylinderHolder::MovieEndMsg(CMovieEndMsg *msg) {
bool CRestaurantCylinderHolder::QueryCylinderHolderMsg(CQueryCylinderHolderMsg *msg) {
CNamedItem *cylinder = findByName("Phonograph Cylinder", true);
- msg->_value1 = _field118;
+ msg->_isOpen = _isOpen;
if (cylinder) {
- msg->_value2 = 1;
+ msg->_isPresent = true;
msg->_target = cylinder;
}
@@ -143,7 +143,7 @@ bool CRestaurantCylinderHolder::QueryCylinderNameMsg(CQueryCylinderNameMsg *msg)
}
bool CRestaurantCylinderHolder::MouseDragStartMsg(CMouseDragStartMsg *msg) {
- if (_field118)
+ if (_isOpen)
return CDropTarget::MouseDragStartMsg(msg);
else
return true;
diff --git a/engines/titanic/game/restaurant_cylinder_holder.h b/engines/titanic/game/restaurant_cylinder_holder.h
index cd0b0783bd..7be73df074 100644
--- a/engines/titanic/game/restaurant_cylinder_holder.h
+++ b/engines/titanic/game/restaurant_cylinder_holder.h
@@ -36,7 +36,7 @@ class CRestaurantCylinderHolder : public CDropTarget {
bool QueryCylinderNameMsg(CQueryCylinderNameMsg *msg);
bool MouseDragStartMsg(CMouseDragStartMsg *msg);
private:
- int _field118;
+ bool _isOpen;
int _field11C;
CString _target;
int _field12C;
diff --git a/engines/titanic/game/restaurant_phonograph.cpp b/engines/titanic/game/restaurant_phonograph.cpp
index 881079e020..3b35514a52 100644
--- a/engines/titanic/game/restaurant_phonograph.cpp
+++ b/engines/titanic/game/restaurant_phonograph.cpp
@@ -36,13 +36,13 @@ BEGIN_MESSAGE_MAP(CRestaurantPhonograph, CPhonograph)
END_MESSAGE_MAP()
CRestaurantPhonograph::CRestaurantPhonograph() : CPhonograph(),
- _fieldF8(1), _field114(0) {}
+ _isLocked(true), _field114(0) {}
void CRestaurantPhonograph::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldF8, indent);
- file->writeQuotedLine(_string2, indent);
- file->writeQuotedLine(_string3, indent);
+ file->writeNumberLine(_isLocked, indent);
+ file->writeQuotedLine(_ejectSoundName, indent);
+ file->writeQuotedLine(_stopSoundName, indent);
file->writeNumberLine(_field114, indent);
@@ -51,29 +51,31 @@ void CRestaurantPhonograph::save(SimpleFile *file, int indent) {
void CRestaurantPhonograph::load(SimpleFile *file) {
file->readNumber();
- _fieldF8 = file->readNumber();
- _string2 = file->readString();
- _string3 = file->readString();
+ _isLocked = file->readNumber();
+ _ejectSoundName = file->readString();
+ _stopSoundName = file->readString();
_field114 = file->readNumber();
CPhonograph::load(file);
}
bool CRestaurantPhonograph::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- if (!_fieldF8 && !_fieldE0) {
+ if (!_isLocked && !_isPlaying) {
CQueryCylinderHolderMsg holderMsg;
holderMsg.execute(this);
- if (!holderMsg._value1) {
+ if (!holderMsg._isOpen) {
+ // Start playing immediately
CPhonographPlayMsg playMsg;
playMsg.execute(this);
- } else if (holderMsg._value2) {
+ } else if (holderMsg._isPresent) {
+ // Need to close the cylinder holder before playing
CEjectCylinderMsg ejectMsg;
- ejectMsg.execute(this);
+ ejectMsg.execute(this, nullptr, MSGFLAG_SCAN);
- _fieldE8 = true;
+ _isDisabled = true;
if (_field114) {
- loadFrame(_fieldEC);
+ loadFrame(_playUnpressedFrame);
playSound(_ejectSoundName);
}
}
@@ -83,9 +85,11 @@ bool CRestaurantPhonograph::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CRestaurantPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) {
- if (_fieldE0) {
- if (findView() == getView() && (!_fieldE8 || !_field114)) {
- loadFrame(_fieldEC);
+ CPhonograph::PhonographPlayMsg(msg);
+
+ if (_isPlaying) {
+ if (findView() == getView() && (!_isDisabled || !_field114)) {
+ loadFrame(_playUnpressedFrame);
playSound(_ejectSoundName);
}
@@ -94,39 +98,39 @@ bool CRestaurantPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) {
CRestaurantMusicChanged musicMsg(nameMsg._name);
musicMsg.execute(findRoom());
} else {
- loadFrame(_fieldF0);
+ loadFrame(_playPressedFrame);
}
return true;
}
bool CRestaurantPhonograph::PhonographStopMsg(CPhonographStopMsg *msg) {
- bool flag = _fieldE0;
+ bool flag = _isPlaying;
CPhonograph::PhonographStopMsg(msg);
- if (_fieldE0) {
- loadFrame(_fieldF0);
- if (flag)
- playSound(_string3);
+ if (_isPlaying) {
+ loadFrame(_playUnpressedFrame);
} else {
- loadFrame(_fieldEC);
+ loadFrame(_playPressedFrame);
+ if (flag)
+ playSound(_stopSoundName);
}
return true;
}
bool CRestaurantPhonograph::PhonographReadyToPlayMsg(CPhonographReadyToPlayMsg *msg) {
- if (_fieldE8) {
+ if (_isDisabled) {
CPhonographPlayMsg playMsg;
playMsg.execute(this);
- _fieldE8 = false;
+ _isDisabled = false;
}
return true;
}
bool CRestaurantPhonograph::EjectCylinderMsg(CEjectCylinderMsg *msg) {
- if (_fieldE0) {
+ if (_isPlaying) {
CPhonographStopMsg stopMsg;
stopMsg.execute(this);
}
@@ -135,12 +139,12 @@ bool CRestaurantPhonograph::EjectCylinderMsg(CEjectCylinderMsg *msg) {
}
bool CRestaurantPhonograph::QueryPhonographState(CQueryPhonographState *msg) {
- msg->_value = _fieldF8;
+ msg->_value = _isLocked;
return true;
}
bool CRestaurantPhonograph::LockPhonographMsg(CLockPhonographMsg *msg) {
- _fieldF8 = msg->_value;
+ _isLocked = msg->_value;
return true;
}
diff --git a/engines/titanic/game/restaurant_phonograph.h b/engines/titanic/game/restaurant_phonograph.h
index 9661df0dfb..67248447ab 100644
--- a/engines/titanic/game/restaurant_phonograph.h
+++ b/engines/titanic/game/restaurant_phonograph.h
@@ -37,9 +37,9 @@ class CRestaurantPhonograph : public CPhonograph {
bool QueryPhonographState(CQueryPhonographState *msg);
bool LockPhonographMsg(CLockPhonographMsg *msg);
private:
- int _fieldF8;
+ bool _isLocked;
CString _ejectSoundName;
- CString _string3;
+ CString _stopSoundName;
int _field114;
public:
CLASSDEF;
diff --git a/engines/titanic/game/season_background.cpp b/engines/titanic/game/season_background.cpp
index 20ad6aca1d..d663c405ce 100644
--- a/engines/titanic/game/season_background.cpp
+++ b/engines/titanic/game/season_background.cpp
@@ -65,39 +65,39 @@ bool CSeasonBackground::ChangeSeasonMsg(CChangeSeasonMsg *msg) {
switch (_seasonNum) {
case SEASON_SUMMER:
- playMovie(0, 45, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(0, 45, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 45;
break;
case SEASON_AUTUMN:
if (_flag) {
- playMovie(232, 278, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(232, 278, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 278;
} else {
- playMovie(45, 91, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(45, 91, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 91;
}
break;
case SEASON_WINTER:
if (_flag) {
- playMovie(278, 326, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(278, 326, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 326;
} else {
CStatusChangeMsg changeMsg;
changeMsg._newStatus = 0;
changeMsg.execute("PickUpSpeechCentre");
- playMovie(91, 139, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(91, 139, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 139;
}
break;
case SEASON_SPRING:
if (_flag) {
- playMovie(326, 417, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(326, 417, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 417;
} else {
- playMovie(139, 228, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(139, 228, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_defaultFrame = 228;
}
break;
diff --git a/engines/titanic/game/sgt/armchair.cpp b/engines/titanic/game/sgt/armchair.cpp
index 681b1ae61d..6c0e7fe0ca 100644
--- a/engines/titanic/game/sgt/armchair.cpp
+++ b/engines/titanic/game/sgt/armchair.cpp
@@ -55,7 +55,7 @@ bool CArmchair::TurnOn(CTurnOn *msg) {
_endFrame = 10;
}
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
playSound("b#0.wav");
_statics->_armchair = "Open";
_isClosed = false;
@@ -70,7 +70,7 @@ bool CArmchair::TurnOff(CTurnOff *msg) {
_startFrame = 11;
_endFrame = 21;
_isClosed = true;
- playMovie(11, 21, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(11, 21, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound("b#0.wav");
}
diff --git a/engines/titanic/game/sgt/basin.cpp b/engines/titanic/game/sgt/basin.cpp
index ce34a49250..fe3216e002 100644
--- a/engines/titanic/game/sgt/basin.cpp
+++ b/engines/titanic/game/sgt/basin.cpp
@@ -48,7 +48,7 @@ bool CBasin::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 0;
_endFrame = 6;
- playMovie(0, 6, MOVIE_GAMESTATE);
+ playMovie(0, 6, MOVIE_WAIT_FOR_FINISH);
playSound("b#13.wav");
}
@@ -61,7 +61,7 @@ bool CBasin::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 8;
_endFrame = 14;
- playMovie(8, 14, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(8, 14, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#13.wav");
}
diff --git a/engines/titanic/game/sgt/bedfoot.cpp b/engines/titanic/game/sgt/bedfoot.cpp
index d84a73f0a5..8f90e0f100 100644
--- a/engines/titanic/game/sgt/bedfoot.cpp
+++ b/engines/titanic/game/sgt/bedfoot.cpp
@@ -53,7 +53,7 @@ bool CBedfoot::TurnOn(CTurnOn *msg) {
playSound("b#4.wav");
}
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
} else if (_statics->_bedfoot == "RestingUnderTV") {
_isClosed = false;
_startFrame = 8;
@@ -65,7 +65,7 @@ bool CBedfoot::TurnOn(CTurnOn *msg) {
playSound("192_436_bed hits floor.wav");
}
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
}
if (_statics->_bedfoot == "Open")
@@ -94,7 +94,7 @@ bool CBedfoot::TurnOff(CTurnOff *msg) {
_endFrame = 25;
}
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
playSound("b#7.wav");
} else if (_statics->_bedfoot == "NotOnWashstand" && _statics->_bedhead == "ClosedWrong") {
@@ -109,14 +109,14 @@ bool CBedfoot::TurnOff(CTurnOff *msg) {
_endFrame = 25;
}
- playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_WAIT_FOR_FINISH);
playSound("b#7.wav");
} else if (_statics->_bedfoot == "RestingUTV" && _statics->_tv == "Closed") {
_statics->_bedfoot = "Closed";
_startFrame = 25;
_endFrame = 30;
- playMovie(25, 30, MOVIE_GAMESTATE);
+ playMovie(25, 30, MOVIE_WAIT_FOR_FINISH);
playSound("b#7.wav");
}
diff --git a/engines/titanic/game/sgt/bedhead.cpp b/engines/titanic/game/sgt/bedhead.cpp
index b42c1c1146..1356afea83 100644
--- a/engines/titanic/game/sgt/bedhead.cpp
+++ b/engines/titanic/game/sgt/bedhead.cpp
@@ -110,7 +110,7 @@ bool CBedhead::TurnOn(CTurnOn *msg) {
setVisible(true);
_statics->_bedhead = entry._name4;
- playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#6.wav");
_isClosed = false;
}
@@ -157,7 +157,7 @@ bool CBedhead::TurnOff(CTurnOff *msg) {
setVisible(true);
_statics->_bedhead = entry._name4;
- playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("193_436_bed fold up 1.wav");
_isClosed = false;
}
diff --git a/engines/titanic/game/sgt/chest_of_drawers.cpp b/engines/titanic/game/sgt/chest_of_drawers.cpp
index 9e00d4fde7..648308fc8f 100644
--- a/engines/titanic/game/sgt/chest_of_drawers.cpp
+++ b/engines/titanic/game/sgt/chest_of_drawers.cpp
@@ -46,7 +46,7 @@ bool CChestOfDrawers::TurnOn(CTurnOn *msg) {
_statics->_chestOfDrawers = "Open";
_startFrame = 1;
_endFrame = 14;
- playMovie(1, 14, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(1, 14, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#11.wav");
}
@@ -62,7 +62,7 @@ bool CChestOfDrawers::TurnOff(CTurnOff *msg) {
_startFrame = 14;
_endFrame = 27;
- playMovie(14, 27, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(14, 27, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#11.wav");
}
diff --git a/engines/titanic/game/sgt/desk.cpp b/engines/titanic/game/sgt/desk.cpp
index a31efe9e5d..1aea9a8ab3 100644
--- a/engines/titanic/game/sgt/desk.cpp
+++ b/engines/titanic/game/sgt/desk.cpp
@@ -47,7 +47,7 @@ bool CDesk::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 1;
_endFrame = 26;
- playMovie(1, 26, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(1, 26, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#12.wav");
}
@@ -64,7 +64,7 @@ bool CDesk::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 26;
_endFrame = 51;
- playMovie(26, 51, MOVIE_GAMESTATE);
+ playMovie(26, 51, MOVIE_WAIT_FOR_FINISH);
playSound("b#9.wav");
}
diff --git a/engines/titanic/game/sgt/deskchair.cpp b/engines/titanic/game/sgt/deskchair.cpp
index 2b25f57d03..23b6ad64d7 100644
--- a/engines/titanic/game/sgt/deskchair.cpp
+++ b/engines/titanic/game/sgt/deskchair.cpp
@@ -48,7 +48,7 @@ bool CDeskchair::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 0;
_endFrame = 16;
- playMovie(0, 16, MOVIE_GAMESTATE);
+ playMovie(0, 16, MOVIE_WAIT_FOR_FINISH);
playSound("b#8.wav");
}
@@ -61,7 +61,7 @@ bool CDeskchair::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 16;
_endFrame = 32;
- playMovie(16, 32, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(16, 32, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#2.wav");
}
diff --git a/engines/titanic/game/sgt/drawer.cpp b/engines/titanic/game/sgt/drawer.cpp
index 68752b3d2f..7288bbdc61 100644
--- a/engines/titanic/game/sgt/drawer.cpp
+++ b/engines/titanic/game/sgt/drawer.cpp
@@ -53,7 +53,7 @@ bool CDrawer::TurnOn(CTurnOn *msg) {
_endFrame = 75;
setVisible(true);
_statics->_drawer = "Open";
- playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#10.wav");
}
@@ -66,7 +66,7 @@ bool CDrawer::TurnOff(CTurnOff *msg) {
_startFrame = 75;
_endFrame = 100;
_isClosed = true;
- playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
playSound("b#10.wav");
}
diff --git a/engines/titanic/game/sgt/sgt_doors.cpp b/engines/titanic/game/sgt/sgt_doors.cpp
index 71eae9800c..2dabd21077 100644
--- a/engines/titanic/game/sgt/sgt_doors.cpp
+++ b/engines/titanic/game/sgt/sgt_doors.cpp
@@ -60,9 +60,9 @@ bool CSGTDoors::EnterViewMsg(CEnterViewMsg *msg) {
if (pet->getRooms1CC() == 1)
playMovie(START_FRAMES[roomNum], END_FRAMES[roomNum],
- MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
else
- playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
return true;
@@ -89,9 +89,9 @@ bool CSGTDoors::LeaveRoomMsg(CLeaveRoomMsg *msg) {
if (pet->getRooms1CC() == 1)
playMovie(START_FRAMES[roomNum], END_FRAMES[roomNum],
- MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
else
- playMovie(12, 25, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(12, 25, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/sgt/sgt_navigation.cpp b/engines/titanic/game/sgt/sgt_navigation.cpp
index 031226226f..d0b57ba1ec 100644
--- a/engines/titanic/game/sgt/sgt_navigation.cpp
+++ b/engines/titanic/game/sgt/sgt_navigation.cpp
@@ -71,9 +71,9 @@ bool CSGTNavigation::StatusChangeMsg(CStatusChangeMsg *msg) {
int startVal = pet->getRooms1CC();
if (startVal > _statics->_changeViewNum)
- playMovie(FRAMES[startVal], FRAMES[_statics->_changeViewNum], MOVIE_GAMESTATE);
+ playMovie(FRAMES[startVal], FRAMES[_statics->_changeViewNum], MOVIE_WAIT_FOR_FINISH);
else
- playMovie(FRAMES[startVal + 3], FRAMES[_statics->_changeViewNum + 3], MOVIE_GAMESTATE);
+ playMovie(FRAMES[startVal + 3], FRAMES[_statics->_changeViewNum + 3], MOVIE_WAIT_FOR_FINISH);
_cursorId = _statics->_changeViewNum != 1 ? CURSOR_MOVE_FORWARD : CURSOR_INVALID;
diff --git a/engines/titanic/game/sgt/sgt_tv.cpp b/engines/titanic/game/sgt/sgt_tv.cpp
index ebec334781..5ce7c5b20e 100644
--- a/engines/titanic/game/sgt/sgt_tv.cpp
+++ b/engines/titanic/game/sgt/sgt_tv.cpp
@@ -46,7 +46,7 @@ bool CSGTTV::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 6;
_endFrame = 12;
- playMovie(6, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(6, 12, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
return true;
@@ -60,7 +60,7 @@ bool CSGTTV::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 1;
_endFrame = 6;
- playMovie(1, 6, MOVIE_GAMESTATE);
+ playMovie(1, 6, MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/sgt/toilet.cpp b/engines/titanic/game/sgt/toilet.cpp
index 544cdda0c6..0f796c2b9d 100644
--- a/engines/titanic/game/sgt/toilet.cpp
+++ b/engines/titanic/game/sgt/toilet.cpp
@@ -50,7 +50,7 @@ bool CToilet::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 0;
_endFrame = 11;
- playMovie(0, 11, MOVIE_GAMESTATE);
+ playMovie(0, 11, MOVIE_WAIT_FOR_FINISH);
playSound("b#1.wav");
}
@@ -64,7 +64,7 @@ bool CToilet::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 11;
_endFrame = 18;
- playMovie(11, 18, MOVIE_GAMESTATE);
+ playMovie(11, 18, MOVIE_WAIT_FOR_FINISH);
playSound("b#1.wav");
}
diff --git a/engines/titanic/game/sgt/vase.cpp b/engines/titanic/game/sgt/vase.cpp
index f9ee292be2..e7b427c28f 100644
--- a/engines/titanic/game/sgt/vase.cpp
+++ b/engines/titanic/game/sgt/vase.cpp
@@ -47,7 +47,7 @@ bool CVase::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 1;
_endFrame = 12;
- playMovie(1, 12, MOVIE_GAMESTATE);
+ playMovie(1, 12, MOVIE_WAIT_FOR_FINISH);
}
return true;
@@ -61,7 +61,7 @@ bool CVase::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 12;
_endFrame = 25;
- playMovie(12, 25, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(12, 25, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
return true;
diff --git a/engines/titanic/game/sgt/washstand.cpp b/engines/titanic/game/sgt/washstand.cpp
index 5be722bec4..217e36c1e9 100644
--- a/engines/titanic/game/sgt/washstand.cpp
+++ b/engines/titanic/game/sgt/washstand.cpp
@@ -47,7 +47,7 @@ bool CWashstand::TurnOn(CTurnOn *msg) {
_isClosed = false;
_startFrame = 0;
_endFrame = 14;
- playMovie(0, 14, MOVIE_GAMESTATE);
+ playMovie(0, 14, MOVIE_WAIT_FOR_FINISH);
playSound("b#14.wav");
}
@@ -61,7 +61,7 @@ bool CWashstand::TurnOff(CTurnOff *msg) {
_isClosed = true;
_startFrame = 14;
_endFrame = 28;
- playMovie(14, 28, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(14, 28, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound("b#14.wav");
}
diff --git a/engines/titanic/game/starling_puret.cpp b/engines/titanic/game/starling_puret.cpp
index 2f1909d963..f598f134ba 100644
--- a/engines/titanic/game/starling_puret.cpp
+++ b/engines/titanic/game/starling_puret.cpp
@@ -59,7 +59,7 @@ bool CStarlingPuret::EnterViewMsg(CEnterViewMsg *msg) {
changeMsg._newStatus = 1;
changeMsg.execute("PromDeckStarlings");
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
CSignalObject signalMsg;
signalMsg._numValue = 4;
signalMsg.execute("PromDeckStarlings");
diff --git a/engines/titanic/game/sub_glass.cpp b/engines/titanic/game/sub_glass.cpp
index 041f49097d..48cc84815a 100644
--- a/engines/titanic/game/sub_glass.cpp
+++ b/engines/titanic/game/sub_glass.cpp
@@ -88,7 +88,7 @@ bool CSUBGlass::SignalObject(CSignalObject *msg) {
setVisible(true);
if (_signalStartFrame >= 0) {
- playMovie(_signalStartFrame, _signalEndFrame, MOVIE_GAMESTATE);
+ playMovie(_signalStartFrame, _signalEndFrame, MOVIE_WAIT_FOR_FINISH);
playSound("z#30.wav");
_fieldBC = false;
}
diff --git a/engines/titanic/game/sweet_bowl.cpp b/engines/titanic/game/sweet_bowl.cpp
index 7a3832e7c2..a1d0dc2b01 100644
--- a/engines/titanic/game/sweet_bowl.cpp
+++ b/engines/titanic/game/sweet_bowl.cpp
@@ -55,7 +55,7 @@ bool CSweetBowl::EnterViewMsg(CEnterViewMsg *msg) {
bool CSweetBowl::ActMsg(CActMsg *msg) {
if (msg->_action == "Jiggle") {
setVisible(true);
- playMovie(MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound(getRandomNumber(1) == 1 ? "b#42.wav" : "b#43.wav");
}
diff --git a/engines/titanic/game/throw_tv_down_well.cpp b/engines/titanic/game/throw_tv_down_well.cpp
index be61f6e9ab..680fc7e29f 100644
--- a/engines/titanic/game/throw_tv_down_well.cpp
+++ b/engines/titanic/game/throw_tv_down_well.cpp
@@ -60,7 +60,7 @@ bool CThrowTVDownWell::ActMsg(CActMsg *msg) {
}
bool CThrowTVDownWell::EnterViewMsg(CEnterViewMsg *msg) {
- playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent(49);
return true;
}
diff --git a/engines/titanic/game/transport/lift.cpp b/engines/titanic/game/transport/lift.cpp
index a6f45bda98..8dfc55905a 100644
--- a/engines/titanic/game/transport/lift.cpp
+++ b/engines/titanic/game/transport/lift.cpp
@@ -120,20 +120,20 @@ bool CLift::StatusChangeMsg(CStatusChangeMsg *msg) {
if (oldClass == newClass) {
debugStr = CString::format("Same (%d-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else if (oldClass == 1 && newClass == 2) {
debugStr = CString::format("1 to 2 (%d-108, 108-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(108, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(108, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else if (oldClass == 1 && newClass == 3) {
debugStr = CString::format("1 to 3 (%d-108, 108-190, 190-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(108, 190, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(108, 190, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else {
debugStr = CString::format("2 to 3 (%d-190, 190-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 190, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 190, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
}
@@ -144,20 +144,20 @@ bool CLift::StatusChangeMsg(CStatusChangeMsg *msg) {
if (oldClass == newClass) {
debugStr = CString::format("Same (%d-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else if (oldClass == 3 && newClass == 2) {
debugStr = CString::format("3 to 2 (%d-407, 407-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(407, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(407, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else if (oldClass == 3 && newClass == 1) {
debugStr = CString::format("3 to 1 (%d-407, 407-489, 489-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(407, 489, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(407, 489, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else {
debugStr = CString::format("2 to 1 (%d-489, 489-%d)", _startFrame, _endFrame);
- playMovie(_startFrame, 489, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_startFrame, 489, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
}
diff --git a/engines/titanic/game/transport/pellerator.cpp b/engines/titanic/game/transport/pellerator.cpp
index 23c61ad0ba..0228f9bc8b 100644
--- a/engines/titanic/game/transport/pellerator.cpp
+++ b/engines/titanic/game/transport/pellerator.cpp
@@ -83,7 +83,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(315, 323, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(299, 304, 0);
- playMovie(305, 313, MOVIE_GAMESTATE);
+ playMovie(305, 313, MOVIE_WAIT_FOR_FINISH);
break;
case 2:
@@ -95,7 +95,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(153, 197, 0);
for (int idx = 0; idx < 5; ++idx)
playMovie(253, 263, 0);
- playMovie(290, 293, MOVIE_GAMESTATE);
+ playMovie(290, 293, MOVIE_WAIT_FOR_FINISH);
break;
case 4:
@@ -107,7 +107,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(253, 263, 0);
for (int idx = 0; idx < 7; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
case 5:
@@ -130,7 +130,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(315, 323, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(299, 304, 0);
- playMovie(305, 313, MOVIE_GAMESTATE);
+ playMovie(305, 313, MOVIE_WAIT_FOR_FINISH);
break;
case 2:
@@ -139,7 +139,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(299, 304, 0);
for (int idx = 0; idx < 15; ++idx)
playMovie(245, 255, 0);
- playMovie(264, 267, MOVIE_GAMESTATE);
+ playMovie(264, 267, MOVIE_WAIT_FOR_FINISH);
++_destination;
break;
@@ -149,7 +149,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(245, 255, 0);
for (int idx = 0; idx < 7; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
case 5:
@@ -160,7 +160,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(245, 255, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(299, 304, 0);
- playMovie(305, 313, MOVIE_GAMESTATE);
+ playMovie(305, 313, MOVIE_WAIT_FOR_FINISH);
break;
default:
@@ -177,14 +177,14 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
"Pellerator.Node 1.N" : "Pellerator.Node 1.S");
if (name == "PelleratorObject") {
- for (; _destination > newDest; --_destination) {
+ for (--_destination; _destination > newDest; --_destination) {
switch (_destination) {
case 0:
case 1:
playMovie(351, 359, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
case 3:
@@ -196,7 +196,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(245, 255, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
--_destination;
break;
@@ -209,7 +209,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(78, 149, 0);
for (int idx = 0; idx < 5; ++idx)
playMovie(245, 255, 0);
- playMovie(264, 267, MOVIE_GAMESTATE);
+ playMovie(264, 267, MOVIE_WAIT_FOR_FINISH);
break;
case 5:
@@ -221,7 +221,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(78, 149, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
default:
@@ -229,14 +229,14 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
}
}
} else {
- for (; _destination > newDest; --_destination) {
+ for (--_destination; _destination > newDest; --_destination) {
switch (_destination) {
case 0:
case 1:
playMovie(351, 359, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
case 3:
@@ -245,7 +245,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(253, 263, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
--_destination;
break;
@@ -255,7 +255,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(299, 304, 0);
for (int idx = 0; idx < 15; ++idx)
playMovie(253, 263, 0);
- playMovie(290, 293, MOVIE_GAMESTATE);
+ playMovie(290, 293, MOVIE_WAIT_FOR_FINISH);
break;
case 5:
@@ -266,7 +266,7 @@ bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) {
playMovie(253, 263, 0);
for (int idx = 0; idx < 3; ++idx)
playMovie(336, 341, 0);
- playMovie(342, 348, MOVIE_GAMESTATE);
+ playMovie(342, 348, MOVIE_WAIT_FOR_FINISH);
break;
default:
diff --git a/engines/titanic/game/wheel_button.cpp b/engines/titanic/game/wheel_button.cpp
index 730a5d9005..71532e52af 100644
--- a/engines/titanic/game/wheel_button.cpp
+++ b/engines/titanic/game/wheel_button.cpp
@@ -31,33 +31,33 @@ BEGIN_MESSAGE_MAP(CWheelButton, CBackground)
END_MESSAGE_MAP()
CWheelButton::CWheelButton() : CBackground(),
- _fieldE0(false), _timerId(0), _fieldE8(0) {
+ _blinking(false), _timerId(0), _unused5(0) {
}
void CWheelButton::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldE0, indent);
+ file->writeNumberLine(_blinking, indent);
file->writeNumberLine(_timerId, indent);
- file->writeNumberLine(_fieldE8, indent);
+ file->writeNumberLine(_unused5, indent);
CBackground::save(file, indent);
}
void CWheelButton::load(SimpleFile *file) {
file->readNumber();
- _fieldE0 = file->readNumber();
+ _blinking = file->readNumber();
_timerId = file->readNumber();
- _fieldE8 = file->readNumber();
+ _unused5 = file->readNumber();
CBackground::load(file);
}
bool CWheelButton::SignalObject(CSignalObject *msg) {
- bool oldFlag = _fieldE0;
- _fieldE0 = msg->_numValue != 0;
+ bool oldBlinking = _blinking;
+ _blinking = msg->_numValue != 0;
- if (oldFlag != _fieldE0) {
- if (_fieldE0) {
+ if (oldBlinking != _blinking) {
+ if (_blinking) {
_timerId = addTimer(500, 500);
} else {
stopAnimTimer(_timerId);
diff --git a/engines/titanic/game/wheel_button.h b/engines/titanic/game/wheel_button.h
index 2725e60622..7bdcecef75 100644
--- a/engines/titanic/game/wheel_button.h
+++ b/engines/titanic/game/wheel_button.h
@@ -33,9 +33,9 @@ class CWheelButton : public CBackground {
bool TimerMsg(CTimerMsg *msg);
bool LeaveViewMsg(CLeaveViewMsg *msg);
public:
- bool _fieldE0;
+ bool _blinking;
int _timerId;
- int _fieldE8;
+ int _unused5;
public:
CLASSDEF;
CWheelButton();
diff --git a/engines/titanic/game/wheel_hotspot.cpp b/engines/titanic/game/wheel_hotspot.cpp
index aeca7130b5..aec1c8b96d 100644
--- a/engines/titanic/game/wheel_hotspot.cpp
+++ b/engines/titanic/game/wheel_hotspot.cpp
@@ -31,36 +31,36 @@ END_MESSAGE_MAP()
void CWheelHotSpot::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_fieldE0, indent);
- file->writeNumberLine(_fieldE4, indent);
+ file->writeNumberLine(_active, indent);
+ file->writeNumberLine(_action, indent);
CBackground::save(file, indent);
}
void CWheelHotSpot::load(SimpleFile *file) {
file->readNumber();
- _fieldE0 = file->readNumber();
- _fieldE4 = file->readNumber();
+ _active = file->readNumber();
+ _action = (WheelHotspotAction)file->readNumber();
CBackground::load(file);
}
bool CWheelHotSpot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
- if (_fieldE0) {
+ if (_active) {
CActMsg actMsg;
- switch (_fieldE4) {
- case 1:
+ switch (_action) {
+ case WH_STOP:
actMsg._action = "Stop";
actMsg.execute("CaptainsWheel");
break;
- case 2:
+ case WH_CRUISE:
actMsg._action = "Cruise";
actMsg.execute("CaptainsWheel");
break;
- case 3:
+ case WH_GO:
actMsg._action = "Go";
actMsg.execute("CaptainsWheel");
break;
@@ -68,7 +68,7 @@ bool CWheelHotSpot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
default:
break;
}
- } else if (_fieldE4 == 3) {
+ } else if (_action == WH_GO) {
petDisplayMessage(GO_WHERE);
}
@@ -76,7 +76,7 @@ bool CWheelHotSpot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
}
bool CWheelHotSpot::SignalObject(CSignalObject *msg) {
- _fieldE0 = msg->_numValue != 0;
+ _active = msg->_numValue != 0;
return true;
}
diff --git a/engines/titanic/game/wheel_hotspot.h b/engines/titanic/game/wheel_hotspot.h
index e9071a2fa4..41da0fba81 100644
--- a/engines/titanic/game/wheel_hotspot.h
+++ b/engines/titanic/game/wheel_hotspot.h
@@ -27,16 +27,20 @@
namespace Titanic {
+enum WheelHotspotAction {
+ WH_NONE = 0, WH_STOP = 1, WH_CRUISE = 2, WH_GO = 3
+};
+
class CWheelHotSpot : public CBackground {
DECLARE_MESSAGE_MAP;
bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
bool SignalObject(CSignalObject *msg);
public:
- int _fieldE0;
- int _fieldE4;
+ bool _active;
+ WheelHotspotAction _action;
public:
CLASSDEF;
- CWheelHotSpot() : CBackground(), _fieldE0(0), _fieldE4(0) {}
+ CWheelHotSpot() : CBackground(), _active(false), _action(WH_NONE) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/game/wheel_spin_horn.cpp b/engines/titanic/game/wheel_spin_horn.cpp
index b01cc678df..c299ffc8ff 100644
--- a/engines/titanic/game/wheel_spin_horn.cpp
+++ b/engines/titanic/game/wheel_spin_horn.cpp
@@ -24,20 +24,39 @@
namespace Titanic {
+BEGIN_MESSAGE_MAP(CWheelSpinHorn, CWheelSpin)
+ ON_MESSAGE(MouseButtonDownMsg)
+END_MESSAGE_MAP()
+
void CWheelSpinHorn::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeQuotedLine(_string1, indent);
- file->writeQuotedLine(_string2, indent);
+ file->writeQuotedLine(_soundName, indent);
+ file->writeQuotedLine(_message, indent);
CWheelSpin::save(file, indent);
}
void CWheelSpinHorn::load(SimpleFile *file) {
file->readNumber();
- _string1 = file->readString();
- _string2 = file->readString();
+ _soundName = file->readString();
+ _message = file->readString();
CWheelSpin::load(file);
}
+bool CWheelSpinHorn::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
+ if (_active) {
+ if (!_soundName.empty())
+ playSound(_soundName);
+
+ if (!_message.empty())
+ petDisplayMessage(_message);
+
+ CActMsg actMsg("Honk");
+ actMsg.execute("CaptainsWheel");
+ }
+
+ return true;
+}
+
} // End of namespace Titanic
diff --git a/engines/titanic/game/wheel_spin_horn.h b/engines/titanic/game/wheel_spin_horn.h
index 21182253b3..b8546b01b6 100644
--- a/engines/titanic/game/wheel_spin_horn.h
+++ b/engines/titanic/game/wheel_spin_horn.h
@@ -28,9 +28,11 @@
namespace Titanic {
class CWheelSpinHorn : public CWheelSpin {
+ DECLARE_MESSAGE_MAP;
+ bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
public:
- CString _string1;
- CString _string2;
+ CString _soundName;
+ CString _message;
public:
CLASSDEF;
diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp
index 96aeda1b83..5f51498e93 100644
--- a/engines/titanic/game_manager.cpp
+++ b/engines/titanic/game_manager.cpp
@@ -276,7 +276,7 @@ void CGameManager::frameMessage(CRoomItem *room) {
CFrameMsg frameMsg(g_vm->_events->getTicksCount());
frameMsg.execute(room, nullptr, MSGFLAG_SCAN);
- if (!_soundMaker) {
+ if (_gameState._soundMakerAllowed && !_soundMaker) {
// Check for a sound maker in the room
_soundMaker = dynamic_cast<CBackgroundSoundMaker *>(
_project->findByName("zBackgroundSoundMaker"));
diff --git a/engines/titanic/game_state.cpp b/engines/titanic/game_state.cpp
index 964d6e604a..7ddd16ab22 100644
--- a/engines/titanic/game_state.cpp
+++ b/engines/titanic/game_state.cpp
@@ -46,8 +46,8 @@ bool CGameStateMovieList::empty() {
CGameState::CGameState(CGameManager *gameManager) :
_gameManager(gameManager), _gameLocation(this), _passengerClass(NO_CLASS),
_priorClass(NO_CLASS), _mode(GSMODE_NONE), _seasonNum(SEASON_SUMMER),
- _petActive(false), _field1C(false), _quitGame(false), _parrotMet(false),
- _nodeChangeCtr(0), _nodeEnterTicks(0), _field38(0) {
+ _petActive(false), _soundMakerAllowed(false), _quitGame(false), _parrotMet(false),
+ _nodeChangeCtr(0), _nodeEnterTicks(0), _parrotResponseIndex(0) {
}
void CGameState::save(SimpleFile *file) const {
@@ -56,9 +56,9 @@ void CGameState::save(SimpleFile *file) const {
file->writeNumber(_priorClass);
file->writeNumber(_seasonNum);
file->writeNumber(_parrotMet);
- file->writeNumber(_field38);
+ file->writeNumber(_parrotResponseIndex);
_gameLocation.save(file);
- file->writeNumber(_field1C);
+ file->writeNumber(_soundMakerAllowed);
}
void CGameState::load(SimpleFile *file) {
@@ -67,10 +67,10 @@ void CGameState::load(SimpleFile *file) {
_priorClass = (PassengerClass)file->readNumber();
_seasonNum = (Season)file->readNumber();
_parrotMet = file->readNumber();
- _field38 = file->readNumber();
+ _parrotResponseIndex = file->readNumber();
_gameLocation.load(file);
- _field1C = file->readNumber();
+ _soundMakerAllowed = file->readNumber();
_nodeChangeCtr = 0;
_nodeEnterTicks = 0;
}
diff --git a/engines/titanic/game_state.h b/engines/titanic/game_state.h
index 5d0f67c02c..547e8f8221 100644
--- a/engines/titanic/game_state.h
+++ b/engines/titanic/game_state.h
@@ -69,13 +69,13 @@ public:
GameStateMode _mode;
Season _seasonNum;
bool _petActive;
- bool _field1C;
+ bool _soundMakerAllowed;
bool _quitGame;
bool _parrotMet;
uint _nodeChangeCtr;
uint32 _nodeEnterTicks;
Point _mousePos;
- int _field38;
+ int _parrotResponseIndex;
public:
CGameState(CGameManager *gameManager);
@@ -151,9 +151,21 @@ public:
*/
bool getParrotMet() const { return _parrotMet; }
+ /**
+ * Gets the counter for the number of times different nodes have
+ * been entered
+ */
int getNodeChangedCtr() const { return _nodeChangeCtr; }
+
+ /**
+ * Gets the node enter ticks amount
+ */
uint32 getNodeEnterTicks() const { return _nodeEnterTicks; }
- void inc38() { ++_field38; }
+
+ /**
+ * Increments the index to use for parrot idle responses
+ */
+ void incParrotResponse() { ++_parrotResponseIndex; }
};
} // End of namespace Titanic
diff --git a/engines/titanic/gfx/music_control.cpp b/engines/titanic/gfx/music_control.cpp
index 317bec209f..40a9f89789 100644
--- a/engines/titanic/gfx/music_control.cpp
+++ b/engines/titanic/gfx/music_control.cpp
@@ -30,7 +30,7 @@ BEGIN_MESSAGE_MAP(CMusicControl, CBackground)
END_MESSAGE_MAP()
CMusicControl::CMusicControl() : CBackground(),
- _controlArea(BELLS), _controlVal(0), _controlMax(1), _fieldEC(1) {
+ _controlArea(BELLS), _controlVal(0), _controlMax(1), _enabled(true) {
}
void CMusicControl::save(SimpleFile *file, int indent) {
@@ -38,17 +38,17 @@ void CMusicControl::save(SimpleFile *file, int indent) {
file->writeNumberLine(_controlArea, indent);
file->writeNumberLine(_controlVal, indent);
file->writeNumberLine(_controlMax, indent);
- file->writeNumberLine(_fieldEC, indent);
+ file->writeNumberLine(_enabled, indent);
CBackground::save(file, indent);
}
void CMusicControl::load(SimpleFile *file) {
file->readNumber();
- _controlArea = (MusicControlArea)file->readNumber();
+ _controlArea = (MusicInstrument)file->readNumber();
_controlVal = file->readNumber();
_controlMax = file->readNumber();
- _fieldEC = file->readNumber();
+ _enabled = file->readNumber();
CBackground::load(file);
}
diff --git a/engines/titanic/gfx/music_control.h b/engines/titanic/gfx/music_control.h
index a0e73392f9..3da063af19 100644
--- a/engines/titanic/gfx/music_control.h
+++ b/engines/titanic/gfx/music_control.h
@@ -33,10 +33,10 @@ class CMusicControl : public CBackground {
bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg);
public:
- MusicControlArea _controlArea;
+ MusicInstrument _controlArea;
int _controlVal;
int _controlMax;
- int _fieldEC;
+ bool _enabled;
public:
CLASSDEF;
CMusicControl();
diff --git a/engines/titanic/gfx/music_slider_pitch.cpp b/engines/titanic/gfx/music_slider_pitch.cpp
index 5f0432e742..49d53f7724 100644
--- a/engines/titanic/gfx/music_slider_pitch.cpp
+++ b/engines/titanic/gfx/music_slider_pitch.cpp
@@ -41,7 +41,7 @@ void CMusicSliderPitch::load(SimpleFile *file) {
}
bool CMusicSliderPitch::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) {
- if (_fieldEC) {
+ if (_enabled) {
if (++_controlVal > _controlMax)
_controlVal = 0;
diff --git a/engines/titanic/gfx/music_slider_speed.cpp b/engines/titanic/gfx/music_slider_speed.cpp
index 93af5d82b7..bc0490677f 100644
--- a/engines/titanic/gfx/music_slider_speed.cpp
+++ b/engines/titanic/gfx/music_slider_speed.cpp
@@ -41,7 +41,7 @@ void CMusicSliderSpeed::load(SimpleFile *file) {
}
bool CMusicSliderSpeed::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) {
- if (_fieldEC) {
+ if (_enabled) {
if (++_controlVal > _controlMax)
_controlVal = 0;
diff --git a/engines/titanic/gfx/music_switch_inversion.cpp b/engines/titanic/gfx/music_switch_inversion.cpp
index d11df79ab4..b6aa1be3e3 100644
--- a/engines/titanic/gfx/music_switch_inversion.cpp
+++ b/engines/titanic/gfx/music_switch_inversion.cpp
@@ -41,7 +41,7 @@ void CMusicSwitchInversion::load(SimpleFile *file) {
}
bool CMusicSwitchInversion::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) {
- if (_fieldEC) {
+ if (_enabled) {
if (++_controlVal > _controlMax)
_controlVal = 0;
diff --git a/engines/titanic/gfx/music_switch_reverse.cpp b/engines/titanic/gfx/music_switch_reverse.cpp
index 9fe6d51d47..674119d571 100644
--- a/engines/titanic/gfx/music_switch_reverse.cpp
+++ b/engines/titanic/gfx/music_switch_reverse.cpp
@@ -39,8 +39,9 @@ void CMusicSwitchReverse::load(SimpleFile *file) {
file->readNumber();
CMusicSwitch::load(file);
}
+
bool CMusicSwitchReverse::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) {
- if (_fieldEC) {
+ if (_enabled) {
if (++_controlVal > _controlMax)
_controlVal = 0;
diff --git a/engines/titanic/gfx/toggle_switch.cpp b/engines/titanic/gfx/toggle_switch.cpp
index 815f96cb5a..dae9acba0e 100644
--- a/engines/titanic/gfx/toggle_switch.cpp
+++ b/engines/titanic/gfx/toggle_switch.cpp
@@ -52,9 +52,9 @@ void CToggleSwitch::load(SimpleFile *file) {
bool CToggleSwitch::MouseButtonUpMsg(CMouseButtonUpMsg *msg) {
_pressed = !_pressed;
if (_pressed)
- fn10(0, 0, 0);
+ setToggleColor(0, 0, 0);
else
- fn10(0xff, 0xff, 0xff);
+ setToggleColor(0xff, 0xff, 0xff);
return true;
}
diff --git a/engines/titanic/messages/messages.h b/engines/titanic/messages/messages.h
index 6832c69f3c..a1e9ccbf9d 100644
--- a/engines/titanic/messages/messages.h
+++ b/engines/titanic/messages/messages.h
@@ -273,7 +273,7 @@ MESSAGE1(CGetChevRoomNum, int, roomNum, 0);
MESSAGE2(CHoseConnectedMsg, bool, connected, true, CGameObject *, object, nullptr);
MESSAGE0(CInitializeAnimMsg);
MESSAGE1(CIsEarBowlPuzzleDone, int, value, 0);
-MESSAGE3(CIsHookedOnMsg, Rect, rect, Rect(), bool, result, false, CString, string1, "");
+MESSAGE3(CIsHookedOnMsg, Rect, rect, Rect(), bool, isHooked, false, CString, armName, "");
MESSAGE1(CIsParrotPresentMsg, bool, value, false);
MESSAGE1(CKeyCharMsg, int, key, 32);
MESSAGE2(CLeaveNodeMsg, CNodeItem *, oldNode, nullptr, CNodeItem *, newNode, nullptr);
@@ -304,8 +304,8 @@ MESSAGE2(CParrotSpeakMsg, CString, target, "", CString, action, "");
MESSAGE2(CParrotTriesChickenMsg, int, value1, 0, int, value2, 0);
MESSAGE1(CPhonographPlayMsg, int, value, 0);
MESSAGE0(CPhonographReadyToPlayMsg);
-MESSAGE1(CPhonographRecordMsg, int, value, 0);
-MESSAGE3(CPhonographStopMsg, int, value1, 0, int, value2, 0, int, value3, 0);
+MESSAGE1(CPhonographRecordMsg, bool, canRecord, false);
+MESSAGE3(CPhonographStopMsg, bool, leavingRoom, false, bool, cylinderPresent, false, bool, dontStop, false);
MESSAGE2(CPlayRangeMsg, int, value1, 0, int, value2, 0);
MESSAGE2(CPlayerTriesRestaurantTableMsg, int, tableId, 0, bool, result, false);
MESSAGE1(CPreSaveMsg, int, value, 0);
@@ -314,7 +314,7 @@ MESSAGE2(CPumpingMsg, int, value, 0, CGameObject *, object, nullptr);
MESSAGE1(CPutBotBackInHisBoxMsg, int, value, 0);
MESSAGE1(CPutParrotBackMsg, int, value, 0);
MESSAGE0(CPuzzleSolvedMsg);
-MESSAGE3(CQueryCylinderHolderMsg, int, value1, 0, int, value2, 0, CTreeItem *, target, (CTreeItem *)nullptr);
+MESSAGE3(CQueryCylinderHolderMsg, bool, isOpen, false, bool, isPresent, false, CTreeItem *, target, (CTreeItem *)nullptr);
MESSAGE1(CQueryCylinderMsg, CString, name, "");
MESSAGE1(CQueryCylinderNameMsg, CString, name, "");
MESSAGE3(CQueryCylinderTypeMsg, int, value1, 0, int, value2, 0, int, value3, 0);
@@ -378,6 +378,7 @@ MESSAGE1(CUseWithCharMsg, CCharacter *, character, nullptr);
MESSAGE1(CUseWithOtherMsg, CGameObject *, other, 0);
MESSAGE1(CVirtualKeyCharMsg, Common::KeyState, keyState, Common::KeyState());
MESSAGE1(CVisibleMsg, bool, visible, true);
+MESSAGE1(CCheckCodeWheelsMsg, bool, isCorrect, true);
} // End of namespace Titanic
diff --git a/engines/titanic/module.mk b/engines/titanic/module.mk
index 51c77ba1dd..35233763d3 100644
--- a/engines/titanic/module.mk
+++ b/engines/titanic/module.mk
@@ -399,6 +399,7 @@ MODULE_OBJS := \
pet_control/pet_show_translation.o \
pet_control/pet_slider.o \
pet_control/pet_sound.o \
+ sound/audio_buffer.o \
sound/auto_music_player.o \
sound/auto_music_player_base.o \
sound/auto_sound_player.o \
@@ -408,10 +409,11 @@ MODULE_OBJS := \
sound/dome_from_top_of_well.o \
sound/enter_view_toggles_other_music.o \
sound/gondolier_song.o \
+ sound/music_player.o \
sound/music_room.o \
sound/music_room_handler.o \
- sound/music_player.o \
- sound/music_wave.o \
+ sound/music_room_instrument.o \
+ sound/music_song.o \
sound/node_auto_sound_player.o \
sound/proximity.o \
sound/qmixer.o \
diff --git a/engines/titanic/moves/enter_bridge.cpp b/engines/titanic/moves/enter_bridge.cpp
index fb44fe2e02..a9fbb5aff1 100644
--- a/engines/titanic/moves/enter_bridge.cpp
+++ b/engines/titanic/moves/enter_bridge.cpp
@@ -45,7 +45,7 @@ bool CEnterBridge::EnterRoomMsg(CEnterRoomMsg *msg) {
CActMsg actMsg("Disable");
actMsg.execute("ShipAnnouncements");
- setState1C(false);
+ stateSetSoundMakerAllowed(false);
_flag = false;
}
diff --git a/engines/titanic/moves/enter_sec_class_state.cpp b/engines/titanic/moves/enter_sec_class_state.cpp
index af2bc4ac00..9ea8ae732a 100644
--- a/engines/titanic/moves/enter_sec_class_state.cpp
+++ b/engines/titanic/moves/enter_sec_class_state.cpp
@@ -85,9 +85,9 @@ bool CEnterSecClassState::StatusChangeMsg(CStatusChangeMsg *msg) {
if (msg->_newStatus != 3) {
if (msg->_newStatus == 2 && _mode == 1)
- playMovie(0, 10, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(0, 10, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
else if (msg->_newStatus == 1)
- playMovie(11, 21, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(11, 21, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
_cursorId = msg->_newStatus == 2 ? CURSOR_MOVE_FORWARD : CURSOR_INVALID;
diff --git a/engines/titanic/npcs/barbot.cpp b/engines/titanic/npcs/barbot.cpp
index 2a0955c3a4..489ed39c4b 100644
--- a/engines/titanic/npcs/barbot.cpp
+++ b/engines/titanic/npcs/barbot.cpp
@@ -25,7 +25,7 @@
namespace Titanic {
-int CBarbot::_v0;
+int CBarbot::_timesCalled;
BEGIN_MESSAGE_MAP(CBarbot, CTrueTalkNPC)
ON_MESSAGE(ActMsg)
@@ -62,14 +62,14 @@ CBarbot::CBarbot() : CTrueTalkNPC() {
_field108 = 0;
_field10C = 0;
_field110 = 0;
- _givenLemon = false;
- _tvGiven = false;
- _field11C = 0;
+ _addedLemon = false;
+ _addedTV = false;
+ _addedPuret = false;
_field120 = 0;
_field124 = 0;
- _field128 = 0;
- _givenPuret = false;
- _field130 = 0;
+ _visCenterOnCounter = false;
+ _addedVodka = false;
+ _gottenDrunk = false;
_field134 = 0;
_field138 = 0;
_field13C = -1;
@@ -79,8 +79,8 @@ CBarbot::CBarbot() : CTrueTalkNPC() {
_field14C = 0;
_field150 = 0;
_field154 = 0;
- _field158 = -1;
- _field15C = 0;
+ _glassContent = GG_DEFAULT;
+ _drunkFlag = false;
_field160 = 0;
}
@@ -89,16 +89,16 @@ void CBarbot::save(SimpleFile *file, int indent) {
file->writeNumberLine(_field108, indent);
file->writeNumberLine(_field10C, indent);
file->writeNumberLine(_field110, indent);
- file->writeNumberLine(_givenLemon, indent);
- file->writeNumberLine(_tvGiven, indent);
- file->writeNumberLine(_field11C, indent);
+ file->writeNumberLine(_addedLemon, indent);
+ file->writeNumberLine(_addedTV, indent);
+ file->writeNumberLine(_addedPuret, indent);
file->writeNumberLine(_field120, indent);
file->writeNumberLine(_field124, indent);
- file->writeNumberLine(_field128, indent);
+ file->writeNumberLine(_visCenterOnCounter, indent);
- file->writeNumberLine(_v0, indent);
- file->writeNumberLine(_givenPuret, indent);
- file->writeNumberLine(_field130, indent);
+ file->writeNumberLine(_timesCalled, indent);
+ file->writeNumberLine(_addedVodka, indent);
+ file->writeNumberLine(_gottenDrunk, indent);
file->writeNumberLine(_field134, indent);
file->writeNumberLine(_field138, indent);
file->writeNumberLine(_field13C, indent);
@@ -108,8 +108,8 @@ void CBarbot::save(SimpleFile *file, int indent) {
file->writeNumberLine(_field14C, indent);
file->writeNumberLine(_field150, indent);
file->writeNumberLine(_field154, indent);
- file->writeNumberLine(_field158, indent);
- file->writeNumberLine(_field15C, indent);
+ file->writeNumberLine(_glassContent, indent);
+ file->writeNumberLine(_drunkFlag, indent);
file->writeNumberLine(_field160, indent);
CTrueTalkNPC::save(file, indent);
@@ -120,16 +120,16 @@ void CBarbot::load(SimpleFile *file) {
_field108 = file->readNumber();
_field10C = file->readNumber();
_field110 = file->readNumber();
- _givenLemon = file->readNumber();
- _tvGiven = file->readNumber();
- _field11C = file->readNumber();
+ _addedLemon = file->readNumber();
+ _addedTV = file->readNumber();
+ _addedPuret = file->readNumber();
_field120 = file->readNumber();
_field124 = file->readNumber();
- _field128 = file->readNumber();
+ _visCenterOnCounter = file->readNumber();
- _v0 = file->readNumber();
- _givenPuret = file->readNumber();
- _field130 = file->readNumber();
+ _timesCalled = file->readNumber();
+ _addedVodka = file->readNumber();
+ _gottenDrunk = file->readNumber();
_field134 = file->readNumber();
_field138 = file->readNumber();
_field13C = file->readNumber();
@@ -139,8 +139,8 @@ void CBarbot::load(SimpleFile *file) {
_field14C = file->readNumber();
_field150 = file->readNumber();
_field154 = file->readNumber();
- _field158 = file->readNumber();
- _field15C = file->readNumber();
+ _glassContent = (GlassGiven)file->readNumber();
+ _drunkFlag = file->readNumber();
_field160 = file->readNumber();
CTrueTalkNPC::load(file);
@@ -148,9 +148,9 @@ void CBarbot::load(SimpleFile *file) {
bool CBarbot::ActMsg(CActMsg *msg) {
if (msg->_action == "Vodka") {
- if (!_givenPuret) {
+ if (!_addedVodka) {
playRange(_frames[47], MOVIE_NOTIFY_OBJECT);
- playRange(_frames[46]);
+ playRange(_frames[46], MOVIE_NOTIFY_OBJECT);
playRange(_frames[40]);
playRange(_frames[7]);
playRange(_frames[13]);
@@ -166,7 +166,7 @@ bool CBarbot::ActMsg(CActMsg *msg) {
playRange(_frames[7]);
playRange(_frames[8]);
playRange(_frames[13]);
- playRange(_frames[40], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playRange(_frames[40], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[40]._endFrame;
}
} else if (msg->_action == "GiveBackVisCentre") {
@@ -178,14 +178,14 @@ bool CBarbot::ActMsg(CActMsg *msg) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
- _field158 = 3;
+ _glassContent = GG_BIRD;
playRange(_frames[32], MOVIE_NOTIFY_OBJECT);
movieEvent();
playRange(_frames[30], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[30]._endFrame;
- if (!_givenLemon || !_tvGiven || !_givenPuret) {
+ if (areIngredientsMissing()) {
playRange(_frames[42], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[42]._endFrame;
}
@@ -196,7 +196,7 @@ bool CBarbot::ActMsg(CActMsg *msg) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
- _field158 = 0;
+ _glassContent = GG_EMPTY;
playRange(_frames[55], MOVIE_NOTIFY_OBJECT);
movieEvent();
@@ -206,7 +206,7 @@ bool CBarbot::ActMsg(CActMsg *msg) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 2;
statusMsg.execute("PickUpGlass");
- _field158 = 1;
+ _glassContent = GG_CONDIMENT;
playRange(_frames[55], MOVIE_NOTIFY_OBJECT);
movieEvent();
@@ -216,17 +216,17 @@ bool CBarbot::ActMsg(CActMsg *msg) {
CActMsg actMsg("InTitilator");
actMsg.execute("BeerGlass");
} else if (msg->_action == "Fruit") {
- if (!_givenLemon) {
+ if (!_addedLemon) {
CActMsg visibleMsg;
visibleMsg.execute("LemonOnBar");
startTalking(this, 250576);
- _givenLemon = true;
+ _addedLemon = true;
playRange(_frames[36], MOVIE_NOTIFY_OBJECT);
movieEvent();
_frameNum = _frames[36]._endFrame;
- if (!_field11C || !_tvGiven || _givenPuret) {
+ if (areIngredientsMissing()) {
playRange(_frames[43], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[43]._endFrame;
}
@@ -235,12 +235,12 @@ bool CBarbot::ActMsg(CActMsg *msg) {
removeMsg.execute("Lemon");
}
} else if (msg->_action == "CrushedTV") {
- if (!_tvGiven) {
+ if (!_addedTV) {
CVisibleMsg visibleMsg;
visibleMsg.execute("TVOnBar");
startTalking(this, 250584);
_field160 = 1;
- _tvGiven = true;
+ _addedTV = true;
playSound("c#5.wav", _volume);
playRange(_frames[35], MOVIE_NOTIFY_OBJECT);
@@ -249,7 +249,7 @@ bool CBarbot::ActMsg(CActMsg *msg) {
playRange(_frames[33], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[33]._endFrame;
- if (!_field11C || !_givenLemon || !_givenPuret) {
+ if (areIngredientsMissing()) {
playRange(_frames[41], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[41]._endFrame;
}
@@ -265,7 +265,7 @@ bool CBarbot::ActMsg(CActMsg *msg) {
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
} else if (msg->_action == "PlayerTakesVisCentre") {
- _field128 = 0;
+ _visCenterOnCounter = false;
loadFrame(0);
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
@@ -307,16 +307,16 @@ bool CBarbot::TurnOn(CTurnOn *msg) {
setVisible(true);
CGameObject *glass = findInRoom("BeerGlass");
- if (!_field130) {
+ if (!_gottenDrunk) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("BarShelfVisCentre");
}
- if (glass && !_field11C) {
+ if (glass && !_addedPuret) {
playRange(_frames[38], MOVIE_NOTIFY_OBJECT);
playRange(_frames[58], MOVIE_NOTIFY_OBJECT);
playRange(_frames[57], MOVIE_NOTIFY_OBJECT);
- playRange(_frames[56], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playRange(_frames[56], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[56]._endFrame;
} else {
playRange(_frames[38]);
@@ -340,7 +340,7 @@ bool CBarbot::TurnOn(CTurnOn *msg) {
}
_fieldC4 = 1;
- ++_v0;
+ ++_timesCalled;
petSetArea(PET_CONVERSATION);
setTalking(this, true);
}
@@ -361,14 +361,15 @@ bool CBarbot::TurnOff(CTurnOff *msg) {
_field124 = 0;
}
- if (_field128) {
- playRange(_frames[28], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ if (_visCenterOnCounter) {
+ // Barbot will put away the vision center
+ playRange(_frames[28], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[28]._endFrame;
- _field128 = 0;
+ _visCenterOnCounter = false;
_field134 = 1;
}
- playRange(_frames[29], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playRange(_frames[29], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent(_frames[29]._startFrame);
_frameNum = _frames[29]._endFrame;
_fieldC4 = 0;
@@ -397,7 +398,7 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
if (msg->_endFrame == _field13C) {
if (_field124)
playMovie(_frames[53]._startFrame, _frames[53]._startFrame, 0);
- else if (_field128)
+ else if (_visCenterOnCounter)
playMovie(_frames[27]._endFrame, _frames[27]._endFrame, 0);
_field13C = -1;
@@ -438,7 +439,7 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
}
if (msg->_endFrame == _frames[45]._endFrame) {
- if (!_field130) {
+ if (!_gottenDrunk) {
CVisibleMsg visibleMsg(false);
visibleMsg.execute("BarShelfVisCentre");
}
@@ -447,7 +448,9 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
}
if (msg->_endFrame == _frames[44]._endFrame) {
- _field128 = _field130 = 1;
+ _visCenterOnCounter = true;
+ _gottenDrunk = true;
+ startTalking(this, 250586);
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
statusMsg.execute("PickUpVisCentre");
@@ -456,7 +459,7 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
}
if (msg->_endFrame == _frames[46]._endFrame) {
- if (!_field130 && !_givenPuret && _field11C && _givenLemon && _tvGiven)
+ if (!_gottenDrunk && !areIngredientsMissing())
startTalking(this, 250571);
return true;
}
@@ -473,19 +476,17 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
playSound("c#3.wav", _volume);
} else if (msg->_endFrame == _frames[36]._endFrame) {
playSound("c#6.wav", _volume);
- }
- else if (msg->_endFrame == _frames[35]._endFrame) {
+ } else if (msg->_endFrame == _frames[35]._endFrame) {
playSound("c#8.wav", _volume);
- }
- else if (msg->_endFrame == _frames[33]._endFrame) {
+ } else if (msg->_endFrame == _frames[33]._endFrame) {
playSound("c#4.wav", _volume);
} else if (msg->_endFrame == _frames[32]._endFrame) {
startTalking(this, 145);
playSound("c#9.wav", _volume);
} else if (msg->_endFrame == _frames[47]._endFrame) {
playSound("c#9.wav", _volume);
- _givenPuret = true;
- _field15C = 1;
+ _addedVodka = true;
+ _drunkFlag = true;
} else if (msg->_endFrame == _frames[30]._endFrame) {
playSound("c#4.wav", 60);
} else if (msg->_endFrame == _frames[29]._endFrame) {
@@ -499,7 +500,7 @@ bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) {
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 1;
statusMsg.execute("PickUpVisCentre");
- _field128 = 1;
+ _visCenterOnCounter = true;
_field134 = 0;
startTalking(this, 250586);
}
@@ -518,8 +519,8 @@ bool CBarbot::TrueTalkQueueUpAnimSetMsg(CTrueTalkQueueUpAnimSetMsg *msg) {
bool CBarbot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) {
switch (msg->_stateNum) {
case 2:
- if (!_field130) {
- if (_field15C) {
+ if (!_gottenDrunk) {
+ if (_drunkFlag) {
msg->_stateVal = _field134 | 1;
return true;
}
@@ -530,18 +531,18 @@ bool CBarbot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) {
case 3:
msg->_stateVal = 0;
- if (_givenLemon)
+ if (_addedLemon)
msg->_stateVal = 1;
- if (_givenPuret)
+ if (_addedVodka)
msg->_stateVal |= 2;
- if (_field11C)
+ if (_addedPuret)
msg->_stateVal |= 4;
- if (_tvGiven)
+ if (_addedTV)
msg->_stateVal |= 8;
break;
case 9:
- msg->_stateVal = _field15C ? 1 : 0;
+ msg->_stateVal = _drunkFlag ? 1 : 0;
break;
default:
@@ -557,21 +558,23 @@ bool CBarbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
if (_field134) {
playRange(_frames[27], MOVIE_NOTIFY_OBJECT);
_frameNum = _frames[27]._endFrame;
- } else if (!_field130 && _field15C) {
+ } else if (!_gottenDrunk && _drunkFlag) {
playRange(_frames[45], MOVIE_NOTIFY_OBJECT);
- playRange(_frames[44], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playRange(_frames[44], MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_frameNum = _frames[44]._endFrame;
}
break;
case 7: {
+ // "add vodka"
CActMsg actMsg("Vodka");
actMsg.execute(this);
break;
}
case 30:
- _field11C = 1;
+ // "starling puret"
+ _addedPuret = true;
break;
default:
@@ -587,7 +590,7 @@ bool CBarbot::FrameMsg(CFrameMsg *msg) {
|| (msg->_ticks - _field150) <= 1000)
return true;
- if (!_field15C) {
+ if (!_drunkFlag) {
if (++_field154 > 2) {
playRange(_frames[0]);
playRange(_frames[1], MOVIE_NOTIFY_OBJECT);
@@ -625,7 +628,7 @@ bool CBarbot::FrameMsg(CFrameMsg *msg) {
break;
case 5:
- if (!_field160 && !_field128) {
+ if (!_field160 && !_visCenterOnCounter) {
playRange(_frames[15], MOVIE_NOTIFY_OBJECT);
_field148 = _frames[15]._endFrame;
}
@@ -698,18 +701,21 @@ bool CBarbot::MovieFrameMsg(CMovieFrameMsg *msg) {
} else if (msg->_frameNumber == _frames[55]._startFrame
|| msg->_frameNumber == _frames[32]._startFrame) {
+ // Finished giving the Barbot a glass
CStatusChangeMsg statusMsg;
statusMsg._newStatus = 0;
statusMsg.execute("PickUpGlass");
- if (_field158 == 0) {
+ if (_glassContent == GG_EMPTY) {
+ // I'd rather see that full of Starling Puret
startTalking(this, 250574);
- } else if (_field158 > 0 && _field158 <= 3) {
+ } else if (_glassContent > GG_EMPTY) {
+ // What's this?
startTalking(this, 250580);
petSetArea(PET_CONVERSATION);
}
- _field158 = -1;
+ _glassContent = GG_DEFAULT;
} else if (msg->_frameNumber == _frames[36]._startFrame) {
CVisibleMsg visibleMsg(false);
diff --git a/engines/titanic/npcs/barbot.h b/engines/titanic/npcs/barbot.h
index cc183be58f..c40f83ec21 100644
--- a/engines/titanic/npcs/barbot.h
+++ b/engines/titanic/npcs/barbot.h
@@ -28,6 +28,8 @@
namespace Titanic {
+enum GlassGiven { GG_DEFAULT = -1, GG_EMPTY = 0, GG_CONDIMENT = 1, GG_BIRD = 3 };
+
class CBarbot : public CTrueTalkNPC {
struct FrameRange {
int _startFrame;
@@ -56,20 +58,20 @@ class CBarbot : public CTrueTalkNPC {
bool EnterRoomMsg(CEnterRoomMsg *msg);
bool TimerMsg(CTimerMsg *msg);
private:
- static int _v0;
+ static int _timesCalled;
private:
FrameRanges _frames;
int _field108;
int _field10C;
int _field110;
- bool _givenLemon;
- bool _tvGiven;
- int _field11C;
+ bool _addedLemon;
+ bool _addedTV;
+ bool _addedPuret;
int _field120;
int _field124;
- int _field128;
- bool _givenPuret;
- int _field130;
+ bool _visCenterOnCounter;
+ bool _addedVodka;
+ bool _gottenDrunk;
int _field134;
int _field138;
int _field13C;
@@ -79,14 +81,22 @@ private:
int _field14C;
int _field150;
int _field154;
- int _field158;
- int _field15C;
+ GlassGiven _glassContent;
+ bool _drunkFlag;
int _field160;
private:
/**
* Plays a given range of movie frames
*/
void playRange(const FrameRange &range, uint flags = 0);
+
+ /**
+ * Returns true if one of the ingredients (with the exception of Vodka)
+ * is missing from the concoction
+ */
+ bool areIngredientsMissing() const {
+ return !_addedPuret || !_addedLemon || !_addedVodka;
+ }
public:
CLASSDEF;
CBarbot();
diff --git a/engines/titanic/npcs/bellbot.cpp b/engines/titanic/npcs/bellbot.cpp
index 26c9b13e40..1782161aea 100644
--- a/engines/titanic/npcs/bellbot.cpp
+++ b/engines/titanic/npcs/bellbot.cpp
@@ -89,7 +89,7 @@ bool CBellBot::OnSummonBotMsg(COnSummonBotMsg *msg) {
_npcFlags &= ~NPCFLAG_MOVE_LOOP;
}
- playClip("Walk On", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playClip("Walk On", MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent();
_npcFlags |= NPCFLAG_MOVING;
@@ -135,13 +135,15 @@ bool CBellBot::MovieEndMsg(CMovieEndMsg *msg) {
}
bool CBellBot::Use(CUse *msg) {
- dynamic_cast<CCarry *>(msg->_item)->_string1 = "Bellbot";
+ CCarry *item = dynamic_cast<CCarry *>(msg->_item);
+ assert(item);
+ item->_npcUse = "Bellbot";
return true;
}
bool CBellBot::DismissBotMsg(CDismissBotMsg *msg) {
if (_npcFlags & NPCFLAG_MOVING) {
- playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
if (_npcFlags & NPCFLAG_START_IDLING) {
_npcFlags &= ~NPCFLAG_START_IDLING;
performAction(true);
@@ -168,7 +170,7 @@ bool CBellBot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
case 5:
_npcFlags &= ~NPCFLAG_MOVE_START;
- playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent();
break;
diff --git a/engines/titanic/npcs/bilge_succubus.cpp b/engines/titanic/npcs/bilge_succubus.cpp
index 63d0006885..4db4d8d595 100644
--- a/engines/titanic/npcs/bilge_succubus.cpp
+++ b/engines/titanic/npcs/bilge_succubus.cpp
@@ -75,9 +75,9 @@ bool CBilgeSuccUBus::PETReceiveMsg(CPETReceiveMsg *msg) {
if (_style) {
if (_receiveStartFrame >= 0)
- playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_GAMESTATE);
+ playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_WAIT_FOR_FINISH);
if (_afterReceiveStartFrame >= 0)
- playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_GAMESTATE);
+ playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_WAIT_FOR_FINISH);
playSound("z#28.wav", 70);
} else if (!_isOn) {
@@ -94,7 +94,7 @@ bool CBilgeSuccUBus::PETReceiveMsg(CPETReceiveMsg *msg) {
if (mailObject) {
_mailP = mailObject;
if (_receiveStartFrame >= 0)
- playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_GAMESTATE);
+ playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_WAIT_FOR_FINISH);
} else {
petDisplayMessage(2, NOTHING_TO_DELIVER);
}
@@ -138,20 +138,20 @@ bool CBilgeSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) {
playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT);
if (_sneezing2StartFrame >= 0) {
- playMovie(_trayOutStartFrame, _trayOutEndFrame, MOVIE_GAMESTATE);
- playMovie(_sneezing1StartFrame, _sneezing1EndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
- playMovie(_sneezing2StartFrame, _sneezing2EndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_trayOutStartFrame, _trayOutEndFrame, MOVIE_WAIT_FOR_FINISH);
+ playMovie(_sneezing1StartFrame, _sneezing1EndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
+ playMovie(_sneezing2StartFrame, _sneezing2EndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
incTransitions();
}
} else {
startTalking(this, 230012);
_sendAction = SA_EATEN;
if (_sendStartFrame >= 0)
- playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
if (_receiveStartFrame >= 0)
- playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
if (_afterReceiveStartFrame >= 0)
- playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_GAMESTATE);
+ playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_WAIT_FOR_FINISH);
}
} else {
if (_isFeathers) {
@@ -159,17 +159,17 @@ bool CBilgeSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) {
_sendAction = SA_BILGE_FEATHERS;
if (_sendStartFrame >= 0)
- playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
if (_receiveStartFrame >= 0)
- playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
if (_afterReceiveStartFrame >= 0)
- playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_afterReceiveStartFrame, _afterReceiveEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
} else {
sendMail(petRoomFlags, roomFlags);
startTalking(this, 230012);
if (_sendStartFrame >= 0) {
_sendAction = SA_BILGE_SENT;
- playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_sendStartFrame, _sendEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
}
}
diff --git a/engines/titanic/npcs/deskbot.cpp b/engines/titanic/npcs/deskbot.cpp
index 56f4d98f18..2b88160e47 100644
--- a/engines/titanic/npcs/deskbot.cpp
+++ b/engines/titanic/npcs/deskbot.cpp
@@ -306,7 +306,7 @@ bool CDeskbot::TurnOff(CTurnOff *msg) {
performAction(1, findView());
_npcFlags = (_npcFlags & ~(NPCFLAG_SPEAKING | NPCFLAG_IDLING | NPCFLAG_START_IDLING)) | NPCFLAG_MOVE_LOOP;
- playClip("Closing", MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playClip("Closing", MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
}
return true;
diff --git a/engines/titanic/npcs/doorbot.cpp b/engines/titanic/npcs/doorbot.cpp
index 79e3dafed4..03d723a384 100644
--- a/engines/titanic/npcs/doorbot.cpp
+++ b/engines/titanic/npcs/doorbot.cpp
@@ -95,7 +95,7 @@ bool CDoorbot::MovieEndMsg(CMovieEndMsg *msg) {
case 6:
if (clipExistsByEnd("Cloak On", msg->_endFrame)) {
petShow();
- setState1C(true);
+ stateSetSoundMakerAllowed(true);
changeView("ServiceElevator.Node 1.S");
changeView("ServiceElevator.Node 1.N");
}
@@ -129,7 +129,7 @@ bool CDoorbot::MovieEndMsg(CMovieEndMsg *msg) {
_introMovieNum = 0;
} else if (clipExistsByEnd("Cloak On", msg->_endFrame)) {
petShow();
- setState1C(true);
+ stateSetSoundMakerAllowed(true);
changeView("ServiceElevator.Node 1.S");
} else {
CTrueTalkNPC::MovieEndMsg(msg);
@@ -185,7 +185,7 @@ bool CDoorbot::OnSummonBotMsg(COnSummonBotMsg *msg) {
}
playClip(getRandomNumber(1) ? "Whizz On Left" : "Whizz On Right",
- MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent();
_npcFlags |= NPCFLAG_MOVE_END;
@@ -200,7 +200,7 @@ bool CDoorbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
case 4:
_npcFlags = (_npcFlags & ~NPCFLAG_IDLING) | NPCFLAG_SUMMON_BELLBOT;
- playClip("Whizz Off Left", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playClip("Whizz Off Left", MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
break;
case 28: {
@@ -387,7 +387,7 @@ bool CDoorbot::PutBotBackInHisBoxMsg(CPutBotBackInHisBoxMsg *msg) {
bool CDoorbot::DismissBotMsg(CDismissBotMsg *msg) {
if (_npcFlags & NPCFLAG_MOVE_END) {
playClip(getRandomNumber(1) ? "Whizz Off Left" : "Whizz Off Right",
- MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
movieEvent();
if (_npcFlags & NPCFLAG_START_IDLING) {
diff --git a/engines/titanic/npcs/maitre_d.cpp b/engines/titanic/npcs/maitre_d.cpp
index cbb406fffa..6ac69d9079 100644
--- a/engines/titanic/npcs/maitre_d.cpp
+++ b/engines/titanic/npcs/maitre_d.cpp
@@ -40,25 +40,24 @@ BEGIN_MESSAGE_MAP(CMaitreD, CTrueTalkNPC)
ON_MESSAGE(TriggerNPCEvent)
END_MESSAGE_MAP()
-int CMaitreD::_v1;
-
CMaitreD::CMaitreD() : CTrueTalkNPC(),
- _string2("z#40.wav"), _string3("z#40.wav"), _field108(0), _field118(1),
- _field11C(0), _field12C(0), _field130(1), _field134(0), _timerId(0) {
+ _priorMusicName("z#40.wav"), _musicName("z#40.wav"), _unused5(0), _hasMusic(true),
+ _musicSet(false), _fightFlag(false), _unused6(true), _savedFightFlag(false),
+ _timerId(0), _defeated(false) {
}
void CMaitreD::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_field108, indent);
- file->writeQuotedLine(_string2, indent);
- file->writeNumberLine(_field118, indent);
- file->writeNumberLine(_field11C, indent);
- file->writeQuotedLine(_string3, indent);
- file->writeNumberLine(_field12C, indent);
- file->writeNumberLine(_field130, indent);
-
- file->writeNumberLine(_v1, indent);
- file->writeNumberLine(_field134, indent);
+ file->writeNumberLine(_unused5, indent);
+ file->writeQuotedLine(_priorMusicName, indent);
+ file->writeNumberLine(_hasMusic, indent);
+ file->writeNumberLine(_musicSet, indent);
+ file->writeQuotedLine(_musicName, indent);
+ file->writeNumberLine(_fightFlag, indent);
+ file->writeNumberLine(_unused6, indent);
+
+ file->writeNumberLine(_defeated, indent);
+ file->writeNumberLine(_savedFightFlag, indent);
file->writeNumberLine(_timerId, indent);
CTrueTalkNPC::save(file, indent);
@@ -66,16 +65,16 @@ void CMaitreD::save(SimpleFile *file, int indent) {
void CMaitreD::load(SimpleFile *file) {
file->readNumber();
- _field108 = file->readNumber();
- _string2 = file->readString();
- _field118 = file->readNumber();
- _field11C = file->readNumber();
- _string3 = file->readString();
- _field12C = file->readNumber();
- _field130 = file->readNumber();
-
- _v1 = file->readNumber();
- _field134 = file->readNumber();
+ _unused5 = file->readNumber();
+ _priorMusicName = file->readString();
+ _hasMusic = file->readNumber();
+ _musicSet = file->readNumber();
+ _musicName = file->readString();
+ _fightFlag = file->readNumber();
+ _unused6 = file->readNumber();
+
+ _defeated = file->readNumber();
+ _savedFightFlag = file->readNumber();
_timerId = file->readNumber();
CTrueTalkNPC::load(file);
@@ -83,10 +82,10 @@ void CMaitreD::load(SimpleFile *file) {
bool CMaitreD::RestaurantMusicChanged(CRestaurantMusicChanged *msg) {
if (msg->_value.empty()) {
- _field118 = 0;
+ _hasMusic = false;
} else {
- _string3 = msg->_value;
- _field118 = _field11C = 1;
+ _musicName = msg->_value;
+ _hasMusic = _musicSet = true;
}
return true;
@@ -94,15 +93,15 @@ bool CMaitreD::RestaurantMusicChanged(CRestaurantMusicChanged *msg) {
bool CMaitreD::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
if (msg->_action == 8) {
- _field12C = 1;
+ _fightFlag = true;
stopAnimTimer(_timerId);
_timerId = startAnimTimer("MD Fight", 3500, 0);
} else if (msg->_action == 9) {
stopAnimTimer(_timerId);
_timerId = 0;
} else if (msg->_action == 10) {
- _field12C = 0;
- _v1 = 1;
+ _fightFlag = false;
+ _defeated = true;
stopAnimTimer(_timerId);
_timerId = 0;
@@ -115,18 +114,23 @@ bool CMaitreD::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) {
bool CMaitreD::EnterViewMsg(CEnterViewMsg *msg) {
setTalking(this, true, findView());
- _field12C = _field134;
+ _fightFlag = _savedFightFlag;
+
+ if (_musicName != "STMusic" && (!_musicSet || _priorMusicName == _musicName))
+ return true;
- if (_string3 == "STMusic" && (!_field11C || _string2 == _string3))
+ // WORKAROUND: It's possible in the original to not have a music handler set
+ // if you start and stop the phonograph, then save and restore the game
+ if (!CMusicRoom::_musicHandler)
return true;
- if (_string3.contains("nasty ambient"))
+ if (_musicName.contains("nasty ambient"))
startTalking(this, 111, findView());
- else if (!CMusicRoom::_musicHandler->checkSound(1))
+ else if (!CMusicRoom::_musicHandler->checkInstrument(SNAKE))
startTalking(this, 114, findView());
- else if (!CMusicRoom::_musicHandler->checkSound(3))
+ else if (!CMusicRoom::_musicHandler->checkInstrument(BASS))
startTalking(this, 113, findView());
- else if (!CMusicRoom::_musicHandler->checkSound(2))
+ else if (!CMusicRoom::_musicHandler->checkInstrument(PIANO))
startTalking(this, 115, findView());
else {
startTalking(this, 110, findView());
@@ -135,16 +139,17 @@ bool CMaitreD::EnterViewMsg(CEnterViewMsg *msg) {
happyMsg.execute("MaitreD Right Arm");
}
+ _priorMusicName = _musicName;
return true;
}
bool CMaitreD::LeaveViewMsg(CLeaveViewMsg *msg) {
- _field134 = _field12C;
+ _savedFightFlag = _fightFlag;
performAction(true);
stopAnimTimer(_timerId);
_timerId = 0;
- _field12C = 0;
+ _fightFlag = false;
return true;
}
@@ -158,7 +163,7 @@ bool CMaitreD::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) {
msg->_names = NAMES;
CAnimateMaitreDMsg animMsg;
- if (_field12C)
+ if (_fightFlag)
animMsg._value = 0;
animMsg.execute(this);
}
@@ -168,7 +173,7 @@ bool CMaitreD::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) {
bool CMaitreD::TimerMsg(CTimerMsg *msg) {
if (msg->_action == "MD Fight") {
- if (_field12C && compareViewNameTo("1stClassRestaurant.MaitreD Node.N")) {
+ if (_fightFlag && compareViewNameTo("1stClassRestaurant.MaitreD Node.N")) {
startTalking(this, 131, findView());
}
} else {
@@ -179,7 +184,7 @@ bool CMaitreD::TimerMsg(CTimerMsg *msg) {
}
bool CMaitreD::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg) {
- if (_field12C) {
+ if (_fightFlag) {
stopAnimTimer(_timerId);
_timerId = 0;
}
@@ -189,7 +194,7 @@ bool CMaitreD::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *m
}
bool CMaitreD::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) {
- if (_field12C) {
+ if (_fightFlag) {
stopAnimTimer(_timerId);
_timerId = startAnimTimer("MD Fight", 3000 + getRandomNumber(3000));
}
@@ -199,7 +204,7 @@ bool CMaitreD::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg)
}
bool CMaitreD::LoadSuccessMsg(CLoadSuccessMsg *msg) {
- if (_field12C) {
+ if (_fightFlag) {
_timerId = startAnimTimer("MD Fight", 3000 + getRandomNumber(3000));
}
diff --git a/engines/titanic/npcs/maitre_d.h b/engines/titanic/npcs/maitre_d.h
index 878c32cc0b..6677a587a8 100644
--- a/engines/titanic/npcs/maitre_d.h
+++ b/engines/titanic/npcs/maitre_d.h
@@ -41,17 +41,16 @@ class CMaitreD : public CTrueTalkNPC {
bool TextInputMsg(CTextInputMsg *msg);
bool TriggerNPCEvent(CTriggerNPCEvent *msg);
private:
- static int _v1;
-private:
- int _field108;
- CString _string2;
- int _field118;
- int _field11C;
- CString _string3;
- int _field12C;
- int _field130;
- int _field134;
+ int _unused5;
+ CString _priorMusicName;
+ bool _hasMusic;
+ bool _musicSet;
+ CString _musicName;
+ bool _fightFlag;
+ bool _unused6;
+ bool _savedFightFlag;
int _timerId;
+ bool _defeated;
public:
CLASSDEF;
CMaitreD();
diff --git a/engines/titanic/npcs/parrot.cpp b/engines/titanic/npcs/parrot.cpp
index b570bea6ae..6a48837d08 100644
--- a/engines/titanic/npcs/parrot.cpp
+++ b/engines/titanic/npcs/parrot.cpp
@@ -43,6 +43,7 @@ BEGIN_MESSAGE_MAP(CParrot, CTrueTalkNPC)
ON_MESSAGE(PreEnterViewMsg)
ON_MESSAGE(PanningAwayFromParrotMsg)
ON_MESSAGE(LeaveRoomMsg)
+ ON_MESSAGE(TrueTalkNotifySpeechEndedMsg)
END_MESSAGE_MAP()
bool CParrot::_eatingChicken;
@@ -475,7 +476,7 @@ bool CParrot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) {
}
} else {
int id = -1;
- switch (stateGet38()) {
+ switch (getParrotResponse()) {
case 0:
id = 280107;
break;
@@ -729,4 +730,15 @@ bool CParrot::LeaveRoomMsg(CLeaveRoomMsg *msg) {
return true;
}
+bool CParrot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) {
+ if (msg->_dialogueId == 80022) {
+ // WORKAROUND: End of parrot speech after having fixed Titania
+ unlockMouse();
+ changeView("Titania.Node 18.N", "");
+ }
+
+ return CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg);
+}
+
+
} // End of namespace Titanic
diff --git a/engines/titanic/npcs/parrot.h b/engines/titanic/npcs/parrot.h
index c178a2086a..d3558dfa3e 100644
--- a/engines/titanic/npcs/parrot.h
+++ b/engines/titanic/npcs/parrot.h
@@ -51,6 +51,7 @@ class CParrot : public CTrueTalkNPC {
bool PreEnterViewMsg(CPreEnterViewMsg *msg);
bool PanningAwayFromParrotMsg(CPanningAwayFromParrotMsg *msg);
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
+ bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg);
public:
static bool _eatingChicken;
static bool _takeOff;
diff --git a/engines/titanic/npcs/succubus.cpp b/engines/titanic/npcs/succubus.cpp
index 71272fad03..ef681f64b8 100644
--- a/engines/titanic/npcs/succubus.cpp
+++ b/engines/titanic/npcs/succubus.cpp
@@ -701,11 +701,11 @@ bool CSuccUBus::TurnOff(CTurnOff *msg) {
if (_offStartFrame >= 0) {
playSound("z#27.wav", 100);
- playMovie(_offStartFrame, _offEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_offStartFrame, _offEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
}
if (!_signalFlag && _endingStartFrame >= 0)
- playMovie(_endingStartFrame, _endingEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE);
+ playMovie(_endingStartFrame, _endingEndFrame, MOVIE_NOTIFY_OBJECT | MOVIE_WAIT_FOR_FINISH);
_isOn = false;
performAction(true);
diff --git a/engines/titanic/npcs/titania.cpp b/engines/titanic/npcs/titania.cpp
index db0c85d5f5..e0ea4f1459 100644
--- a/engines/titanic/npcs/titania.cpp
+++ b/engines/titanic/npcs/titania.cpp
@@ -43,7 +43,7 @@ CTitania::CTitania() : CCharacter() {
_ear2 = false;
_nose = false;
_mouth = false;
- _showIntro = true;
+ _showSpeech = true;
}
void CTitania::save(SimpleFile *file, int indent) {
@@ -59,7 +59,7 @@ void CTitania::save(SimpleFile *file, int indent) {
file->writeNumberLine(_ear2, indent);
file->writeNumberLine(_nose, indent);
file->writeNumberLine(_mouth, indent);
- file->writeNumberLine(_showIntro, indent);
+ file->writeNumberLine(_showSpeech, indent);
CCharacter::save(file, indent);
}
@@ -77,7 +77,7 @@ void CTitania::load(SimpleFile *file) {
_ear2 = file->readNumber();
_nose = file->readNumber();
_mouth = file->readNumber();
- _showIntro = file->readNumber();
+ _showSpeech = file->readNumber();
CCharacter::load(file);
}
@@ -99,7 +99,7 @@ bool CTitania::AddHeadPieceMsg(CAddHeadPieceMsg *msg) {
_eye2 = true;
} else if (msg->_value == "Ear1") {
_ear1 = true;
- } else if (msg->_value == "Ear2") {
+ } else if (msg->_value == "Ear 2") {
_ear2 = true;
} else if (msg->_value == "Mouth") {
_mouth = true;
@@ -197,8 +197,8 @@ bool CTitania::ActMsg(CActMsg *msg) {
}
bool CTitania::EnterViewMsg(CEnterViewMsg *msg) {
- if (_showIntro) {
- _showIntro = false;
+ if (_showSpeech) {
+ _showSpeech = false;
disableMouse();
petHide();
@@ -216,8 +216,11 @@ bool CTitania::EnterViewMsg(CEnterViewMsg *msg) {
}
bool CTitania::TimerMsg(CTimerMsg *msg) {
- changeView("Titania.Node 18.N", "");
+ // WORKAROUND: The original uses the disc change dialog as a pause
+ // to allow the parrot speech to finish. I've rewritten it to instead
+ // use the standard TrueTalkNotifySpeechEndedMsg message instead
startTalking("PerchedParrot", 80022);
+ lockMouse();
return true;
}
diff --git a/engines/titanic/npcs/titania.h b/engines/titanic/npcs/titania.h
index 61f8c86018..f94442d317 100644
--- a/engines/titanic/npcs/titania.h
+++ b/engines/titanic/npcs/titania.h
@@ -46,7 +46,7 @@ private:
bool _ear2;
bool _nose;
bool _mouth;
- bool _showIntro;
+ bool _showSpeech;
public:
CLASSDEF;
CTitania();
diff --git a/engines/titanic/sound/audio_buffer.cpp b/engines/titanic/sound/audio_buffer.cpp
new file mode 100644
index 0000000000..636f4a5107
--- /dev/null
+++ b/engines/titanic/sound/audio_buffer.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.
+ *
+ */
+
+#include "titanic/sound/audio_buffer.h"
+#include "common/algorithm.h"
+
+namespace Titanic {
+
+CAudioBuffer::CAudioBuffer(int maxSize) : _finished(false) {
+ _data.resize(maxSize);
+ reset();
+}
+
+void CAudioBuffer::reset() {
+ _frontP = _backP = &_data[0];
+}
+
+void CAudioBuffer::push(int16 value) {
+ assert(!full());
+ compact();
+
+ *_backP++ = value;
+}
+
+void CAudioBuffer::push(int16 *values, int count) {
+ compact();
+ assert(freeSize() >= count);
+
+ Common::copy(values, values + count, _backP);
+ _backP += count;
+}
+
+int16 CAudioBuffer::pop() {
+ assert(!empty());
+ return *_frontP++;
+}
+
+void CAudioBuffer::compact() {
+ if (_frontP != &_data[0]) {
+ Common::copy(_frontP, _backP, &_data[0]);
+ _backP -= _frontP - &_data[0];
+ _frontP = &_data[0];
+ }
+}
+
+int CAudioBuffer::freeSize() {
+ compact();
+ return &_data[0] + _data.size() - _backP;
+}
+
+void CAudioBuffer::enterCriticalSection() {
+ _mutex.lock();
+}
+
+void CAudioBuffer::leaveCriticalSection() {
+ _mutex.unlock();
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/sound/audio_buffer.h b/engines/titanic/sound/audio_buffer.h
new file mode 100644
index 0000000000..8d27667e93
--- /dev/null
+++ b/engines/titanic/sound/audio_buffer.h
@@ -0,0 +1,100 @@
+/* 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.
+ *
+ */
+
+#ifndef TITANIC_AUDIO_BUFFER_H
+#define TITANIC_AUDIO_BUFFER_H
+
+#include "common/array.h"
+#include "common/mutex.h"
+
+namespace Titanic {
+
+class CAudioBuffer {
+private:
+ Common::Mutex _mutex;
+ Common::Array<int16> _data;
+ int16 *_frontP, *_backP;
+
+ /**
+ * Reclaims any space at the start of the array resulting from
+ * having read values off the font
+ */
+ void compact();
+public:
+ bool _finished;
+public:
+ CAudioBuffer(int maxSize);
+
+ /**
+ * Resets the audio buffer
+ */
+ void reset();
+
+ /**
+ * Returns true if the buffer is empty
+ */
+ bool empty() const { return _data.empty(); }
+
+ /**
+ * Returns the number of 16-bit entries in the buffer
+ */
+ int size() const { return _backP - _frontP; }
+
+ /**
+ * Returns true if the buffer is full
+ */
+ bool full() const { return (_backP - _frontP) == (int)_data.size(); }
+
+ /**
+ * Returns the number of entries free in the buffer
+ */
+ int freeSize();
+
+ /**
+ * Adds a value to the buffer
+ */
+ void push(int16 value);
+
+ /**
+ * Adds a value to the buffer
+ */
+ void push(int16 *values, int count);
+
+ /**
+ * Removes a value from the buffer
+ */
+ int16 pop();
+
+ /**
+ * Enters a critical section
+ */
+ void enterCriticalSection();
+
+ /**
+ * Leave a critical section
+ */
+ void leaveCriticalSection();
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_AUDIO_BUFFER_H */
diff --git a/engines/titanic/sound/music_player.cpp b/engines/titanic/sound/music_player.cpp
index a1aaf8ff8b..fe75382dc3 100644
--- a/engines/titanic/sound/music_player.cpp
+++ b/engines/titanic/sound/music_player.cpp
@@ -39,8 +39,8 @@ void CMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_isActive, indent);
file->writeQuotedLine(_stopTarget, indent);
- file->writeNumberLine(_stopWaves, indent);
- file->writeNumberLine(_musicId, indent);
+ file->writeNumberLine(_musicActive, indent);
+ file->writeNumberLine(_volume, indent);
CGameObject::save(file, indent);
}
@@ -49,14 +49,14 @@ void CMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_isActive = file->readNumber();
_stopTarget = file->readString();
- _stopWaves = file->readNumber();
- _musicId = file->readNumber();
+ _musicActive = file->readNumber();
+ _volume = file->readNumber();
CGameObject::load(file);
}
bool CMusicPlayer::StartMusicMsg(CStartMusicMsg *msg) {
- if (msg->_musicPlayer == this) {
+ if (msg->_musicPlayer != this) {
if (_isActive) {
CStopMusicMsg stopMusicMsg;
stopMusicMsg.execute(this);
@@ -73,8 +73,9 @@ bool CMusicPlayer::StartMusicMsg(CStartMusicMsg *msg) {
CSetMusicControlsMsg controlsMsg;
controlsMsg.execute(this, nullptr, MSGFLAG_SCAN);
- getMusicRoom()->startMusic(_musicId);
+ getMusicRoom()->setupMusic(_volume);
_isActive = true;
+ unlockMouse();
}
return true;
@@ -97,7 +98,7 @@ bool CMusicPlayer::StopMusicMsg(CStopMusicMsg *msg) {
}
bool CMusicPlayer::FrameMsg(CFrameMsg *msg) {
- if (_isActive && !CMusicRoom::_musicHandler->poll()) {
+ if (_isActive && !CMusicRoom::_musicHandler->update()) {
getMusicRoom()->stopMusic();
_isActive = false;
@@ -109,6 +110,7 @@ bool CMusicPlayer::FrameMsg(CFrameMsg *msg) {
}
bool CMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
+ // Set up a timer that will create a music handler
addTimer(100);
return true;
}
@@ -120,43 +122,43 @@ bool CMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
bool CMusicPlayer::CreateMusicPlayerMsg(CCreateMusicPlayerMsg *msg) {
if (CMusicRoom::_musicHandler) {
- CMusicRoom::_musicHandler->setStopWaves(_stopWaves);
+ CMusicRoom::_musicHandler->setActive(_musicActive);
return true;
}
CMusicRoomHandler *musicHandler = getMusicRoom()->createMusicHandler();
- CMusicWave *wave;
+ CMusicRoomInstrument *ins;
if (musicHandler) {
- wave = musicHandler->createMusicWave(0, 3);
- wave->load(0, "z#490.wav", 60);
- wave->load(1, "z#488.wav", 62);
- wave->load(2, "z#489.wav", 63);
-
- wave = musicHandler->createMusicWave(1, 5);
- wave->load(0, "z#493.wav", 22);
- wave->load(1, "z#495.wav", 29);
- wave->load(2, "z#492.wav", 34);
- wave->load(3, "z#494.wav", 41);
- wave->load(4, "z#491.wav", 46);
-
- wave = musicHandler->createMusicWave(2, 5);
- wave->load(0, "z#499.wav", 26);
- wave->load(1, "z#497.wav", 34);
- wave->load(2, "z#498.wav", 38);
- wave->load(3, "z#496.wav", 46);
- wave->load(4, "z#500.wav", 60);
-
- wave = musicHandler->createMusicWave(3, 7);
- wave->load(0, "z#504.wav", 22);
- wave->load(1, "z#507.wav", 29);
- wave->load(2, "z#503.wav", 34);
- wave->load(3, "z#506.wav", 41);
- wave->load(4, "z#502.wav", 46);
- wave->load(5, "z#505.wav", 53);
- wave->load(6, "z#501.wav", 58);
-
- CMusicRoom::_musicHandler->setStopWaves(_stopWaves);
+ ins = musicHandler->createInstrument(BELLS, 3);
+ ins->load(0, "z#490.wav", 60);
+ ins->load(1, "z#488.wav", 62);
+ ins->load(2, "z#489.wav", 63);
+
+ ins = musicHandler->createInstrument(SNAKE, 5);
+ ins->load(0, "z#493.wav", 22);
+ ins->load(1, "z#495.wav", 29);
+ ins->load(2, "z#492.wav", 34);
+ ins->load(3, "z#494.wav", 41);
+ ins->load(4, "z#491.wav", 46);
+
+ ins = musicHandler->createInstrument(PIANO, 5);
+ ins->load(0, "z#499.wav", 26);
+ ins->load(1, "z#497.wav", 34);
+ ins->load(2, "z#498.wav", 38);
+ ins->load(3, "z#496.wav", 46);
+ ins->load(4, "z#500.wav", 60);
+
+ ins = musicHandler->createInstrument(BASS, 7);
+ ins->load(0, "z#504.wav", 22);
+ ins->load(1, "z#507.wav", 29);
+ ins->load(2, "z#503.wav", 34);
+ ins->load(3, "z#506.wav", 41);
+ ins->load(4, "z#502.wav", 46);
+ ins->load(5, "z#505.wav", 53);
+ ins->load(6, "z#501.wav", 58);
+
+ CMusicRoom::_musicHandler->setActive(_musicActive);
}
return true;
@@ -170,6 +172,7 @@ bool CMusicPlayer::TimerMsg(CTimerMsg *msg) {
bool CMusicPlayer::LoadSuccessMsg(CLoadSuccessMsg *msg) {
if (_isActive) {
+ // Music is meant to be playing, so restart it
CStopMusicMsg stopMsg;
stopMsg.execute(this);
CStartMusicMsg startMsg;
diff --git a/engines/titanic/sound/music_player.h b/engines/titanic/sound/music_player.h
index 7b82d4da00..4d322e01dc 100644
--- a/engines/titanic/sound/music_player.h
+++ b/engines/titanic/sound/music_player.h
@@ -41,12 +41,12 @@ class CMusicPlayer : public CGameObject {
protected:
bool _isActive;
CString _stopTarget;
- bool _stopWaves;
- int _musicId;
+ bool _musicActive;
+ int _volume;
public:
CLASSDEF;
CMusicPlayer() : CGameObject(),
- _isActive(false), _stopWaves(false), _musicId(100) {}
+ _isActive(false), _musicActive(false), _volume(100) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/sound/music_room.cpp b/engines/titanic/sound/music_room.cpp
index 9586f55c58..a3752c5ddb 100644
--- a/engines/titanic/sound/music_room.cpp
+++ b/engines/titanic/sound/music_room.cpp
@@ -32,7 +32,6 @@ CMusicRoomHandler *CMusicRoom::_musicHandler;
CMusicRoom::CMusicRoom(CGameManager *gameManager) :
_gameManager(gameManager) {
_sound = &_gameManager->_sound;
- _controls.resize(4);
}
CMusicRoom::~CMusicRoom() {
@@ -52,8 +51,9 @@ void CMusicRoom::destroyMusicHandler() {
_musicHandler = nullptr;
}
-void CMusicRoom::startMusic(int volume) {
+void CMusicRoom::setupMusic(int volume) {
if (_musicHandler) {
+ // Set up the control values that form the correct settings
_musicHandler->setSpeedControl2(BELLS, 0);
_musicHandler->setSpeedControl2(SNAKE, 1);
_musicHandler->setSpeedControl2(PIANO, -1);
@@ -62,29 +62,31 @@ void CMusicRoom::startMusic(int volume) {
_musicHandler->setPitchControl2(BELLS, 1);
_musicHandler->setPitchControl2(SNAKE, 2);
_musicHandler->setPitchControl2(PIANO, 0);
- _musicHandler->setPitchControl2(BELLS, 1);
-
- _musicHandler->setInversionControl2(BELLS, 1);
- _musicHandler->setInversionControl2(SNAKE, 0);
- _musicHandler->setInversionControl2(PIANO, 1);
- _musicHandler->setInversionControl2(BASS, 0);
-
- _musicHandler->setDirectionControl2(BELLS, 0);
- _musicHandler->setDirectionControl2(SNAKE, 0);
- _musicHandler->setDirectionControl2(PIANO, 1);
- _musicHandler->setDirectionControl2(BASS, 1);
-
- for (MusicControlArea idx = BELLS; idx <= BASS;
- idx = (MusicControlArea)((int)idx + 1)) {
- Controls &controls = _controls[idx];
- _musicHandler->setSpeedControl(idx, controls._speedControl);
- _musicHandler->setPitchControl(idx, controls._pitchControl);
- _musicHandler->setDirectionControl(idx, controls._directionControl);
- _musicHandler->setInversionControl(idx, controls._inversionControl);
- _musicHandler->setMuteControl(idx, controls._muteControl);
+ _musicHandler->setPitchControl2(BASS, 1);
+
+ _musicHandler->setInversionControl2(BELLS, true);
+ _musicHandler->setInversionControl2(SNAKE, false);
+ _musicHandler->setInversionControl2(PIANO, true);
+ _musicHandler->setInversionControl2(BASS, false);
+
+ _musicHandler->setDirectionControl2(BELLS, false);
+ _musicHandler->setDirectionControl2(SNAKE, false);
+ _musicHandler->setDirectionControl2(PIANO, true);
+ _musicHandler->setDirectionControl2(BASS, true);
+
+ // Set up the current control values
+ for (MusicInstrument idx = BELLS; idx <= BASS;
+ idx = (MusicInstrument)((int)idx + 1)) {
+ MusicRoomInstrument &instr = _instruments[idx];
+ _musicHandler->setSpeedControl(idx, instr._speedControl);
+ _musicHandler->setPitchControl(idx, instr._pitchControl);
+ _musicHandler->setDirectionControl(idx, instr._directionControl);
+ _musicHandler->setInversionControl(idx, instr._inversionControl);
+ _musicHandler->setMuteControl(idx, instr._muteControl);
}
- _musicHandler->createWaveFile(volume);
+ // Set up the music handler
+ _musicHandler->setup(volume);
}
}
diff --git a/engines/titanic/sound/music_room.h b/engines/titanic/sound/music_room.h
index 4b584a0dd4..f39957bdd1 100644
--- a/engines/titanic/sound/music_room.h
+++ b/engines/titanic/sound/music_room.h
@@ -32,18 +32,8 @@ class CGameManager;
class CSound;
class CMusicRoom {
- struct Controls {
- int _speedControl;
- int _pitchControl;
- int _directionControl;
- int _inversionControl;
- int _muteControl;
-
- Controls() : _speedControl(0), _pitchControl(0), _directionControl(0),
- _inversionControl(0), _muteControl(0) {}
- };
private:
- Common::Array<Controls> _controls;
+ MusicRoomInstrument _instruments[4];
public:
static CMusicRoomHandler *_musicHandler;
public:
@@ -63,16 +53,45 @@ public:
*/
void destroyMusicHandler();
- void setSpeedControl(MusicControlArea index, int val) { _controls[index]._speedControl = val; }
- void setPitchControl(MusicControlArea index, int val) { _controls[index]._pitchControl = val; }
- void setDirectionControl(MusicControlArea index, int val) { _controls[index]._directionControl = val; }
- void setInversionControl(MusicControlArea index, int val) { _controls[index]._inversionControl = val; }
- void setMuteControl(MusicControlArea index, int val) { _controls[index]._muteControl = val; }
+ /**
+ * Sets the speed control for a given instrument
+ */
+ void setSpeedControl(MusicInstrument instrument, int val) {
+ _instruments[instrument]._speedControl = val;
+ }
+
+ /**
+ * Sets the pitch control for a given instrument
+ */
+ void setPitchControl(MusicInstrument instrument, int val) {
+ _instruments[instrument]._pitchControl = val;
+ }
+
+ /**
+ * Sets the direction control for a given instrument
+ */
+ void setDirectionControl(MusicInstrument instrument, bool val) {
+ _instruments[instrument]._directionControl = val;
+ }
+
+ /**
+ * Sets the inversion control for a given instrument
+ */
+ void setInversionControl(MusicInstrument instrument, bool val) {
+ _instruments[instrument]._inversionControl = val;
+ }
+
+ /**
+ * Sets the mute control for a given instrument
+ */
+ void setMuteControl(MusicInstrument instrument, bool val) {
+ _instruments[instrument]._muteControl = val;
+ }
/**
- * Start playing a given music number
+ * Sets up the music controls
*/
- void startMusic(int volume = 100);
+ void setupMusic(int volume);
/**
* Stop playing music
diff --git a/engines/titanic/sound/music_room_handler.cpp b/engines/titanic/sound/music_room_handler.cpp
index a9f4116691..76d7043d0c 100644
--- a/engines/titanic/sound/music_room_handler.cpp
+++ b/engines/titanic/sound/music_room_handler.cpp
@@ -23,52 +23,80 @@
#include "titanic/sound/music_room_handler.h"
#include "titanic/sound/sound_manager.h"
#include "titanic/core/project_item.h"
+#include "titanic/titanic.h"
namespace Titanic {
CMusicRoomHandler::CMusicRoomHandler(CProjectItem *project, CSoundManager *soundManager) :
- _project(project), _soundManager(soundManager), _stopWaves(false),
- _soundHandle(-1), _waveFile(nullptr), _soundVolume(100),
- _field108(0) {
- Common::fill(&_musicWaves[0], &_musicWaves[4], (CMusicWave *)nullptr);
+ _project(project), _soundManager(soundManager), _active(false),
+ _soundHandle(-1), _waveFile(nullptr), _volume(100) {
+ _instrumentsActive = 0;
+ _isPlaying = false;
+ _startTicks = _soundStartTicks = 0;
+ Common::fill(&_instruments[0], &_instruments[4], (CMusicRoomInstrument *)nullptr);
+ for (int idx = 0; idx < 4; ++idx)
+ _songs[idx] = new CMusicSong(idx);
+ Common::fill(&_startPos[0], &_startPos[4], 0);
+ Common::fill(&_animTime[0], &_animTime[4], 0.0);
+ Common::fill(&_position[0], &_position[4], 0);
+
+ _audioBuffer = new CAudioBuffer(88200);
}
CMusicRoomHandler::~CMusicRoomHandler() {
stop();
for (int idx = 0; idx < 4; ++idx)
- delete _musicWaves[idx];
+ delete _songs[idx];
+
+ delete _audioBuffer;
}
-CMusicWave *CMusicRoomHandler::createMusicWave(int waveIndex, int count) {
- switch (waveIndex) {
- case 0:
- _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 2);
+CMusicRoomInstrument *CMusicRoomHandler::createInstrument(MusicInstrument instrument, int count) {
+ switch (instrument) {
+ case BELLS:
+ _instruments[BELLS] = new CMusicRoomInstrument(_project, _soundManager, MV_BELLS);
break;
- case 1:
- _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 3);
+ case SNAKE:
+ _instruments[SNAKE] = new CMusicRoomInstrument(_project, _soundManager, MV_SNAKE);
break;
- case 2:
- _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 0);
+ case PIANO:
+ _instruments[PIANO] = new CMusicRoomInstrument(_project, _soundManager, MV_PIANO);
break;
- case 3:
- _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 1);
+ case BASS:
+ _instruments[BASS] = new CMusicRoomInstrument(_project, _soundManager, MV_BASS);
break;
default:
return nullptr;
}
- _musicWaves[waveIndex]->setSize(count);
- return _musicWaves[waveIndex];
+ _instruments[instrument]->setFilesCount(count);
+ return _instruments[instrument];
}
-void CMusicRoomHandler::createWaveFile(int musicVolume) {
- _soundVolume = musicVolume;
-// _waveFile = _soundManager->loadMusic()
-}
+void CMusicRoomHandler::setup(int volume) {
+ _volume = volume;
+ _audioBuffer->reset();
+
+ for (int idx = 0; idx < 4; ++idx) {
+ MusicRoomInstrument &ins1 = _array1[idx];
+ MusicRoomInstrument &ins2 = _array2[idx];
+
+ if (ins1._directionControl == ins2._directionControl) {
+ _startPos[idx] = 0;
+ } else {
+ _startPos[idx] = _songs[idx]->size() - 1;
+ }
+
+ _position[idx] = _startPos[idx];
+ _animTime[idx] = 0.0;
+ }
-bool CMusicRoomHandler::poll() {
- // TODO
- return false;
+ _instrumentsActive = 4;
+ _isPlaying = true;
+ update();
+
+ _waveFile = _soundManager->loadMusic(_audioBuffer, DisposeAfterUse::NO);
+ update();
}
void CMusicRoomHandler::stop() {
@@ -80,64 +108,237 @@ void CMusicRoomHandler::stop() {
}
for (int idx = 0; idx < 4; ++idx) {
- if (_stopWaves && _musicWaves[idx])
- _musicWaves[idx]->stop();
+ _instruments[idx]->clear();
+ if (_active && _instruments[idx])
+ _instruments[idx]->stop();
}
+
+ _instrumentsActive = 0;
+ _isPlaying = false;
+ _startTicks = _soundStartTicks = 0;
}
-bool CMusicRoomHandler::checkSound(int index) const {
- // TODO
- return false;
+bool CMusicRoomHandler::checkInstrument(MusicInstrument instrument) const {
+ return (_array1[instrument]._speedControl + _array2[instrument]._speedControl) == 0
+ && (_array1[instrument]._pitchControl + _array2[instrument]._pitchControl) == 0
+ && _array1[instrument]._directionControl == _array2[instrument]._directionControl
+ && _array1[instrument]._inversionControl == _array2[instrument]._inversionControl
+ && _array1[instrument]._muteControl == _array2[instrument]._muteControl;
}
-void CMusicRoomHandler::setSpeedControl2(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array2[area]._speedControl = value;
+void CMusicRoomHandler::setSpeedControl2(MusicInstrument instrument, int value) {
+ if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
+ _array2[instrument]._speedControl = value;
}
-void CMusicRoomHandler::setPitchControl2(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array2[area]._pitchControl = value * 3;
+void CMusicRoomHandler::setPitchControl2(MusicInstrument instrument, int value) {
+ if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
+ _array2[instrument]._pitchControl = value * 3;
}
-void CMusicRoomHandler::setInversionControl2(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array2[area]._inversionControl = value;
+void CMusicRoomHandler::setInversionControl2(MusicInstrument instrument, bool value) {
+ if (instrument >= BELLS && instrument <= BASS)
+ _array2[instrument]._inversionControl = value;
}
-void CMusicRoomHandler::setDirectionControl2(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array2[area]._directionControl = value;
+void CMusicRoomHandler::setDirectionControl2(MusicInstrument instrument, bool value) {
+ if (instrument >= BELLS && instrument <= BASS)
+ _array2[instrument]._directionControl = value;
}
-void CMusicRoomHandler::setPitchControl(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array1[area]._pitchControl = value;
+void CMusicRoomHandler::setPitchControl(MusicInstrument instrument, int value) {
+ if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
+ _array1[instrument]._pitchControl = value * 3;
}
-void CMusicRoomHandler::setSpeedControl(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array1[area]._speedControl = value;
+void CMusicRoomHandler::setSpeedControl(MusicInstrument instrument, int value) {
+ if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
+ _array1[instrument]._speedControl = value;
}
-void CMusicRoomHandler::setDirectionControl(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array1[area]._directionControl = value;
+void CMusicRoomHandler::setDirectionControl(MusicInstrument instrument, bool value) {
+ if (instrument >= BELLS && instrument <= BASS)
+ _array1[instrument]._directionControl = value;
}
-void CMusicRoomHandler::setInversionControl(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array1[area]._inversionControl = value;
+void CMusicRoomHandler::setInversionControl(MusicInstrument instrument, bool value) {
+ if (instrument >= BELLS && instrument <= BASS)
+ _array1[instrument]._inversionControl = value;
}
-void CMusicRoomHandler::setMuteControl(MusicControlArea area, int value) {
- if (area >= 0 && area <= 3 && value >= -2 && value <= 2)
- _array1[area]._muteControl = value;
+void CMusicRoomHandler::setMuteControl(MusicInstrument instrument, bool value) {
+ if (instrument >= BELLS && instrument <= BASS)
+ _array1[instrument]._muteControl = value;
}
-bool CMusicRoomHandler::isBusy() {
- // TODO: stuff
- return _field108 > 0;
+void CMusicRoomHandler::start() {
+ if (_active) {
+ for (int idx = 0; idx < 4; ++idx)
+ _instruments[idx]->start();
+ }
+}
+
+bool CMusicRoomHandler::update() {
+ uint currentTicks = g_vm->_events->getTicksCount();
+
+ if (!_startTicks) {
+ start();
+ _startTicks = currentTicks;
+ } else if (!_soundStartTicks && currentTicks >= (_startTicks + 3000)) {
+ if (_waveFile) {
+ CProximity prox;
+ prox._channelVolume = _volume;
+ _soundHandle = _soundManager->playSound(*_waveFile, prox);
+ }
+
+ _soundStartTicks = currentTicks;
+ }
+
+ updateAudio();
+ updateInstruments();
+
+ return _instrumentsActive > 0;
+}
+
+void CMusicRoomHandler::updateAudio() {
+ _audioBuffer->enterCriticalSection();
+
+ int size = _audioBuffer->freeSize();
+ int count;
+ int16 *ptr;
+
+ if (size > 0) {
+ // Create a temporary buffer for merging the instruments into
+ int16 *audioData = new int16[size];
+ Common::fill(audioData, audioData + size, 0);
+
+ for (MusicInstrument instrument = BELLS; instrument <= BASS;
+ instrument = (MusicInstrument)((int)instrument + 1)) {
+ CMusicRoomInstrument *musicWave = _instruments[instrument];
+
+ // Iterate through each of the four instruments and do an additive
+ // read that will merge their data onto the output buffer
+ for (count = size, ptr = audioData; count > 0; ) {
+ int amount = musicWave->read(ptr, count);
+ if (amount > 0) {
+ count -= amount;
+ ptr += amount / sizeof(uint16);
+ } else if (!pollInstrument(instrument)) {
+ --_instrumentsActive;
+ break;
+ }
+ }
+ }
+
+ _audioBuffer->push(audioData, size);
+ delete[] audioData;
+ }
+
+ _audioBuffer->leaveCriticalSection();
+}
+
+void CMusicRoomHandler::updateInstruments() {
+ if (_active && _soundStartTicks) {
+ for (MusicInstrument instrument = BELLS; instrument <= BASS;
+ instrument = (MusicInstrument)((int)instrument + 1)) {
+ MusicRoomInstrument &ins1 = _array1[instrument];
+ MusicRoomInstrument &ins2 = _array2[instrument];
+ CMusicRoomInstrument *ins = _instruments[instrument];
+
+ // Is this about checking playback position?
+ if (_position[instrument] < 0 || ins1._muteControl || _position[instrument] >= _songs[instrument]->size()) {
+ _position[instrument] = -1;
+ continue;
+ }
+
+ uint ticks = g_vm->_events->getTicksCount() - _soundStartTicks;
+ double time = (double)ticks * 0.001 - 0.6;
+ double threshold = _animTime[instrument] - ins->_animTime;
+
+ if (time >= threshold) {
+ _animTime[instrument] += getAnimDuration(instrument, _position[instrument]);
+
+ const CValuePair &vp = (*_songs[instrument])[_position[instrument]];
+ if (vp._data != 0x7FFFFFFF) {
+ int amount = getPitch(instrument, _position[instrument]);
+ _instruments[instrument]->update(amount);
+ }
+
+ if (ins1._directionControl == ins2._directionControl) {
+ _position[instrument]++;
+ } else {
+ _position[instrument]--;
+ }
+ }
+ }
+ }
+}
+
+bool CMusicRoomHandler::pollInstrument(MusicInstrument instrument) {
+ int &arrIndex = _startPos[instrument];
+ if (arrIndex < 0) {
+ _instruments[instrument]->clear();
+ return false;
+ }
+
+ const CMusicSong &song = *_songs[instrument];
+ if (arrIndex >= song.size()) {
+ arrIndex = -1;
+ _instruments[instrument]->clear();
+ return false;
+ }
+
+ const CValuePair &vp = song[arrIndex];
+ uint duration = static_cast<int>(getAnimDuration(instrument, arrIndex) * 44100.0) & ~1;
+
+ if (vp._data == 0x7FFFFFFF || _array1[instrument]._muteControl)
+ _instruments[instrument]->reset(duration);
+ else
+ _instruments[instrument]->chooseWaveFile(getPitch(instrument, arrIndex), duration);
+
+ if (_array1[instrument]._directionControl == _array2[instrument]._directionControl) {
+ ++arrIndex;
+ } else {
+ --arrIndex;
+ }
+
+ return true;
+}
+
+double CMusicRoomHandler::getAnimDuration(MusicInstrument instrument, int arrIndex) {
+ const CValuePair &vp = (*_songs[instrument])[arrIndex];
+
+ switch (_array1[instrument]._speedControl + _array2[instrument]._speedControl + 3) {
+ case 0:
+ return (double)vp._length * 1.5 * 0.0625 * 0.46875;
+ case 1:
+ return (double)vp._length * 1.33 * 0.0625 * 0.46875;
+ case 2:
+ return (double)vp._length * 1.25 * 0.0625 * 0.46875;
+ case 4:
+ return (double)vp._length * 0.75 * 0.0625 * 0.46875;
+ case 5:
+ return (double)vp._length * 0.67 * 0.0625 * 0.46875;
+ case 6:
+ return (double)vp._length * 0.5 * 0.0625 * 0.46875;
+ default:
+ return (double)vp._length * 1.0 * 0.0625 * 0.46875;
+ }
+}
+
+int CMusicRoomHandler::getPitch(MusicInstrument instrument, int arrIndex) {
+ const CMusicSong &song = *_songs[instrument];
+ const CValuePair &vp = song[arrIndex];
+ int val = vp._data;
+ const MusicRoomInstrument &ins1 = _array1[instrument];
+ const MusicRoomInstrument &ins2 = _array2[instrument];
+
+ if (ins1._inversionControl != ins2._inversionControl) {
+ val = song._minVal * 2 + song._range - val;
+ }
+
+ val += ins1._pitchControl + ins2._pitchControl;
+ return val;
}
} // End of namespace Titanic
diff --git a/engines/titanic/sound/music_room_handler.h b/engines/titanic/sound/music_room_handler.h
index a15ef2d1bc..ec117e3098 100644
--- a/engines/titanic/sound/music_room_handler.h
+++ b/engines/titanic/sound/music_room_handler.h
@@ -23,7 +23,9 @@
#ifndef TITANIC_MUSIC_ROOM_HANDLER_H
#define TITANIC_MUSIC_ROOM_HANDLER_H
-#include "titanic/sound/music_wave.h"
+#include "titanic/sound/audio_buffer.h"
+#include "titanic/sound/music_room_instrument.h"
+#include "titanic/sound/music_song.h"
#include "titanic/sound/wave_file.h"
namespace Titanic {
@@ -31,94 +33,156 @@ namespace Titanic {
class CProjectItem;
class CSoundManager;
-enum MusicControlArea { BELLS = 0, SNAKE = 1, PIANO = 2, BASS = 3 };
+enum MusicInstrument { BELLS = 0, SNAKE = 1, PIANO = 2, BASS = 3 };
+
+struct MusicRoomInstrument {
+ int _pitchControl;
+ int _speedControl;
+ bool _directionControl;
+ bool _inversionControl;
+ bool _muteControl;
+ MusicRoomInstrument() : _pitchControl(0), _speedControl(0), _directionControl(false),
+ _inversionControl(false), _muteControl(false) {}
+};
class CMusicRoomHandler {
- struct Controls {
- int _pitchControl;
- int _speedControl;
- int _directionControl;
- int _inversionControl;
- int _muteControl;
- Controls() : _pitchControl(0), _speedControl(0), _directionControl(0),
- _inversionControl(0), _muteControl(0) {}
- };
- struct Array5Entry {
- int _v1;
- int _v2;
- Array5Entry() : _v1(0), _v2(0) {}
- };
private:
CProjectItem *_project;
CSoundManager *_soundManager;
- CMusicWave *_musicWaves[4];
- Controls _array1[4];
- Controls _array2[4];
- Array5Entry _array5[4];
- bool _stopWaves;
+ CMusicRoomInstrument *_instruments[4];
+ MusicRoomInstrument _array1[4];
+ MusicRoomInstrument _array2[4];
+ CMusicSong *_songs[4];
+ int _startPos[4];
+ int _position[4];
+ double _animTime[4];
+
+ bool _active;
CWaveFile *_waveFile;
int _soundHandle;
- int _soundVolume;
- int _field108;
+ int _instrumentsActive;
+ CAudioBuffer *_audioBuffer;
+ bool _isPlaying;
+ uint _soundStartTicks;
+ uint _startTicks;
+ int _volume;
+private:
+ /**
+ * Starts music room instruments animation
+ */
+ void start();
+
+ /**
+ * Handles updating the raw audio being played for all the instruments
+ */
+ void updateAudio();
+
+ /**
+ * Handles updating the instruments themselves, and keeping them animating
+ */
+ void updateInstruments();
+
+ /**
+ * Polls a specified instrument for any updates to see if it's still active.
+ * @returns Returns true if a given instrument is still active..
+ * that is, that there is still more data that can be read from it to play
+ */
+ bool pollInstrument(MusicInstrument instrument);
+
+ /**
+ * Gets the duration for a given fragment of an instrument to play
+ * out, so that animations of the instruments can be synchronized
+ * to the actual music
+ */
+ double getAnimDuration(MusicInstrument instrument, int arrIndex);
+
+ /**
+ * Figures out a pitch value (of some sort) for use in determining
+ * which wave file the music instruments will use.
+ */
+ int getPitch(MusicInstrument instrument, int arrIndex);
public:
CMusicRoomHandler(CProjectItem *project, CSoundManager *soundManager);
~CMusicRoomHandler();
/**
- * Creates a new music wave class instance, and assigns it to a slot
- * in the music handler
- * @param waveIndex Slot to save new instance in
- * @param count Number of files the new instance will contain
+ * Creates a new music room instrument class to handle the operation of one
+ * of the instruments in the music room.
+ * @param instrument Which instrument to create for
+ * @param count Number of Wave files the new instance will contain
*/
- CMusicWave *createMusicWave(int waveIndex, int count);
-
- void createWaveFile(int musicVolume);
+ CMusicRoomInstrument *createInstrument(MusicInstrument instrument, int count);
/**
- * Handles regular polling the music handler
+ * Main setup for the music room handler
*/
- bool poll();
-
- bool isBusy();
+ void setup(int volume);
/**
- * Flags whether the loaded music waves will be stopped when the
- * music handler is stopped
+ * Flags whether the music handler is active
*/
- void setStopWaves(bool flag) { _stopWaves = flag; }
+ void setActive(bool flag) { _active = flag; }
/**
* Stop playing the music
*/
void stop();
- bool checkSound(int index) const;
+ /**
+ * Checks the specified instrument to see if it's settings are "correct"
+ */
+ bool checkInstrument(MusicInstrument instrument) const;
+
+ /**
+ * Sets the speed control value
+ */
+ void setSpeedControl2(MusicInstrument instrument, int value);
+
+ /**
+ * Sets the pitch control value
+ */
+ void setPitchControl2(MusicInstrument instrument, int value);
+
+ /**
+ * Sets the inversion control value
+ */
+ void setInversionControl2(MusicInstrument instrument, bool value);
+
+ /**
+ * Sets the direction control value
+ */
+ void setDirectionControl2(MusicInstrument instrument, bool value);
/**
- * Set a setting
+ * Sets the pitch control value
*/
- void setSpeedControl2(MusicControlArea area, int value);
+ void setPitchControl(MusicInstrument instrument, int value);
/**
- * Set a setting
+ * Sets the speed control value
*/
- void setPitchControl2(MusicControlArea area, int value);
+ void setSpeedControl(MusicInstrument instrument, int value);
/**
- * Set a setting
+ * Sets the direction control value
*/
- void setInversionControl2(MusicControlArea area, int value);
+ void setDirectionControl(MusicInstrument instrument, bool value);
/**
- * Set a setting
+ * Sets the inversion control value
*/
- void setDirectionControl2(MusicControlArea area, int value);
+ void setInversionControl(MusicInstrument instrument, bool value);
- void setPitchControl(MusicControlArea area, int value);
- void setSpeedControl(MusicControlArea area, int value);
- void setDirectionControl(MusicControlArea area, int value);
- void setInversionControl(MusicControlArea area, int value);
- void setMuteControl(MusicControlArea area, int value);
+ /**
+ * Sets the mute control value
+ */
+ void setMuteControl(MusicInstrument instrument, bool value);
+
+ /**
+ * Handles regular updates
+ * @returns True if the music is still playing
+ */
+ bool update();
};
} // End of namespace Titanic
diff --git a/engines/titanic/sound/music_room_instrument.cpp b/engines/titanic/sound/music_room_instrument.cpp
new file mode 100644
index 0000000000..b92329850b
--- /dev/null
+++ b/engines/titanic/sound/music_room_instrument.cpp
@@ -0,0 +1,353 @@
+/* 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.
+ *
+ */
+
+#include "titanic/sound/music_room_instrument.h"
+#include "titanic/sound/sound_manager.h"
+#include "titanic/core/project_item.h"
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+bool CMusicRoomInstrument::_pianoToggle;
+int CMusicRoomInstrument::_pianoCtr;
+int CMusicRoomInstrument::_bassCtr;
+byte *CMusicRoomInstrument::_buffer;
+double *CMusicRoomInstrument::_array;
+int CMusicRoomInstrument::_arrayIndex;
+
+void CMusicRoomInstrument::init() {
+ _pianoToggle = false;
+ _pianoCtr = 0;
+ _bassCtr = 0;
+ _buffer = nullptr;
+ _array = nullptr;
+ _arrayIndex = 0;
+}
+
+void CMusicRoomInstrument::deinit() {
+ delete[] _buffer;
+ delete[] _array;
+ _buffer = nullptr;
+}
+
+CMusicRoomInstrument::CMusicRoomInstrument(CProjectItem *project, CSoundManager *soundManager, MusicWaveInstrument instrument) :
+ _project(project), _soundManager(soundManager), _instrument(instrument) {
+ Common::fill(&_gameObjects[0], &_gameObjects[4], (CGameObject *)nullptr);
+ _animTime = 0.0;
+ _waveIndex = -1;
+ _readPos = 0;
+ _readIncrement = 0;
+ _size = 0;
+ _count = 0;
+ _field4C = 0;
+
+ switch (instrument) {
+ case MV_PIANO:
+ _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Piano Man"));
+ _gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Piano Mouth"));
+ _gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Piano Left Arm"));
+ _gameObjects[3] = static_cast<CGameObject *>(_project->findByName("Piano Right Arm"));
+ _animTime = 0.45;
+ break;
+
+ case MV_BASS:
+ _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Bass Player"));
+ break;
+
+ case MV_BELLS:
+ _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Tubular Bells"));
+ _animTime = 0.4;
+ break;
+
+ case MV_SNAKE:
+ _gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Snake_Hammer"));
+ _gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Snake_Glass"));
+ _gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Snake_Head"));
+ _animTime = 0.17;
+ break;
+ }
+}
+
+void CMusicRoomInstrument::setFilesCount(uint count) {
+ assert(_items.empty());
+ _items.resize(count);
+}
+
+void CMusicRoomInstrument::load(int index, const CString &filename, int v3) {
+ assert(!_items[index]._waveFile);
+ _items[index]._waveFile = createWaveFile(filename);
+ _items[index]._value = v3;
+}
+
+CWaveFile *CMusicRoomInstrument::createWaveFile(const CString &name) {
+ if (name.empty())
+ return nullptr;
+ return _soundManager->loadSound(name);
+}
+
+void CMusicRoomInstrument::start() {
+ if (_gameObjects[0]) {
+ switch (_instrument) {
+ case MV_PIANO:
+ _gameObjects[0]->playMovie(0, 29, MOVIE_STOP_PREVIOUS);
+ _gameObjects[2]->loadFrame(14);
+ _gameObjects[3]->loadFrame(22);
+ break;
+
+ case MV_BELLS:
+ _gameObjects[0]->loadFrame(0);
+ _gameObjects[0]->movieSetAudioTiming(true);
+ break;
+
+ case MV_SNAKE:
+ _field4C = 22;
+ _gameObjects[1]->playMovie(0, 22, 0);
+ _gameObjects[2]->playMovie(0, 35, MOVIE_STOP_PREVIOUS);
+ _gameObjects[0]->playMovie(0, 1, MOVIE_STOP_PREVIOUS);
+ _gameObjects[0]->playMovie(0, 1, 0);
+ _gameObjects[0]->playMovie(0, 1, 0);
+ _gameObjects[0]->playMovie(0, 1, 0);
+ _gameObjects[0]->playMovie(0, 1, 0);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void CMusicRoomInstrument::stop() {
+ if (_gameObjects[0]) {
+ switch (_instrument) {
+ case MV_PIANO:
+ _gameObjects[1]->setVisible(false);
+ _gameObjects[2]->setVisible(false);
+ _gameObjects[3]->setVisible(false);
+ _gameObjects[0]->playMovie(29, 58, MOVIE_STOP_PREVIOUS);
+ break;
+
+ case MV_BELLS:
+ _gameObjects[0]->stopMovie();
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void CMusicRoomInstrument::update(int val) {
+ if (_gameObjects[0]) {
+ switch (_instrument) {
+ case MV_PIANO:
+ _gameObjects[1]->setVisible(true);
+ _gameObjects[2]->setVisible(true);
+ _gameObjects[3]->setVisible(true);
+ _gameObjects[_pianoToggle ? 3 : 2]->playMovie(MOVIE_STOP_PREVIOUS);
+ _pianoToggle = !_pianoToggle;
+
+ switch (_pianoCtr) {
+ case 0:
+ _gameObjects[1]->playMovie(0, 4, MOVIE_STOP_PREVIOUS);
+ break;
+ case 1:
+ _gameObjects[1]->playMovie(4, 8, MOVIE_STOP_PREVIOUS);
+ break;
+ case 2:
+ _gameObjects[1]->playMovie(8, 12, MOVIE_STOP_PREVIOUS);
+ break;
+ case 3:
+ _gameObjects[1]->playMovie(12, 16, MOVIE_STOP_PREVIOUS);
+ break;
+ default:
+ break;
+ }
+
+ _pianoCtr = (_pianoCtr + 1) % 4;
+ break;
+
+ case MV_BASS:
+ switch (_bassCtr) {
+ case 0:
+ _gameObjects[0]->playMovie(0, 7, MOVIE_STOP_PREVIOUS);
+ break;
+ case 1:
+ _gameObjects[0]->playMovie(7, 14, MOVIE_STOP_PREVIOUS);
+ break;
+ case 2:
+ _gameObjects[0]->playMovie(15, 24, MOVIE_STOP_PREVIOUS);
+ break;
+ case 3:
+ _gameObjects[0]->playMovie(25, 33, MOVIE_STOP_PREVIOUS);
+ break;
+ default:
+ break;
+ }
+
+ // WORKAROUND: Original didn't change the selected bass animation
+ _bassCtr = (_bassCtr + 1) % 4;
+ break;
+
+ case MV_BELLS:
+ switch (val) {
+ case 60:
+ _gameObjects[0]->movieSetAudioTiming(true);
+ _gameObjects[0]->playMovie(0, 512, MOVIE_STOP_PREVIOUS);
+ _animTime = 0.6;
+ break;
+
+ case 62:
+ _gameObjects[0]->playMovie(828, 1023, MOVIE_STOP_PREVIOUS);
+ _animTime = 0.3;
+ break;
+
+ case 63:
+ _gameObjects[0]->playMovie(1024, 1085, MOVIE_STOP_PREVIOUS);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case MV_SNAKE: {
+ _gameObjects[0]->playMovie(0, 7, MOVIE_STOP_PREVIOUS);
+
+ double tempVal = 46.0 - ((double)(val - 14) * 1.43);
+ int frameNum = _field4C;
+ int frameNum1 = (int)((tempVal - frameNum) * 0.25);
+ _gameObjects[1]->playMovie(frameNum1, frameNum1, MOVIE_STOP_PREVIOUS);
+
+ frameNum += frameNum1;
+ _gameObjects[1]->playMovie(frameNum, frameNum, 0);
+
+ frameNum += frameNum1;
+ _gameObjects[1]->playMovie(frameNum, frameNum, 0);
+
+ _gameObjects[2]->playMovie(45, 49, MOVIE_STOP_PREVIOUS);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+
+void CMusicRoomInstrument::clear() {
+ _waveIndex = 0;
+ _readPos = 0;
+ _readIncrement = 0;
+ _size = 0;
+ _count = 0;
+}
+
+void CMusicRoomInstrument::reset(uint total) {
+ _waveIndex = -1;
+ _readPos = 0;
+ _readIncrement = 0;
+ _size = total;
+ _count = 0;
+}
+
+int CMusicRoomInstrument::read(int16 *ptr, uint size) {
+ if (!_size)
+ return 0;
+
+ if (size >= _size)
+ size = _size;
+
+ if (_waveIndex != -1) {
+ // Lock the specified wave file for access
+ const int16 *data = _items[_waveIndex]._waveFile->lock();
+ assert(data);
+ const int16 *src = data;
+
+ // Loop through merging data from the wave file into the dest buffer
+ for (uint idx = 0; idx < (size / sizeof(int16)); ++idx, _readPos += _readIncrement) {
+ uint srcPos = _readPos >> 8;
+ if (srcPos >= _count)
+ break;
+
+ int16 val = READ_LE_UINT16(src + srcPos);
+ *ptr++ += val;
+ }
+
+ // Unlock the wave file
+ _items[_waveIndex]._waveFile->unlock(data);
+ }
+
+ _size -= size;
+ return size;
+}
+
+void CMusicRoomInstrument::chooseWaveFile(int index, int size) {
+ if (!_array)
+ setupArray(-36, 36);
+
+ int minDiff = ABS(_items[0]._value - index);
+ int waveIndex = 0;
+
+ for (uint idx = 1; idx < _items.size(); ++idx) {
+ int diff = ABS(_items[idx]._value - index);
+ if (diff < minDiff) {
+ minDiff = diff;
+ waveIndex = idx;
+ }
+ }
+
+ const CInstrumentWaveFile &wf = _items[waveIndex];
+ int arrIndex = _arrayIndex - wf._value + index;
+ uint waveSize = wf._waveFile->size();
+
+ _waveIndex = waveIndex;
+ _readPos = 0;
+ _readIncrement = (int)(_array[arrIndex] * 256);
+ _size = size;
+ _count = waveSize / 2;
+}
+
+void CMusicRoomInstrument::setupArray(int minVal, int maxVal) {
+ // Delete any prior array and recreate it
+ delete[] _array;
+
+ int arrSize = maxVal - minVal + 1;
+ _array = new double[arrSize];
+ _arrayIndex = ABS(minVal);
+
+ // Setup array contents
+ _array[_arrayIndex] = 1.0;
+
+ double val = 1.0594634;
+ for (int idx = 1; idx <= maxVal; ++idx) {
+ _array[_arrayIndex + idx] = val;
+ val *= 1.0594634;
+ }
+
+ val = 0.94387404038686;
+ for (int idx = -1; idx >= minVal; --idx) {
+ _array[_arrayIndex + idx] = val;
+ val *= 0.94387404038686;
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/sound/music_room_instrument.h b/engines/titanic/sound/music_room_instrument.h
new file mode 100644
index 0000000000..d859fe2a0e
--- /dev/null
+++ b/engines/titanic/sound/music_room_instrument.h
@@ -0,0 +1,142 @@
+/* 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.
+ *
+ */
+
+#ifndef TITANIC_MUSIC_ROOM_INSTRUMENT_H
+#define TITANIC_MUSIC_ROOM_INSTRUMENT_H
+
+#include "common/array.h"
+#include "titanic/support/string.h"
+
+namespace Titanic {
+
+enum MusicWaveInstrument { MV_PIANO = 0, MV_BASS = 1, MV_BELLS = 2, MV_SNAKE = 3 };
+
+class CProjectItem;
+class CSoundManager;
+class CWaveFile;
+class CGameObject;
+
+class CMusicRoomInstrument {
+ struct CInstrumentWaveFile {
+ CWaveFile *_waveFile;
+ int _value;
+ CInstrumentWaveFile() : _waveFile(nullptr), _value(0) {}
+ };
+private:
+ static bool _pianoToggle;
+ static int _pianoCtr;
+ static int _bassCtr;
+ static byte *_buffer;
+ static double *_array;
+ static int _arrayIndex;
+private:
+ CSoundManager *_soundManager;
+ Common::Array<CInstrumentWaveFile> _items;
+ MusicWaveInstrument _instrument;
+ CProjectItem *_project;
+ CGameObject *_gameObjects[4];
+ int _waveIndex;
+ int _readPos;
+ int _readIncrement;
+ uint _size;
+ uint _count;
+ int _field4C;
+private:
+ /**
+ * Loads the specified wave file, and returns a CWaveFile instance for it
+ */
+ CWaveFile *createWaveFile(const CString &name);
+
+ /**
+ * Sets up an array used for figuring out the sequence in which to
+ * play the different wave files for each instrument to give the
+ * music based on the console's settings
+ */
+ void setupArray(int minVal, int maxVal);
+public:
+ double _animTime;
+public:
+ /**
+ * Handles initialization of static fields
+ */
+ static void init();
+
+ /**
+ * Deinitialization of static fields
+ */
+ static void deinit();
+public:
+ CMusicRoomInstrument(CProjectItem *project, CSoundManager *soundManager, MusicWaveInstrument instrument);
+
+ /**
+ * Sets the maximum number of allowed files that be defined
+ */
+ void setFilesCount(uint count);
+
+ /**
+ * Loads a new file into the list of available entries
+ */
+ void load(int index, const CString &filename, int v3);
+
+
+ /**
+ * Starts the music and associated animations
+ */
+ void start();
+
+ /**
+ * Stops the music and associated animations
+ */
+ void stop();
+
+ /**
+ * Handles regular updates of the instrument, allowing associated
+ * objects to start animations as the music is played
+ */
+ void update(int val);
+
+ /**
+ * Clear the instrument
+ */
+ void clear();
+
+ /**
+ * Resets the instrument, and sets the maximum for how much data can
+ * be read from the wave files during each read action
+ */
+ void reset(uint total);
+
+ /**
+ * If there is any wave file currently specified, reads it in
+ * and merges it into the supplied buffer
+ */
+ int read(int16 *ptr, uint size);
+
+ /**
+ * Figure out which wave file to use next
+ */
+ void chooseWaveFile(int index, int freq);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MUSIC_ROOM_INSTRUMENT_H */
diff --git a/engines/titanic/sound/music_song.cpp b/engines/titanic/sound/music_song.cpp
new file mode 100644
index 0000000000..a5527da356
--- /dev/null
+++ b/engines/titanic/sound/music_song.cpp
@@ -0,0 +1,192 @@
+/* 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.
+ *
+ */
+
+#include "titanic/sound/music_song.h"
+#include "titanic/titanic.h"
+#include "common/util.h"
+
+namespace Titanic {
+
+CMusicSong::CMusicSong(int index) {
+ // Read in the list of song strings
+ Common::SeekableReadStream *res = g_vm->_filesManager->getResource("MUSIC/PARSER");
+ Common::StringArray parserStrings;
+ while (res->pos() < res->size())
+ parserStrings.push_back(readStringFromStream(res));
+ delete res;
+
+ // Set up a new song parser with the desired string
+ CSongParser parser(parserStrings[index].c_str());
+
+ // Count how many encoded values there are
+ CValuePair r;
+ int count = 0;
+ while (parser.parse(r))
+ ++count;
+ assert(count > 0);
+
+ // Read in the values to the array
+ _data.resize(count);
+ parser.reset();
+ for (int idx = 0; idx < count; ++idx)
+ parser.parse(_data[idx]);
+
+ // Figure out the range of values in the array
+ _minVal = 0x7FFFFFFF;
+ int maxVal = -0x7FFFFFFF;
+
+ for (int idx = 0; idx < count; ++idx) {
+ CValuePair &vp = _data[idx];
+ if (vp._data != 0x7FFFFFFF) {
+ if (vp._data < _minVal)
+ _minVal = vp._data;
+ if (vp._data > maxVal)
+ maxVal = vp._data;
+ }
+ }
+
+ _range = maxVal - _minVal;
+}
+
+CMusicSong::~CMusicSong() {
+ _data.clear();
+}
+
+/*------------------------------------------------------------------------*/
+
+#define FETCH_CHAR _currentChar = _str[_strIndex++]
+
+CSongParser::CSongParser(const char *str) : _str(str), _strIndex(0),
+ _field8(0), _priorChar('A'), _field10(32), _field14(0), _flag(false),
+ _field1C(0), _currentChar(' '), _numValue(1) {
+}
+
+void CSongParser::reset() {
+ _strIndex = 0;
+ _field8 = 0;
+ _field10 = 0;
+ _field14 = 0;
+ _currentChar = ' ';
+ _priorChar = 'A';
+ _numValue = 1;
+ _field1C = 0;
+}
+
+bool CSongParser::parse(CValuePair &r) {
+ const int INDEXES[8] = { 0, 2, 3, 5, 7, 8, 10, 0 };
+
+ while (_currentChar) {
+ skipSpaces();
+
+ if (Common::isDigit(_currentChar)) {
+ // Parse the number
+ Common::String numStr;
+ do {
+ numStr += _currentChar;
+ FETCH_CHAR;
+ } while (_currentChar && Common::isDigit(_currentChar));
+
+ _numValue = atoi(numStr.c_str());
+ } else if (_currentChar == ',') {
+ _field10 = _numValue;
+ FETCH_CHAR;
+ } else if (_currentChar == ':') {
+ _priorChar = 'A';
+ _field8 = _numValue * 12;
+ FETCH_CHAR;
+ } else if (_currentChar == '/') {
+ r._length += _field10;
+ _field1C += _field10;
+ FETCH_CHAR;
+ } else if (_currentChar == '+') {
+ ++_field14;
+ FETCH_CHAR;
+ } else if (_currentChar == '-') {
+ --_field14;
+ FETCH_CHAR;
+ } else if (_currentChar == '^') {
+ if (_flag)
+ break;
+
+ _flag = true;
+ r._data = 0x7FFFFFFF;
+ r._length = _field10;
+ _field14 = 0;
+ _field1C += _field10;
+ FETCH_CHAR;
+ } else if (_currentChar == '|') {
+ _field1C = 0;
+ FETCH_CHAR;
+ } else if (Common::isAlpha(_currentChar)) {
+ if (_flag)
+ break;
+
+ int val1 = INDEXES[tolower(_currentChar) - 'a'];
+ int val2 = INDEXES[tolower(_priorChar) - 'a'];
+ bool flag = true;
+
+ if (_currentChar == _priorChar) {
+ r._data = _field8;
+ } else if (_currentChar >= 'a' && _currentChar <= 'g') {
+ val1 -= val2;
+ if (val1 >= 0)
+ val1 -= 12;
+ r._data = _field8 + val1;
+ } else if (_currentChar >= 'A' && _currentChar <= 'G') {
+ val1 -= val2;
+ if (val1 <= 0)
+ val1 += 12;
+ r._data = _field8 + val1;
+ } else {
+ flag = false;
+ }
+
+ if (flag) {
+ r._length = _field10;
+ _field1C += _field10;
+ _field8 = r._data;
+ _priorChar = _currentChar;
+ r._data += _field14;
+ _field14 = 0;
+ _flag = true;
+ }
+
+ FETCH_CHAR;
+ } else {
+ FETCH_CHAR;
+ }
+ }
+
+ if (!_flag)
+ return false;
+
+ _flag = false;
+ return true;
+}
+
+void CSongParser::skipSpaces() {
+ while (_currentChar && Common::isSpace(_currentChar)) {
+ FETCH_CHAR;
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/sound/music_wave.h b/engines/titanic/sound/music_song.h
index 4082a926cf..98bc37fd2b 100644
--- a/engines/titanic/sound/music_wave.h
+++ b/engines/titanic/sound/music_song.h
@@ -20,51 +20,62 @@
*
*/
-#ifndef TITANIC_MUSIC_WAVE_H
-#define TITANIC_MUSIC_WAVE_H
+#ifndef TITANIC_MUSIC_SONG_H
+#define TITANIC_MUSIC_SONG_H
+#include "common/scummsys.h"
#include "common/array.h"
-#include "titanic/support/string.h"
namespace Titanic {
-class CProjectItem;
-class CSoundManager;
-class CWaveFile;
+struct CValuePair {
+ int _data;
+ int _length;
+ CValuePair() : _data(0), _length(0) {}
+};
+
+class CMusicSong {
+public:
+ Common::Array<CValuePair> _data;
+ int _minVal;
+ int _range;
+public:
+ CMusicSong(int index);
+ ~CMusicSong();
+
+ int size() const { return _data.size(); }
+
+ const CValuePair &operator[](int index) const { return _data[index]; }
+};
-class CMusicWave {
- struct CMusicWaveFile {
- CWaveFile *_waveFile;
- int _value;
- CMusicWaveFile() : _waveFile(nullptr), _value(0) {}
- };
+class CSongParser {
private:
- CSoundManager *_soundManager;
- Common::Array<CMusicWaveFile> _items;
+ const char *_str;
+ uint _strIndex;
+ int _field8;
+ char _priorChar;
+ int _field10;
+ int _field14;
+ bool _flag;
+ int _field1C;
+ char _currentChar;
+ int _numValue;
private:
- /**
- * Loads the specified wave file, and returns a CWaveFile instance for it
- */
- CWaveFile *createWaveFile(const CString &name);
+ void skipSpaces();
public:
- CMusicWave(CProjectItem *project, CSoundManager *soundManager, int index);
-
- /**
- * Sets the maximum number of allowed files that be defined
- */
- void setSize(uint count);
+ CSongParser(const char *str);
/**
- * Loads a new file into the list of available entries
+ * Resets the parser
*/
- void load(int index, const CString &filename, int v3);
+ void reset();
/**
- * Stops the music
+ * Parses a value from the string
*/
- void stop();
+ bool parse(CValuePair &r);
};
} // End of namespace Titanic
-#endif /* TITANIC_MUSIC_WAVE_H */
+#endif /* TITANIC_MUSIC_SONG_H */
diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp
index b3910f846a..9ff6834efc 100644
--- a/engines/titanic/sound/qmixer.cpp
+++ b/engines/titanic/sound/qmixer.cpp
@@ -204,9 +204,9 @@ void QMixer::qsWaveMixPump() {
if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) {
if (sound._loops == -1 || sound._loops-- > 0) {
// Need to loop the sound again
- sound._waveFile->_stream->rewind();
+ sound._waveFile->audioStream()->rewind();
_mixer->playStream(sound._waveFile->_soundType,
- &sound._soundHandle, sound._waveFile->_stream,
+ &sound._soundHandle, sound._waveFile->audioStream(),
-1, channel.getRawVolume(), 0, DisposeAfterUse::NO);
} else {
// Sound is finished
@@ -230,7 +230,7 @@ void QMixer::qsWaveMixPump() {
// Calculate an effective volume based on distance of source
_mixer->playStream(sound._waveFile->_soundType,
- &sound._soundHandle, sound._waveFile->_stream,
+ &sound._soundHandle, sound._waveFile->audioStream(),
-1, channel.getRawVolume(), 0, DisposeAfterUse::NO);
sound._started = true;
}
diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp
index a3cdae9635..09ba1ae4a7 100644
--- a/engines/titanic/sound/sound_manager.cpp
+++ b/engines/titanic/sound/sound_manager.cpp
@@ -155,6 +155,18 @@ CWaveFile *QSoundManager::loadMusic(const CString &name) {
return waveFile;
}
+CWaveFile *QSoundManager::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) {
+ CWaveFile *waveFile = new CWaveFile();
+
+ // Try to load the specified audio buffer
+ if (!waveFile->loadMusic(buffer, disposeAfterUse)) {
+ delete waveFile;
+ return nullptr;
+ }
+
+ return waveFile;
+}
+
int QSoundManager::playSound(CWaveFile &waveFile, CProximity &prox) {
int channel = -1;
uint flags = QMIX_CLEARQUEUE;
diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h
index ff556346de..3c217324c2 100644
--- a/engines/titanic/sound/sound_manager.h
+++ b/engines/titanic/sound/sound_manager.h
@@ -25,6 +25,7 @@
#include "titanic/core/list.h"
#include "titanic/support/simple_file.h"
+#include "titanic/sound/audio_buffer.h"
#include "titanic/sound/proximity.h"
#include "titanic/sound/qmixer.h"
#include "titanic/sound/wave_file.h"
@@ -64,13 +65,20 @@ public:
* Loads a music file
* @param name Name of music resource
* @returns Loaded wave file
- * @remarks The original created a streaming audio buffer for the wave file,
- * and passed this to the method. For ScummVM, this has been discarded
- * in favor of simply passing the filename.
+ * @remarks The original only classified music as what's produced in the
+ * music room puzzle. For ScummVM, we've reclassified some wave files that
+ * contain background music as music as well.
*/
virtual CWaveFile *loadMusic(const CString &name) { return nullptr; }
/**
+ * Loads a music file from a streaming audio buffer
+ * @param buffer Audio buffer
+ * @returns Loaded wave file
+ */
+ virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { return nullptr; }
+
+ /**
* Start playing a previously loaded wave file
*/
virtual int playSound(CWaveFile &waveFile, CProximity &prox) = 0;
@@ -333,13 +341,20 @@ public:
* Loads a music file
* @param name Name of music resource
* @returns Loaded wave file
- * @remarks The original created a streaming audio buffer for the wave file,
- * and passed this to the method. For ScummVM, this has been discarded
- * in favor of simply passing the filename.
+ * @remarks The original only classified music as what's produced in the
+ * music room puzzle. For ScummVM, we've reclassified some wave files that
+ * contain background music as music as well.
*/
virtual CWaveFile *loadMusic(const CString &name);
/**
+ * Loads a music file from a streaming audio buffer
+ * @param buffer Audio buffer
+ * @returns Loaded wave file
+ */
+ virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse);
+
+ /**
* Start playing a previously loaded sound resource
*/
virtual int playSound(CWaveFile &waveFile, CProximity &prox);
diff --git a/engines/titanic/sound/titania_speech.cpp b/engines/titanic/sound/titania_speech.cpp
index d0ff423342..1adce7a5ac 100644
--- a/engines/titanic/sound/titania_speech.cpp
+++ b/engines/titanic/sound/titania_speech.cpp
@@ -34,16 +34,16 @@ END_MESSAGE_MAP()
void CTitaniaSpeech::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_paraNum, indent);
- file->writeNumberLine(_frameNum, indent);
+ file->writeNumberLine(_actionNum, indent);
+ file->writeNumberLine(_backgroundFrame, indent);
CGameObject::save(file, indent);
}
void CTitaniaSpeech::load(SimpleFile *file) {
file->readNumber();
- _paraNum = file->readNumber();
- _frameNum = file->readNumber();
+ _actionNum = file->readNumber();
+ _backgroundFrame = file->readNumber();
CGameObject::load(file);
}
@@ -54,16 +54,16 @@ bool CTitaniaSpeech::ActMsg(CActMsg *msg) {
CActMsg actMsg;
if (msg->_action == "TitaniaSpeech") {
- switch (_paraNum) {
- case 0:
+ switch (_actionNum) {
+ case 1:
movieSetAudioTiming(true);
loadSound("a#12.wav");
sleep(1000);
- playMovie(0, 187, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(0, 187, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
movieEvent(0);
break;
- case 1:
+ case 2:
loadSound("a#11.wav");
addTimer(0);
startAnimTimer("Para2", 300);
@@ -74,34 +74,34 @@ bool CTitaniaSpeech::ActMsg(CActMsg *msg) {
startAnimTimer("NextPara", 30000);
break;
- case 2:
+ case 3:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound("a#10.wav");
- playMovie(585, 706, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(585, 706, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound("a#10.wav");
break;
- case 3:
+ case 4:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound("a#9.wav");
- playMovie(707, 905, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(707, 905, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound("a#9.wav");
break;
- case 4:
+ case 5:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound("a#8.wav");
- playMovie(906, 938, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT);
+ playMovie(906, 938, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound("a#8.wav");
break;
default:
sleep(3000);
actMsg._action = "SleepTitania";
- actMsg.execute(this);
+ actMsg.execute("TitaniaControl");
}
}
@@ -109,10 +109,10 @@ bool CTitaniaSpeech::ActMsg(CActMsg *msg) {
}
bool CTitaniaSpeech::MovieEndMsg(CMovieEndMsg *msg) {
- if (_paraNum == 5) {
+ if (_actionNum == 5) {
startAnimTimer("NextPara", 0);
} else {
- if (_paraNum != 1)
+ if (_actionNum != 1)
addTimer(0);
startAnimTimer("NextPara", 3000);
}
@@ -135,12 +135,12 @@ bool CTitaniaSpeech::TimerMsg(CTimerMsg *msg) {
if (msg->_action == "NextPara") {
visibleMsg.execute("TitaniaStillControl");
- ++_paraNum;
+ ++_actionNum;
actMsg.execute(this);
} else if (msg->_action == "Para2") {
playSound("a#11.wav");
} else {
- frameMsg._frameNumber = _frameNum;
+ frameMsg._frameNumber = _backgroundFrame++;
frameMsg.execute("TitaniaStillControl");
}
diff --git a/engines/titanic/sound/titania_speech.h b/engines/titanic/sound/titania_speech.h
index 2244bb01af..48e0b7bdad 100644
--- a/engines/titanic/sound/titania_speech.h
+++ b/engines/titanic/sound/titania_speech.h
@@ -36,10 +36,11 @@ class CTitaniaSpeech : public CGameObject {
bool TimerMsg(CTimerMsg *msg);
bool EnterRoomMsg(CEnterRoomMsg *msg);
private:
- int _paraNum, _frameNum;
+ int _actionNum;
+ int _backgroundFrame;
public:
CLASSDEF;
- CTitaniaSpeech() : CGameObject(), _paraNum(1), _frameNum(0) {}
+ CTitaniaSpeech() : CGameObject(), _actionNum(1), _backgroundFrame(0) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp
index f2366d1dd5..c9205c76ac 100644
--- a/engines/titanic/sound/wave_file.cpp
+++ b/engines/titanic/sound/wave_file.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "audio/decoders/raw.h"
#include "audio/decoders/wave.h"
#include "common/memstream.h"
#include "titanic/sound/wave_file.h"
@@ -28,46 +29,99 @@
namespace Titanic {
-CWaveFile::CWaveFile() : _owner(nullptr), _stream(nullptr),
- _soundType(Audio::Mixer::kPlainSoundType) {
+/**
+ * This creates a ScummVM audio stream around a CAudioBuffer buffer,
+ * allowing for streaming audio output for the music room music
+ */
+class AudioBufferStream : public Audio::SeekableAudioStream {
+private:
+ CAudioBuffer *_audioBuffer;
+public:
+ AudioBufferStream(CAudioBuffer *audioBuffer) : _audioBuffer(audioBuffer) {}
+
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const { return false; }
+ virtual bool endOfData() const;
+ virtual int getRate() const { return 22050; }
+ virtual Audio::Timestamp getLength() const { return Audio::Timestamp(); }
+ virtual bool seek(const Audio::Timestamp &where) { return false; }
+};
+
+int AudioBufferStream::readBuffer(int16 *buffer, const int numSamples) {
+ _audioBuffer->enterCriticalSection();
+ int samplesToRead = MIN((const int)numSamples, (const int)_audioBuffer->size());
+
+ for (int idx = 0; idx < samplesToRead; ++idx)
+ *buffer++ = _audioBuffer->pop();
+
+ _audioBuffer->leaveCriticalSection();
+ return samplesToRead;
}
-CWaveFile::CWaveFile(QSoundManager *owner) : _owner(owner), _stream(nullptr),
- _soundType(Audio::Mixer::kPlainSoundType) {
+bool AudioBufferStream::endOfData() const {
+ return _audioBuffer->_finished;
+}
+
+/*------------------------------------------------------------------------*/
+
+CWaveFile::CWaveFile() : _audioStream(nullptr),
+ _waveData(nullptr), _waveSize(0), _dataSize(0), _headerSize(0),
+ _rate(0), _flags(0), _wavType(0), _soundType(Audio::Mixer::kPlainSoundType) {
+ setup();
+}
+
+CWaveFile::CWaveFile(QSoundManager *owner) : _audioStream(nullptr),
+ _waveData(nullptr), _waveSize(0), _dataSize(0), _headerSize(0),
+ _rate(0), _flags(0), _wavType(0), _soundType(Audio::Mixer::kPlainSoundType) {
+ setup();
+}
+
+void CWaveFile::setup() {
+ _loadMode = LOADMODE_SCUMMVM;
+ _dataSize = 0;
+ _audioBuffer = nullptr;
+ _disposeAudioBuffer = DisposeAfterUse::NO;
+ _channel = -1;
}
CWaveFile::~CWaveFile() {
- if (_stream) {
- _owner->soundFreed(_soundHandle);
- delete _stream;
+ if (_audioStream) {
+ //_soundManager->soundFreed(_soundHandle);
+ delete _audioStream;
}
+
+ if (_disposeAudioBuffer == DisposeAfterUse::YES && _audioBuffer)
+ delete _audioBuffer;
+
+ delete[] _waveData;
}
uint CWaveFile::getDurationTicks() const {
- if (!_stream)
+ if (!_audioStream)
return 0;
// FIXME: The original uses acmStreamSize to calculate
// a desired size. Since I have no idea how the system API
// method works, for now I'm using a simple ratio of a
// sample output to input value
- uint dataSize = _size - 0x46;
- double newSize = (double)dataSize * (1475712.0 / 199836.0);
- return (uint)(newSize * 1000.0 / _stream->getRate());
+ double newSize = (double)_dataSize * (1475712.0 / 199836.0);
+ return (uint)(newSize * 1000.0 / _audioStream->getRate());
}
bool CWaveFile::loadSound(const CString &name) {
- assert(!_stream);
+ assert(!_audioStream);
StdCWadFile file;
if (!file.open(name))
return false;
Common::SeekableReadStream *stream = file.readStream();
- _size = stream->size();
- _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES);
- _soundType = Audio::Mixer::kSFXSoundType;
+ uint wavSize = stream->size();
+ byte *data = new byte[wavSize];
+ stream->read(data, wavSize);
+ load(data, wavSize);
+ _soundType = Audio::Mixer::kSFXSoundType;
return true;
}
@@ -78,36 +132,92 @@ bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) {
byte *data = (byte *)malloc(res->_size);
dialogueFile->read(res, data, res->_size);
+ load(data, res->_size);
- _size = res->_size;
- _stream = Audio::makeWAVStream(new Common::MemoryReadStream(data, _size, DisposeAfterUse::YES),
- DisposeAfterUse::YES);
_soundType = Audio::Mixer::kSpeechSoundType;
-
return true;
}
bool CWaveFile::loadMusic(const CString &name) {
- assert(!_stream);
+ assert(!_audioStream);
StdCWadFile file;
if (!file.open(name))
return false;
Common::SeekableReadStream *stream = file.readStream();
- _size = stream->size();
- _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES);
+ uint wavSize = stream->size();
+ byte *data = new byte[wavSize];
+ stream->read(data, wavSize);
+ delete stream;
+
+ load(data, wavSize);
_soundType = Audio::Mixer::kMusicSoundType;
+ return true;
+}
+
+bool CWaveFile::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) {
+ _audioBuffer = buffer;
+ _disposeAudioBuffer = disposeAfterUse;
+ _loadMode = LOADMODE_AUDIO_BUFFER;
+ _audioStream = new AudioBufferStream(_audioBuffer);
return true;
}
-uint CWaveFile::getFrequency() const {
- return _stream->getRate();
+void CWaveFile::load(byte *data, uint dataSize) {
+ _waveData = data;
+ _waveSize = dataSize;
+
+ // Parse the wave header
+ Common::MemoryReadStream wavStream(data, dataSize, DisposeAfterUse::NO);
+ if (!Audio::loadWAVFromStream(wavStream, _dataSize, _rate, _flags, &_wavType))
+ error("Invalid wave file");
+ _headerSize = wavStream.pos();
+}
+
+Audio::SeekableAudioStream *CWaveFile::audioStream() {
+ if (!_audioStream) {
+ // No stream yet, so create one and give it control of the raw wave data
+ assert(_waveData);
+ _audioStream = Audio::makeWAVStream(
+ new Common::MemoryReadStream(_waveData, _waveSize, DisposeAfterUse::YES),
+ DisposeAfterUse::YES);
+ _waveData = nullptr;
+ }
+
+ return _audioStream;
+}
+
+
+uint CWaveFile::getFrequency() {
+ return audioStream()->getRate();
}
void CWaveFile::reset() {
- _stream->rewind();
+ audioStream()->rewind();
+}
+
+const int16 *CWaveFile::lock() {
+ enum { kWaveFormatPCM = 1 };
+
+ switch (_loadMode) {
+ case LOADMODE_SCUMMVM:
+ // Sanity checking that only raw 16-bit LE 22Khz waves can be locked
+ assert(_waveData && _rate == 22050);
+ assert(_flags == (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS));
+ assert(_wavType == kWaveFormatPCM);
+
+ // Return a pointer to the data section of the wave file
+ return (const int16 *)(_waveData + _headerSize);
+
+ default:
+ return nullptr;
+ }
+}
+
+void CWaveFile::unlock(const int16 *ptr) {
+ // No implementation needed in ScummVM
}
} // End of namespace Titanic z
diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h
index e4bb71a0b6..6bd18989b9 100644
--- a/engines/titanic/sound/wave_file.h
+++ b/engines/titanic/sound/wave_file.h
@@ -25,21 +25,43 @@
#include "audio/audiostream.h"
#include "audio/mixer.h"
+#include "titanic/sound/audio_buffer.h"
#include "titanic/support/string.h"
#include "titanic/true_talk/dialogue_file.h"
namespace Titanic {
+enum LoadMode { LOADMODE_AUDIO_BUFFER = 1, LOADMODE_SCUMMVM = 2 };
+
class QSoundManager;
class CWaveFile {
private:
- uint _size;
+ byte *_waveData;
+ int _waveSize;
+ int _dataSize;
+ int _headerSize;
+ int _rate;
+ byte _flags;
+ uint16 _wavType;
+ Audio::SeekableAudioStream *_audioStream;
+private:
+ /**
+ * Handles setup of fields shared by the constructors
+ */
+ void setup();
+
+ /**
+ * Gets passed the raw data for the wave file
+ */
+ void load(byte *data, uint dataSize);
public:
- QSoundManager *_owner;
- Audio::SeekableAudioStream *_stream;
- Audio::SoundHandle _soundHandle;
Audio::Mixer::SoundType _soundType;
+
+ LoadMode _loadMode;
+ CAudioBuffer *_audioBuffer;
+ DisposeAfterUse::Flag _disposeAudioBuffer;
+ int _channel;
public:
CWaveFile();
CWaveFile(QSoundManager *owner);
@@ -55,7 +77,12 @@ public:
/**
* Return the size of the wave file
*/
- uint size() const { return _size; }
+ uint size() const { return _dataSize; }
+
+ /**
+ * Returns a ScummVM Audio Stream for playback purposes
+ */
+ Audio::SeekableAudioStream *audioStream();
/**
* Tries to load the specified wave file sound
@@ -73,19 +100,36 @@ public:
bool loadMusic(const CString &name);
/**
+ * Tries to load the specified audio buffer
+ */
+ bool loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse);
+
+ /**
* Returns true if the wave file has data loaded
*/
- bool isLoaded() const { return _stream != nullptr; }
+ bool isLoaded() const {
+ return _audioStream != nullptr || _waveData != nullptr;
+ }
/**
* Return the frequency of the loaded wave file
*/
- uint getFrequency() const;
+ uint getFrequency();
/**
* Resets the music stream
*/
void reset();
+
+ /**
+ * Lock sound data for access
+ */
+ const int16 *lock();
+
+ /**
+ * Unlock sound data after a prior call to lock
+ */
+ void unlock(const int16 *ptr);
};
} // End of namespace Titanic
diff --git a/engines/titanic/star_control/star_control.cpp b/engines/titanic/star_control/star_control.cpp
index dcb004231a..a1c4f33ad2 100644
--- a/engines/titanic/star_control/star_control.cpp
+++ b/engines/titanic/star_control/star_control.cpp
@@ -133,8 +133,8 @@ void CStarControl::fn1(int action) {
// TODO
}
-bool CStarControl::fn4() {
- return _starField.get6();
+bool CStarControl::isSolved() const {
+ return _starField.isSolved();
}
bool CStarControl::canSetStarDestination() const {
diff --git a/engines/titanic/star_control/star_control.h b/engines/titanic/star_control/star_control.h
index bf964b7cfa..0ee7c6530e 100644
--- a/engines/titanic/star_control/star_control.h
+++ b/engines/titanic/star_control/star_control.h
@@ -69,7 +69,11 @@ public:
virtual void draw(CScreenManager *screenManager);
void fn1(int action);
- bool fn4();
+
+ /**
+ * Returns true if the starfield puzzle has been solved
+ */
+ bool isSolved() const;
/**
* Returns true if a star destination can be set
diff --git a/engines/titanic/star_control/star_field.cpp b/engines/titanic/star_control/star_field.cpp
index 0dbc5fd700..7502f84d3d 100644
--- a/engines/titanic/star_control/star_field.cpp
+++ b/engines/titanic/star_control/star_field.cpp
@@ -26,7 +26,7 @@
namespace Titanic {
CStarField::CStarField() : _val1(0), _val2(0), _val3(0), _val4(true),
- _val5(0), _val6(false) {
+ _val5(0), _isSolved(false) {
}
void CStarField::load(SimpleFile *file) {
@@ -36,7 +36,7 @@ void CStarField::load(SimpleFile *file) {
_val2 = file->readNumber();
_val3 = file->readNumber();
_val4 = file->readNumber();
- _val6 = file->readNumber();
+ _isSolved = file->readNumber();
}
void CStarField::save(SimpleFile *file, int indent) {
@@ -46,7 +46,7 @@ void CStarField::save(SimpleFile *file, int indent) {
file->writeNumberLine(_val2, indent);
file->writeNumberLine(_val3, indent);
file->writeNumberLine(_val4, indent);
- file->writeNumberLine(_val6, indent);
+ file->writeNumberLine(_isSolved, indent);
}
bool CStarField::initDocument() {
@@ -119,12 +119,12 @@ int CStarField::get5() const {
return _val5;
}
-void CStarField::update6() {
- _val6 = _sub8._field8 == 2;
+void CStarField::setSolved() {
+ _isSolved = _sub8._field8 == 2;
}
-int CStarField::get6() const {
- return _val6;
+bool CStarField::isSolved() const {
+ return _isSolved;
}
} // End of namespace Titanic
diff --git a/engines/titanic/star_control/star_field.h b/engines/titanic/star_control/star_field.h
index 91cefbb457..41f01894f4 100644
--- a/engines/titanic/star_control/star_field.h
+++ b/engines/titanic/star_control/star_field.h
@@ -44,7 +44,7 @@ private:
int _val3;
bool _val4;
int _val5;
- bool _val6;
+ bool _isSolved;
public:
CStarField();
@@ -77,8 +77,16 @@ public:
bool set4(bool val);
int get88() const;
int get5() const;
- void update6();
- int get6() const;
+
+ /**
+ * Sets the flag that the starfield has been solved
+ */
+ void setSolved();
+
+ /**
+ * Returns true if the starfield puzzle has been solved
+ */
+ bool isSolved() const;
};
} // End of namespace Titanic
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
index 42e3618b97..a1dbecbe1c 100644
--- a/engines/titanic/support/avi_surface.cpp
+++ b/engines/titanic/support/avi_surface.cpp
@@ -284,10 +284,13 @@ void AVISurface::copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedS
if (src.format.bytesPerPixel == 1) {
// Paletted 8-bit, so convert to 16-bit and copy over
- Graphics::Surface *s = src.convertTo(dest.format, _decoder->getPalette());
- dest.blitFrom(*s, copyRect, Common::Point(0, 0));
- s->free();
- delete s;
+ const byte *palette = _decoder->getPalette();
+ if (palette) {
+ Graphics::Surface *s = src.convertTo(dest.format, palette);
+ dest.blitFrom(*s, copyRect, Common::Point(0, 0));
+ s->free();
+ delete s;
+ }
} else if (src.format.bytesPerPixel == 2) {
// Source is already 16-bit, with no alpha, so do a straight copy
dest.blitFrom(src, copyRect, Common::Point(0, 0));
diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h
index f45db3599e..d3442a12f7 100644
--- a/engines/titanic/support/avi_surface.h
+++ b/engines/titanic/support/avi_surface.h
@@ -34,8 +34,11 @@ class CSoundManager;
class CVideoSurface;
enum MovieFlag {
- MOVIE_REPEAT = 1, MOVIE_STOP_PREVIOUS = 2, MOVIE_NOTIFY_OBJECT = 4,
- MOVIE_REVERSE = 8, MOVIE_GAMESTATE = 0x10
+ MOVIE_REPEAT = 1, // Repeat movie
+ MOVIE_STOP_PREVIOUS = 2, // Stop any prior movie playing on the object
+ MOVIE_NOTIFY_OBJECT = 4, // Notify the object when the movie finishes
+ MOVIE_REVERSE = 8, // Play the movie in reverse
+ MOVIE_WAIT_FOR_FINISH = 0x10 // Let finish before playing next movie for object
};
class AVIDecoder : public Video::AVIDecoder {
diff --git a/engines/titanic/support/files_manager.cpp b/engines/titanic/support/files_manager.cpp
index fc09c5702c..cf706974a7 100644
--- a/engines/titanic/support/files_manager.cpp
+++ b/engines/titanic/support/files_manager.cpp
@@ -106,7 +106,7 @@ void CFilesManager::loadDrive() {
}
void CFilesManager::insertCD(CScreenManager *screenManager) {
- // We not support running game directly from the original CDs,
+ // We don't support running the game directly from the original CDs,
// so this method can remain stubbed
}
diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp
index 60d01dae35..116c3346e8 100644
--- a/engines/titanic/titanic.cpp
+++ b/engines/titanic/titanic.cpp
@@ -41,6 +41,7 @@
#include "titanic/moves/enter_exit_sec_class_mini_lift.h"
#include "titanic/moves/exit_pellerator.h"
#include "titanic/pet_control/pet_control.h"
+#include "titanic/sound/music_room_instrument.h"
#include "titanic/support/simple_file.h"
#include "titanic/true_talk/tt_npc_script.h"
@@ -86,6 +87,7 @@ void TitanicEngine::initialize() {
CGetLiftEye2::init();
CHose::init();
CMovie::init();
+ CMusicRoomInstrument::init();
CParrotLobbyObject::init();
CSGTNavigation::init();
CSGTStateRoom::init();
diff --git a/engines/titanic/true_talk/barbot_script.cpp b/engines/titanic/true_talk/barbot_script.cpp
index 3da9d0e05f..c0d879b965 100644
--- a/engines/titanic/true_talk/barbot_script.cpp
+++ b/engines/titanic/true_talk/barbot_script.cpp
@@ -1016,11 +1016,10 @@ uint BarbotScript::getDialsBitset() const {
}
int BarbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) {
- int v34 = getState();
uint id = 0;
- if (v34 > 0x200) {
- switch (v34 - 0x201) {
+ if (val1 > 0x200) {
+ switch (val1 - 0x201) {
case 0:
if (getValue(4) != 2)
id = 250738;
@@ -1035,11 +1034,11 @@ int BarbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScrip
default:
break;
}
- } else if (v34 == 0x200) {
+ } else if (val1 == 0x200) {
if (getValue(4) != 1)
id = 250738;
} else {
- switch (v34) {
+ switch (val1) {
case 2:
if (getValue(1) != 1)
return 1;
@@ -1072,40 +1071,34 @@ int BarbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScrip
break;
case 9: {
uint val = CTrueTalkManager::getStateValue(3);
- bool bit0 = (val & 1) != 0;
- bool bit2 = (val & 4) != 0;
- bool bit3 = (val & 8) != 0;
+ bool lemonFlag = (val & 1) != 0;
+ bool puretFlag = (val & 4) != 0;
+ bool tvFlag = (val & 8) != 0;
- if (bit2) {
- if (!bit0) {
- id = 250085 - (bit3 ? 0 : 199715);
+ if (puretFlag) {
+ if (!lemonFlag) {
+ id = tvFlag ? 50369 : 250085;
break;
- } else if (!bit3) {
+ } else if (!tvFlag) {
id = 250627;
}
} else {
- if (!bit0) {
- id = 50365 + (bit3 ? 0 : 2);
- } else if (!bit3) {
+ if (lemonFlag) {
+ id = tvFlag ? 50367 : 50365;
+ } else if (tvFlag) {
id = 50370;
}
}
-
- if (id) {
- addResponse(getDialogueId(id));
- applyResponse();
- return 2;
- }
break;
}
case 10: {
uint val = CTrueTalkManager::getStateValue(3);
- bool bit0 = (val & 1) != 0;
- bool bit2 = (val & 4) != 0;
- bool bit3 = (val & 8) != 0;
+ bool lemonFlag = (val & 1) != 0;
+ bool puretFlag = (val & 4) != 0;
+ bool tvFlag = (val & 8) != 0;
- if (bit0 && bit2 && bit3) {
+ if (lemonFlag && puretFlag && tvFlag) {
addResponse(getDialogueId(251027));
applyResponse();
CTrueTalkManager::triggerAction(7, 0);
diff --git a/engines/titanic/true_talk/tt_npc_script.cpp b/engines/titanic/true_talk/tt_npc_script.cpp
index ba205b6498..990f22722d 100644
--- a/engines/titanic/true_talk/tt_npc_script.cpp
+++ b/engines/titanic/true_talk/tt_npc_script.cpp
@@ -113,6 +113,13 @@ void TTnpcData::resetFlags() {
Common::fill(&_array[20], &_array[136], 0);
}
+void TTnpcData::copyData() {
+ if (_array[20]) {
+ Common::copy_backward(&_array[16], &_array[136], &_array[24]);
+ Common::fill(&_array[20], &_array[28], 0);
+ }
+}
+
/*------------------------------------------------------------------------*/
TTnpcScriptBase::TTnpcScriptBase(int charId_, const char *charClass, int v2,
@@ -803,6 +810,7 @@ TTscriptRange *TTnpcScript::findRange(uint id) {
}
void TTnpcScript::checkItems(const TTroomScript *roomScript, const TTsentence *sentence) {
+ _data.copyData();
_field2CC = 0;
++CTrueTalkManager::_v2;
diff --git a/engines/titanic/true_talk/tt_npc_script.h b/engines/titanic/true_talk/tt_npc_script.h
index e5be7d7296..c2f001f8cc 100644
--- a/engines/titanic/true_talk/tt_npc_script.h
+++ b/engines/titanic/true_talk/tt_npc_script.h
@@ -43,6 +43,8 @@ public:
int &operator[](int idx) { return _array[idx]; }
int *getSlot(int idx) { return &_array[16 + idx * 4]; }
void resetFlags();
+
+ void copyData();
};
class TTnpcScriptBase : public TTscriptBase {
diff --git a/engines/titanic/true_talk/tt_parser.cpp b/engines/titanic/true_talk/tt_parser.cpp
index bd89079cf1..88a5ec3614 100644
--- a/engines/titanic/true_talk/tt_parser.cpp
+++ b/engines/titanic/true_talk/tt_parser.cpp
@@ -131,7 +131,7 @@ int TTparser::normalize(TTsentence *sentence) {
if (!destLine->empty() && destLine->lastChar() != ' ')
(*destLine) += ' ';
} else if (Common::isUpper(c)) {
- (*destLine) += toupper(c);
+ (*destLine) += tolower(c);
} else if (Common::isDigit(c)) {
if (c == '0' && isEmoticon(srcLine, index)) {
sentence->set38(10);
@@ -256,7 +256,7 @@ int TTparser::isEmoticon(const TTstring &str, int &index) {
}
}
-bool TTparser::normalizeContraction(const TTstring &srcLine, int srcIndex, TTstring &destLine) {
+bool TTparser::normalizeContraction(const TTstring &srcLine, int &srcIndex, TTstring &destLine) {
int startIndex = srcIndex + 1;
switch (srcLine[startIndex]) {
case 'd':
@@ -792,8 +792,8 @@ int TTparser::considerRequests(TTword *word) {
if (flag)
delete oldConcept;
} else if (!_sentenceConcept->_concept3P &&
- (!_sentenceConcept->_concept1P || (_sentenceConcept->_concept1P->getWordId() &&
- _sentenceConcept->_concept1P->getWordId() == 112)) &&
+ (!_sentenceConcept->_concept1P || (_sentenceConcept->_concept1P->getWordId() != 113 &&
+ _sentenceConcept->_concept1P->getWordId() != 112)) &&
_sentenceConcept->_concept2P->checkWordId1() &&
(word->_wordClass == WC_THING || word->_wordClass == WC_PRONOUN)) {
_sentenceConcept->changeConcept(0, &_sentenceConcept->_concept2P, 3);
diff --git a/engines/titanic/true_talk/tt_parser.h b/engines/titanic/true_talk/tt_parser.h
index 5fd997a985..458a719e1f 100644
--- a/engines/titanic/true_talk/tt_parser.h
+++ b/engines/titanic/true_talk/tt_parser.h
@@ -95,7 +95,7 @@ private:
* Submethod called by normalize to handle expanding contacted word pairs
* like can't, should've, and so on.
*/
- bool normalizeContraction(const TTstring &srcLine, int srcIndex, TTstring &destLine);
+ bool normalizeContraction(const TTstring &srcLine, int &srcIndex, TTstring &destLine);
/**
* Checks for what is likely special developer cheat codes
diff --git a/engines/titanic/true_talk/tt_title_script.cpp b/engines/titanic/true_talk/tt_title_script.cpp
index 2effb96cc7..b69318dbe5 100644
--- a/engines/titanic/true_talk/tt_title_script.cpp
+++ b/engines/titanic/true_talk/tt_title_script.cpp
@@ -24,8 +24,7 @@
namespace Titanic {
-TTTitleScript::TTTitleScript() : TTscriptBase(1, "", 0, "", 0, -1, -1, -1, 0),
- _field50(0), _field5C(-1), _field60(0) {
+TTTitleScript::TTTitleScript() : TTscriptBase(1, "", 0, "", 0, -1, -1, -1, 0) {
}
} // End of namespace Titanic
diff --git a/engines/titanic/true_talk/tt_title_script.h b/engines/titanic/true_talk/tt_title_script.h
index f02e591c54..03d1b04ac7 100644
--- a/engines/titanic/true_talk/tt_title_script.h
+++ b/engines/titanic/true_talk/tt_title_script.h
@@ -29,11 +29,6 @@
namespace Titanic {
class TTTitleScript : public TTscriptBase {
-private:
- int _field50;
- TTstring _string1;
- int _field5C;
- int _field60;
public:
TTTitleScript();
};
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index ecaa671bd7..e8d51109b1 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -1228,7 +1228,8 @@ void Ringworld2Game::processEvent(Event &event) {
case Common::KEYCODE_F8:
// F8 - Credits
- R2_GLOBALS._sceneManager.changeScene(205);
+ if (R2_GLOBALS._sceneManager._sceneNumber != 205)
+ R2_GLOBALS._sceneManager.changeScene(205);
break;
case Common::KEYCODE_F10:
@@ -1972,11 +1973,11 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
case 0:
// Draw from uncompressed source
for (int sliceNum = 0; sliceNum < _subData._ySlices; ++sliceNum) {
- for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex) {
+ for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, ++y) {
// TODO: Check of _subData._drawType was done for two different kinds of
// line slice drawing in original
const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)dest.getBasePtr(0, y++);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
Common::copy(pSrc, pSrc + _subData._sliceSize, pDest);
}
@@ -1988,12 +1989,12 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
case 0xfe:
// Draw from uncompressed source with optional skipped rows
for (int sliceNum = 0; sliceNum < _subData._ySlices; ++sliceNum) {
- for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, playerBounds.top++) {
+ for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, ++y) {
int offset = READ_LE_UINT16(sliceData1 + sliceNum * 2);
if (offset) {
const byte *pSrc = (const byte *)sliceDataStart + offset;
- byte *pDest = (byte *)dest.getBasePtr(0, 0);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
//Common::copy(pSrc, pSrc + playerBounds.width(), pDest);
rleDecode(pSrc, pDest, playerBounds.width());
@@ -2004,11 +2005,11 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
case 0xff:
// Draw from RLE compressed source
for (int sliceNum = 0; sliceNum < _subData._ySlices; ++sliceNum) {
- for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, playerBounds.top++) {
+ for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, ++y) {
// TODO: Check of _subData._drawType was done for two different kinds of
// line slice drawing in original
const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)dest.getBasePtr(0, 0);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
rleDecode(pSrc, pDest, _subData._sliceSize);
}
@@ -2020,10 +2021,10 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
byte *sliceData2 = &slices._pixelData[slice2._sliceOffset - 96];
for (int sliceNum = 0; sliceNum < _subData._ySlices; ++sliceNum) {
- for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex) {
+ for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex, ++y) {
const byte *pSrc1 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData2 + sliceNum * 2);
const byte *pSrc2 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)dest.getBasePtr(0, y++);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
if (slice2._drawMode == 0) {
// Uncompressed background, foreground compressed