aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS7
-rw-r--r--CONTRIBUTING.md12
-rw-r--r--NEWS4
-rw-r--r--README4
-rw-r--r--backends/events/dinguxsdl/dinguxsdl-events.cpp34
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp6
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp2
-rw-r--r--backends/keymapper/action.h2
-rw-r--r--backends/platform/android/asset-archive.cpp3
-rw-r--r--backends/platform/dingux/dingux.mk35
-rw-r--r--backends/platform/sdl/sdl.cpp2
-rw-r--r--backends/platform/wii/osystem_events.cpp136
-rw-r--r--base/version.cpp8
-rw-r--r--common/EventMapper.cpp6
-rw-r--r--common/c++11-compat.h6
-rw-r--r--common/scummsys.h2
-rw-r--r--common/unzip.cpp2
-rw-r--r--common/xmlparser.cpp2
-rwxr-xr-xconfig.guess364
-rwxr-xr-xconfig.sub158
-rwxr-xr-xconfigure31
-rw-r--r--devtools/create_translations/po_parser.cpp7
-rwxr-xr-xdevtools/credits.pl5
-rw-r--r--devtools/scumm-md5.txt43
-rw-r--r--dists/gcw0/default.gcw0.desktop16
-rwxr-xr-xdists/gcw0/opk_make.sh111
-rw-r--r--dists/gcw0/scummvm.pngbin0 -> 2656 bytes
-rwxr-xr-xdists/gcw0/scummvm.sh9
-rw-r--r--dists/gcw0/scummvmrc9
-rw-r--r--engines/agi/agi.cpp6
-rw-r--r--engines/agi/detection.cpp9
-rw-r--r--engines/agi/graphics.cpp23
-rw-r--r--engines/agi/preagi_mickey.cpp2
-rw-r--r--engines/agos/detection_tables.h26
-rw-r--r--engines/agos/gfx.cpp2
-rw-r--r--engines/agos/input.cpp10
-rw-r--r--engines/agos/midi.cpp22
-rw-r--r--engines/agos/midi.h4
-rw-r--r--engines/bbvs/bbvs.cpp98
-rw-r--r--engines/bbvs/bbvs.h78
-rw-r--r--engines/bbvs/detection.cpp2
-rw-r--r--engines/bbvs/dialogs.cpp8
-rw-r--r--engines/bbvs/dialogs.h6
-rw-r--r--engines/bbvs/gamemodule.cpp40
-rw-r--r--engines/bbvs/gamemodule.h50
-rw-r--r--engines/bbvs/graphics.cpp4
-rw-r--r--engines/bbvs/minigames/bbairguitar.cpp62
-rw-r--r--engines/bbvs/minigames/bbairguitar.h34
-rw-r--r--engines/bbvs/minigames/bbant.cpp64
-rw-r--r--engines/bbvs/minigames/bbant.h26
-rw-r--r--engines/bbvs/minigames/bbloogie.cpp68
-rw-r--r--engines/bbvs/minigames/bbloogie.h36
-rw-r--r--engines/bbvs/minigames/bbtennis.cpp44
-rw-r--r--engines/bbvs/minigames/bbtennis.h22
-rw-r--r--engines/bbvs/minigames/minigame.cpp6
-rw-r--r--engines/bbvs/minigames/minigame.h14
-rw-r--r--engines/bbvs/saveload.cpp26
-rw-r--r--engines/bbvs/scene.cpp20
-rw-r--r--engines/bbvs/spritemodule.cpp12
-rw-r--r--engines/bbvs/videoplayer.cpp4
-rw-r--r--engines/bbvs/walk.cpp24
-rw-r--r--engines/cge/vga13h.cpp2
-rw-r--r--engines/cge2/cge2.cpp2
-rw-r--r--engines/cge2/cge2.h2
-rw-r--r--engines/cge2/cge2_main.cpp24
-rw-r--r--engines/cge2/cge2_main.h2
-rw-r--r--engines/cge2/configure.engine2
-rw-r--r--engines/cge2/events.cpp4
-rw-r--r--engines/cge2/hero.cpp10
-rw-r--r--engines/cge2/map.cpp2
-rw-r--r--engines/cge2/saveload.cpp4
-rw-r--r--engines/cge2/snail.cpp10
-rw-r--r--engines/cge2/spare.h2
-rw-r--r--engines/cge2/talk.cpp2
-rw-r--r--engines/cge2/vga13h.cpp8
-rw-r--r--engines/fullpipe/fullpipe.cpp4
-rw-r--r--engines/fullpipe/gfx.cpp8
-rw-r--r--engines/fullpipe/input.cpp2
-rw-r--r--engines/fullpipe/motion.cpp14
-rw-r--r--engines/fullpipe/scene.cpp2
-rw-r--r--engines/fullpipe/scenes/scene02.cpp2
-rw-r--r--engines/fullpipe/scenes/scene14.cpp2
-rw-r--r--engines/fullpipe/scenes/scene15.cpp2
-rw-r--r--engines/fullpipe/scenes/scene16.cpp8
-rw-r--r--engines/fullpipe/scenes/scene23.cpp2
-rw-r--r--engines/fullpipe/scenes/scene28.cpp2
-rw-r--r--engines/fullpipe/scenes/scene29.cpp2
-rw-r--r--engines/fullpipe/scenes/scene37.cpp2
-rw-r--r--engines/fullpipe/sound.cpp2
-rw-r--r--engines/fullpipe/statics.cpp8
-rw-r--r--engines/groovie/graphics.cpp25
-rw-r--r--engines/groovie/graphics.h2
-rw-r--r--engines/groovie/roq.cpp76
-rw-r--r--engines/groovie/roq.h6
-rw-r--r--engines/groovie/script.cpp69
-rw-r--r--engines/groovie/script.h1
-rw-r--r--engines/hopkins/computer.cpp2
-rw-r--r--engines/hopkins/files.cpp2
-rw-r--r--engines/hopkins/sound.cpp53
-rw-r--r--engines/hopkins/sound.h2
-rw-r--r--engines/hopkins/talk.cpp2
-rw-r--r--engines/kyra/vqa.cpp2
-rw-r--r--engines/mads/game.cpp2
-rw-r--r--engines/mads/menu_views.cpp24
-rw-r--r--engines/mads/msurface.h4
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp2
-rw-r--r--engines/mads/nebular/dialogs_nebular.h4
-rw-r--r--engines/mads/nebular/game_nebular.cpp2
-rw-r--r--engines/mads/nebular/menu_nebular.cpp16
-rw-r--r--engines/mads/nebular/nebular_scenes6.cpp2
-rw-r--r--engines/mads/nebular/nebular_scenes7.cpp2
-rw-r--r--engines/mads/nebular/nebular_scenes8.cpp2
-rw-r--r--engines/mads/palette.cpp4
-rw-r--r--engines/mads/scene.cpp6
-rw-r--r--engines/mads/scene_data.cpp2
-rw-r--r--engines/mads/sequence.cpp2
-rw-r--r--engines/mohawk/riven_external.cpp2
-rw-r--r--engines/mortevielle/detection_tables.h2
-rw-r--r--engines/mortevielle/mortevielle.h2
-rw-r--r--engines/mortevielle/utils.cpp2
-rw-r--r--engines/neverhood/console.cpp2
-rw-r--r--engines/neverhood/modules/module2400.cpp9
-rw-r--r--engines/neverhood/modules/module2700_sprites.cpp56
-rw-r--r--engines/neverhood/modules/module2800.cpp15
-rw-r--r--engines/neverhood/modules/module2800_sprites.cpp10
-rw-r--r--engines/neverhood/modules/module3000.cpp12
-rw-r--r--engines/neverhood/modules/module3000_sprites.cpp36
-rw-r--r--engines/neverhood/sound.cpp2
-rw-r--r--engines/pegasus/input.cpp2
-rw-r--r--engines/pegasus/pegasus.cpp2
-rw-r--r--engines/prince/animation.cpp6
-rw-r--r--engines/prince/animation.h2
-rw-r--r--engines/prince/archive.cpp24
-rw-r--r--engines/prince/archive.h1
-rw-r--r--engines/prince/cursor.h2
-rw-r--r--engines/prince/detection.cpp6
-rw-r--r--engines/prince/detection.h38
-rw-r--r--engines/prince/graphics.cpp2
-rw-r--r--engines/prince/graphics.h2
-rw-r--r--engines/prince/hero.cpp4
-rw-r--r--engines/prince/hero.h4
-rw-r--r--engines/prince/mhwanh.cpp4
-rw-r--r--engines/prince/mob.h2
-rw-r--r--engines/prince/object.cpp2
-rw-r--r--engines/prince/object.h2
-rw-r--r--engines/prince/prince.cpp219
-rw-r--r--engines/prince/prince.h20
-rw-r--r--engines/prince/pscr.h2
-rw-r--r--engines/prince/resource.h6
-rw-r--r--engines/prince/saveload.cpp33
-rw-r--r--engines/prince/script.cpp33
-rw-r--r--engines/prince/script.h3
-rw-r--r--engines/queen/logic.cpp6
-rw-r--r--engines/queen/talk.cpp12
-rw-r--r--engines/saga/actor.h1
-rw-r--r--engines/saga/introproc_ite.cpp2
-rw-r--r--engines/saga/saveload.cpp29
-rw-r--r--engines/saga/scene.h3
-rw-r--r--engines/saga/sfuncs.cpp4
-rw-r--r--engines/sci/console.cpp5
-rw-r--r--engines/sci/engine/kernel.h4
-rw-r--r--engines/sci/engine/kgraphics.cpp33
-rw-r--r--engines/sci/engine/kstring.cpp10
-rw-r--r--engines/sci/engine/script_patches.cpp40
-rw-r--r--engines/sci/engine/script_patches.h2
-rw-r--r--engines/sci/engine/state.cpp115
-rw-r--r--engines/sci/engine/workarounds.cpp3
-rw-r--r--engines/sci/graphics/controls16.cpp12
-rw-r--r--engines/sci/graphics/controls16.h6
-rw-r--r--engines/sci/graphics/cursor.cpp8
-rw-r--r--engines/sci/graphics/font.cpp8
-rw-r--r--engines/sci/graphics/font.h4
-rw-r--r--engines/sci/graphics/frameout.cpp10
-rw-r--r--engines/sci/graphics/paint16.cpp6
-rw-r--r--engines/sci/graphics/paint16.h2
-rw-r--r--engines/sci/graphics/paint32.cpp2
-rw-r--r--engines/sci/graphics/palette.cpp87
-rw-r--r--engines/sci/graphics/palette.h6
-rw-r--r--engines/sci/graphics/picture.cpp88
-rw-r--r--engines/sci/graphics/portrait.cpp42
-rw-r--r--engines/sci/graphics/portrait.h2
-rw-r--r--engines/sci/graphics/ports.cpp16
-rw-r--r--engines/sci/graphics/screen.cpp384
-rw-r--r--engines/sci/graphics/screen.h94
-rw-r--r--engines/sci/graphics/text16.cpp225
-rw-r--r--engines/sci/graphics/text16.h15
-rw-r--r--engines/sci/graphics/transitions.cpp6
-rw-r--r--engines/sci/graphics/view.cpp2
-rw-r--r--engines/sci/module.mk4
-rw-r--r--engines/sci/resource.cpp3
-rw-r--r--engines/sci/resource_audio.cpp2
-rw-r--r--engines/sci/sci.cpp6
-rw-r--r--engines/sci/sci.h7
-rw-r--r--engines/sci/sound/music.cpp2
-rw-r--r--engines/sci/sound/music.h2
-rw-r--r--engines/scumm/actor.cpp725
-rw-r--r--engines/scumm/actor.h49
-rw-r--r--engines/scumm/boxes.cpp24
-rw-r--r--engines/scumm/cdda.cpp2
-rw-r--r--engines/scumm/detection.cpp5
-rw-r--r--engines/scumm/detection_tables.h16
-rw-r--r--engines/scumm/dialogs.cpp6
-rw-r--r--engines/scumm/file.cpp26
-rw-r--r--engines/scumm/input.cpp12
-rw-r--r--engines/scumm/resource_v2.cpp10
-rw-r--r--engines/scumm/room.cpp9
-rw-r--r--engines/scumm/saveload.cpp7
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script.cpp6
-rw-r--r--engines/scumm/script_v0.cpp34
-rw-r--r--engines/scumm/script_v2.cpp9
-rw-r--r--engines/scumm/script_v5.cpp4
-rw-r--r--engines/scumm/scumm-md5.h42
-rw-r--r--engines/scumm/scumm.cpp16
-rw-r--r--engines/scumm/scumm.h4
-rw-r--r--engines/scumm/scumm_v0.h8
-rw-r--r--engines/scumm/sound.cpp4
-rw-r--r--engines/scumm/vars.cpp2
-rw-r--r--engines/scumm/verbs.cpp57
-rw-r--r--engines/sword1/console.cpp2
-rw-r--r--engines/sword1/sound.cpp2
-rw-r--r--engines/sword25/gfx/renderobjectmanager.cpp2
-rw-r--r--engines/sword25/sword25.cpp1
-rw-r--r--engines/sword25/util/lua/lapi.cpp3
-rw-r--r--engines/sword25/util/lua/liolib.cpp2
-rw-r--r--engines/sword25/util/pluto/pluto.cpp8
-rw-r--r--engines/tony/game.cpp4
-rw-r--r--engines/tony/gfxcore.cpp119
-rw-r--r--engines/tony/mpal/lzo.cpp2
-rw-r--r--engines/tony/window.cpp14
-rw-r--r--engines/toon/character.cpp2
-rw-r--r--engines/toon/state.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_outpost.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp2
-rw-r--r--engines/wintermute/base/base_engine.cpp3
-rw-r--r--engines/wintermute/base/base_engine.h9
-rw-r--r--engines/wintermute/base/base_game.cpp5
-rw-r--r--engines/wintermute/base/base_game.h2
-rw-r--r--engines/wintermute/base/base_game_settings.cpp5
-rw-r--r--engines/wintermute/base/base_game_settings.h1
-rw-r--r--engines/wintermute/base/base_keyboard_state.cpp48
-rw-r--r--engines/wintermute/base/base_sprite.cpp15
-rw-r--r--engines/wintermute/base/base_string_table.cpp9
-rw-r--r--engines/wintermute/base/base_string_table.h1
-rw-r--r--engines/wintermute/detection.cpp6
-rw-r--r--engines/wintermute/detection_tables.h1552
-rw-r--r--engines/wintermute/game_description.h (renamed from engines/zvision/inventory/inventory_manager.h)33
-rw-r--r--engines/wintermute/math/rect32.h2
-rw-r--r--engines/wintermute/module.mk2
-rw-r--r--engines/wintermute/video/subtitle_card.cpp56
-rw-r--r--engines/wintermute/video/subtitle_card.h53
-rw-r--r--engines/wintermute/video/video_subtitler.cpp266
-rw-r--r--engines/wintermute/video/video_subtitler.h53
-rw-r--r--engines/wintermute/video/video_theora_player.cpp27
-rw-r--r--engines/wintermute/video/video_theora_player.h6
-rw-r--r--engines/wintermute/wintermute.cpp4
-rw-r--r--engines/wintermute/wintermute.h5
-rw-r--r--engines/zvision/animation/meta_animation.cpp132
-rw-r--r--engines/zvision/animation/meta_animation.h (renamed from engines/zvision/scripting/controls/animation_control.h)59
-rw-r--r--engines/zvision/animation/rlf_animation.cpp255
-rw-r--r--engines/zvision/animation/rlf_animation.h35
-rw-r--r--engines/zvision/core/console.cpp124
-rw-r--r--engines/zvision/core/console.h2
-rw-r--r--engines/zvision/core/events.cpp363
-rw-r--r--engines/zvision/core/menu.cpp761
-rw-r--r--engines/zvision/core/menu.h99
-rw-r--r--engines/zvision/core/midi.cpp89
-rw-r--r--engines/zvision/core/midi.h59
-rw-r--r--engines/zvision/core/save_manager.cpp231
-rw-r--r--engines/zvision/core/save_manager.h21
-rw-r--r--engines/zvision/core/search_manager.cpp273
-rw-r--r--engines/zvision/core/search_manager.h73
-rw-r--r--engines/zvision/cursors/cursor.cpp78
-rw-r--r--engines/zvision/cursors/cursor.h27
-rw-r--r--engines/zvision/cursors/cursor_manager.cpp202
-rw-r--r--engines/zvision/cursors/cursor_manager.h78
-rw-r--r--engines/zvision/detection.cpp216
-rw-r--r--engines/zvision/detection.h1
-rw-r--r--engines/zvision/fonts/truetype_font.cpp113
-rw-r--r--engines/zvision/graphics/effect.h83
-rw-r--r--engines/zvision/graphics/effects/fog.cpp173
-rw-r--r--engines/zvision/graphics/effects/fog.h52
-rw-r--r--engines/zvision/graphics/effects/light.cpp109
-rw-r--r--engines/zvision/graphics/effects/light.h53
-rw-r--r--engines/zvision/graphics/effects/wave.cpp145
-rw-r--r--engines/zvision/graphics/effects/wave.h51
-rw-r--r--engines/zvision/graphics/render_manager.cpp1144
-rw-r--r--engines/zvision/graphics/render_manager.h337
-rw-r--r--engines/zvision/graphics/render_table.cpp74
-rw-r--r--engines/zvision/graphics/render_table.h18
-rw-r--r--engines/zvision/graphics/subtitles.cpp108
-rw-r--r--engines/zvision/graphics/subtitles.h (renamed from engines/zvision/subtitles/subtitles.h)28
-rw-r--r--engines/zvision/graphics/truetype_font.cpp341
-rw-r--r--engines/zvision/graphics/truetype_font.h (renamed from engines/zvision/fonts/truetype_font.h)50
-rw-r--r--engines/zvision/module.mk35
-rw-r--r--engines/zvision/scripting/actions.cpp898
-rw-r--r--engines/zvision/scripting/actions.h338
-rw-r--r--engines/zvision/scripting/control.cpp54
-rw-r--r--engines/zvision/scripting/control.h106
-rw-r--r--engines/zvision/scripting/controls/animation_control.cpp263
-rw-r--r--engines/zvision/scripting/controls/fist_control.cpp319
-rw-r--r--engines/zvision/scripting/controls/fist_control.h86
-rw-r--r--engines/zvision/scripting/controls/hotmov_control.cpp200
-rw-r--r--engines/zvision/scripting/controls/hotmov_control.h62
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp201
-rw-r--r--engines/zvision/scripting/controls/input_control.h35
-rw-r--r--engines/zvision/scripting/controls/lever_control.cpp212
-rw-r--r--engines/zvision/scripting/controls/lever_control.h20
-rw-r--r--engines/zvision/scripting/controls/paint_control.cpp214
-rw-r--r--engines/zvision/scripting/controls/paint_control.h91
-rw-r--r--engines/zvision/scripting/controls/push_toggle_control.cpp103
-rw-r--r--engines/zvision/scripting/controls/push_toggle_control.h22
-rw-r--r--engines/zvision/scripting/controls/safe_control.cpp204
-rw-r--r--engines/zvision/scripting/controls/safe_control.h70
-rw-r--r--engines/zvision/scripting/controls/save_control.cpp124
-rw-r--r--engines/zvision/scripting/controls/save_control.h55
-rw-r--r--engines/zvision/scripting/controls/slot_control.cpp218
-rw-r--r--engines/zvision/scripting/controls/slot_control.h84
-rw-r--r--engines/zvision/scripting/controls/titler_control.cpp107
-rw-r--r--engines/zvision/scripting/controls/titler_control.h54
-rw-r--r--engines/zvision/scripting/inventory.cpp122
-rw-r--r--engines/zvision/scripting/puzzle.h12
-rw-r--r--engines/zvision/scripting/scr_file_handling.cpp291
-rw-r--r--engines/zvision/scripting/script_manager.cpp916
-rw-r--r--engines/zvision/scripting/script_manager.h197
-rw-r--r--engines/zvision/scripting/sidefx.h114
-rw-r--r--engines/zvision/scripting/sidefx/animation_node.cpp204
-rw-r--r--engines/zvision/scripting/sidefx/animation_node.h83
-rw-r--r--engines/zvision/scripting/sidefx/distort_node.cpp105
-rw-r--r--engines/zvision/scripting/sidefx/distort_node.h63
-rw-r--r--engines/zvision/scripting/sidefx/music_node.cpp238
-rw-r--r--engines/zvision/scripting/sidefx/music_node.h135
-rw-r--r--engines/zvision/scripting/sidefx/region_node.cpp56
-rw-r--r--engines/zvision/scripting/sidefx/region_node.h57
-rw-r--r--engines/zvision/scripting/sidefx/syncsound_node.cpp85
-rw-r--r--engines/zvision/scripting/sidefx/syncsound_node.h56
-rw-r--r--engines/zvision/scripting/sidefx/timer_node.cpp (renamed from engines/zvision/scripting/controls/timer_node.cpp)40
-rw-r--r--engines/zvision/scripting/sidefx/timer_node.h (renamed from engines/zvision/scripting/controls/timer_node.h)14
-rw-r--r--engines/zvision/scripting/sidefx/ttytext_node.cpp174
-rw-r--r--engines/zvision/scripting/sidefx/ttytext_node.h73
-rw-r--r--engines/zvision/sound/zork_raw.cpp235
-rw-r--r--engines/zvision/sound/zork_raw.h88
-rw-r--r--engines/zvision/text/string_manager.cpp (renamed from engines/zvision/strings/string_manager.cpp)33
-rw-r--r--engines/zvision/text/string_manager.h (renamed from engines/zvision/strings/string_manager.h)14
-rw-r--r--engines/zvision/text/text.cpp544
-rw-r--r--engines/zvision/text/text.h99
-rw-r--r--engines/zvision/utility/clock.cpp1
-rw-r--r--engines/zvision/utility/clock.h11
-rw-r--r--engines/zvision/utility/lzss_read_stream.cpp13
-rw-r--r--engines/zvision/utility/lzss_read_stream.h3
-rw-r--r--engines/zvision/utility/single_value_container.cpp348
-rw-r--r--engines/zvision/utility/single_value_container.h183
-rw-r--r--engines/zvision/utility/utility.cpp192
-rw-r--r--engines/zvision/utility/utility.h67
-rw-r--r--engines/zvision/utility/zfs_archive.cpp (renamed from engines/zvision/archives/zfs_archive.cpp)13
-rw-r--r--engines/zvision/utility/zfs_archive.h (renamed from engines/zvision/archives/zfs_archive.h)3
-rw-r--r--engines/zvision/video/video.cpp133
-rw-r--r--engines/zvision/video/zork_avi_decoder.cpp16
-rw-r--r--engines/zvision/video/zork_avi_decoder.h28
-rw-r--r--engines/zvision/zvision.cpp446
-rw-r--r--engines/zvision/zvision.h123
-rw-r--r--graphics/VectorRenderer.h2
-rw-r--r--graphics/VectorRendererSpec.cpp52
-rw-r--r--graphics/VectorRendererSpec.h2
-rw-r--r--graphics/surface.h2
-rw-r--r--graphics/transform_struct.h2
-rw-r--r--gui/EventRecorder.cpp1
-rw-r--r--gui/about.cpp2
-rw-r--r--gui/browser_osx.mm4
-rw-r--r--gui/credits.h5
-rw-r--r--gui/debugger.cpp81
-rw-r--r--gui/debugger.h4
-rw-r--r--gui/themes/scummmodern.zipbin1489429 -> 1485886 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx4
-rw-r--r--gui/themes/translations.datbin468258 -> 470115 bytes
-rw-r--r--gui/widgets/edittext.cpp2
-rw-r--r--gui/widgets/tab.h2
-rw-r--r--image/codecs/mjpeg.cpp2
-rw-r--r--image/codecs/mpeg.h2
-rw-r--r--image/iff.cpp2
-rw-r--r--image/image_decoder.h2
-rw-r--r--po/nl_NL.po100
-rw-r--r--ports.mk5
-rw-r--r--video/avi_decoder.cpp373
-rw-r--r--video/avi_decoder.h18
385 files changed, 17182 insertions, 6979 deletions
diff --git a/AUTHORS b/AUTHORS
index 37067e5e04..9470217230 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -257,6 +257,7 @@ ScummVM Team
Wintermute:
Einar Johan T. Somaaen
+ Tobia Tesan
ZVision:
Adrian Astley
@@ -651,7 +652,7 @@ Special thanks to
repository, planet and doxygen sites as well as tons
of HD space
DOSBox Team - For their awesome OPL2 and OPL3 emulator
- Yusuke Kamiyamane - For contributing some GUI icons
+ Yusuke Kamiyamane - For contributing some GUI icons
Till Kresslein - For design of modern ScummVM GUI
Jezar - For his freeverb filter implementation
Jim Leiterman - Various info on his FM-TOWNS/Marty SCUMM ports
@@ -700,8 +701,8 @@ Special thanks to
of Dreamweb and for their tremendous support.
Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe
- Avalon for providing full source code for Soltys and letting us
- redistribute the game.
+ Avalon for providing full source code for Soltys and Sfinx and letting us
+ redistribute the games.
Jan Nedoma for providing the sources to the Wintermute-engine, and for his
support while porting the engine to ScummVM.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..3a6672b0cb
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,12 @@
+Thank you for considering contributing to ScummVM.
+
+Please make sure to read our guidelines for contributions on our
+[wiki](http://wiki.scummvm.org/index.php/Developer_Central). In particular:
+
+* [Coding style](http://wiki.scummvm.org/index.php/Code_Formatting_Conventions)
+* [Portability](http://wiki.scummvm.org/index.php/Coding_Conventions)
+* [Commit message style](http://wiki.scummvm.org/index.php/Commit_Guidelines)
+* License: GPLv2+
+
+If you have any questions about code, style, procedure, or anything else, feel
+free to contact us on our mailing list at scummvm-devel@lists.sourceforge.net.
diff --git a/NEWS b/NEWS
index bb23bb37ff..762af70962 100644
--- a/NEWS
+++ b/NEWS
@@ -2,8 +2,10 @@ For a more comprehensive changelog of the latest experimental code, see:
https://github.com/scummvm/scummvm/commits/
1.8.0 (????-??-??)
+ New Games:
+ - Added support for Sfinx.
-Broken Sword 1:
+ Broken Sword 1:
- Fix speech endianness detection on big endian systems for the mac
version (bug #6720).
- Fix crash when reloading a game from the Main Menu while in the bull's
diff --git a/README b/README
index 0a256b39f3..5b0569089c 100644
--- a/README
+++ b/README
@@ -427,7 +427,7 @@ in the previous paragraph.
3.3) Maniac Mansion NES notes:
---- -------------------------
Supported versions are English GB (E), French (F), German (G), Italian (I),
-Swedish (SW) and English US (U). ScummVM requires just the PRG section
+Swedish (SW) and English US (U). ScummVM requires just the PRG section
to run and not the whole ROM.
In order to get the game working, you will have to strip out the first
@@ -1441,7 +1441,7 @@ The platforms that currently have a different default directory are:
<windir>\Profiles\username\Application Data\ScummVM\Saved games\
Saved games are stored under a hidden area in Windows NT4/2000/XP/Vista/7,
-which can be accessed by running "%APPDATA%\ScummVM\Saved Games\" or by
+which can be accessed by running "%APPDATA%\ScummVM\Saved Games\" or by
enabling hidden files in Windows Explorer.
Note for Windows NT4/2000/XP/Vista/7 users: The default saved games location
diff --git a/backends/events/dinguxsdl/dinguxsdl-events.cpp b/backends/events/dinguxsdl/dinguxsdl-events.cpp
index 6f9f2a7748..cc15f2666c 100644
--- a/backends/events/dinguxsdl/dinguxsdl-events.cpp
+++ b/backends/events/dinguxsdl/dinguxsdl-events.cpp
@@ -26,18 +26,48 @@
#include "backends/events/dinguxsdl/dinguxsdl-events.h"
+#ifndef GCW0
#define PAD_UP SDLK_UP
#define PAD_DOWN SDLK_DOWN
#define PAD_LEFT SDLK_LEFT
#define PAD_RIGHT SDLK_RIGHT
#define BUT_A SDLK_LCTRL
#define BUT_B SDLK_LALT
-#define BUT_X SDLK_SPACE
-#define BUT_Y SDLK_LSHIFT
+#define BUT_X SDLK_SPACE // BUT_Y in GCW0
+#define BUT_Y SDLK_LSHIFT // BUT_X in GCW0
#define BUT_SELECT SDLK_ESCAPE
#define BUT_START SDLK_RETURN
#define TRIG_L SDLK_TAB
#define TRIG_R SDLK_BACKSPACE
+#else // GCW0
+
+/******
+ * GCW0 keymap
+ * Dingoo button
+ * A -> Left Button BUT_Y
+ * B -> right button BUT_B
+ * X -> ' ' BUT_A '0'
+ * Y -> '.' BUT_X
+ * Select -> ESC TRIG_R
+ * Start -> F5 TRIG_L
+ * L -> Shift BUT_START
+ * R -> VK BUT_SELECT
+ */
+
+#define PAD_UP SDLK_UP
+#define PAD_DOWN SDLK_DOWN
+#define PAD_LEFT SDLK_LEFT
+#define PAD_RIGHT SDLK_RIGHT
+#define BUT_A SDLK_LSHIFT
+#define BUT_B SDLK_LALT
+#define BUT_X SDLK_SPACE
+#define BUT_Y SDLK_LCTRL
+#define BUT_SELECT SDLK_BACKSPACE
+#define BUT_START SDLK_TAB
+#define TRIG_L SDLK_RETURN
+#define TRIG_R SDLK_ESCAPE
+
+#endif
bool DINGUXSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
if (ev.key.keysym.sym == PAD_UP) {
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index cbd06e9161..c455c4ce2e 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -489,7 +489,7 @@ void OpenGLGraphicsManager::warpMouse(int x, int y) {
if (!_overlay) {
return;
}
-
+
// It might be confusing that we actually have to handle something
// here when the overlay is visible. This is because for very small
// resolutions we have a minimal overlay size and have to adjust
@@ -1044,8 +1044,8 @@ void OpenGLGraphicsManager::recalculateDisplayArea() {
}
// We center the screen in the middle for now.
- _displayX = (_outputScreenWidth - _displayWidth ) / 2;
- _displayY = (_outputScreenHeight - _displayHeight) / 2;
+ _displayX = (_outputScreenWidth - _displayWidth ) / 2;
+ _displayY = (_outputScreenHeight - _displayHeight) / 2;
}
void OpenGLGraphicsManager::updateCursorPalette() {
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index c998f3d1f1..b028cd5b1a 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -282,7 +282,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
if (!_fullscreenVideoModes.empty()) {
VideoModeArray::const_iterator i = _fullscreenVideoModes.end();
--i;
-
+
_desiredFullscreenWidth = i->width;
_desiredFullscreenHeight = i->height;
} else {
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index ed4bb86ce6..17b1153c77 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -37,7 +37,7 @@ namespace Common {
struct HardwareInput;
class Keymap;
-#define ACTION_ID_SIZE (4)
+#define ACTION_ID_SIZE (5)
struct KeyActionEntry {
const KeyState ks;
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 52c2c084bd..6680081c16 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -295,7 +295,6 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
jclass cls = env->GetObjectClass(_assetfd);
MID_close = env->GetMethodID(cls, "close", "()V");
assert(MID_close);
- env->DeleteLocalRef(cls);
jmethodID MID_getStartOffset =
env->GetMethodID(cls, "getStartOffset", "()J");
@@ -321,6 +320,8 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
_fd = env->GetIntField(javafd, FID_descriptor);
env->DeleteLocalRef(javafd);
+
+ env->DeleteLocalRef(cls);
}
AssetFdReadStream::~AssetFdReadStream() {
diff --git a/backends/platform/dingux/dingux.mk b/backends/platform/dingux/dingux.mk
index 48a9347143..1333e89ff8 100644
--- a/backends/platform/dingux/dingux.mk
+++ b/backends/platform/dingux/dingux.mk
@@ -1,6 +1,7 @@
DINGUX_EXE_STRIPPED := scummvm_stripped$(EXEEXT)
bundle_name = dingux-dist/scummvm
+gcw0_bundle = gcw0-opk
all: $(DINGUX_EXE_STRIPPED)
@@ -30,3 +31,37 @@ endif
$(CP) $(srcdir)/backends/platform/dingux/scummvm.gpe $(bundle_name)/
$(CP) $(srcdir)/backends/platform/dingux/README.DINGUX $(bundle_name)/
$(CP) $(srcdir)/backends/platform/dingux/scummvm.png $(bundle_name)/
+
+# Special target for generationg GCW-Zero OPK bundle
+$(gcw0_bundle): all
+ $(MKDIR) $(gcw0_bundle)
+ $(CP) $(DIST_FILES_DOCS) $(gcw0_bundle)/
+ $(MKDIR) $(gcw0_bundle)/themes
+ $(CP) $(DIST_FILES_THEMES) $(gcw0_bundle)/themes/
+ifdef DIST_FILES_ENGINEDATA
+ $(MKDIR) $(gcw0_bundle)/engine-data
+ $(CP) $(DIST_FILES_ENGINEDATA) $(gcw0_bundle)/engine-data/
+endif
+ifdef DYNAMIC_MODULES
+ $(MKDIR) $(gcw0_bundle)/plugins
+ $(CP) $(PLUGINS) $(gcw0_bundle)/plugins/
+endif
+ $(CP) $(EXECUTABLE) $(gcw0_bundle)/scummvm
+
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(gcw0_bundle)/
+ $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_small.zip $(gcw0_bundle)/
+
+ $(CP) $(srcdir)/dists/gcw0/scummvm.png $(gcw0_bundle)/
+ $(CP) $(srcdir)/dists/gcw0/default.gcw0.desktop $(gcw0_bundle)/
+ $(CP) $(srcdir)/dists/gcw0/scummvmrc $(gcw0_bundle)/
+ $(CP) $(srcdir)/dists/gcw0/scummvm.sh $(gcw0_bundle)/
+
+gcw0-opk-unstripped: $(gcw0_bundle)
+ $(CP) $(PLUGINS) $(gcw0_bundle)/plugins/
+ $(CP) $(EXECUTABLE) $(gcw0_bundle)/scummvm
+ ./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm
+
+gcw-opk: $(gcw0_bundle)
+ $(STRIP) $(gcw0_bundle)/plugins/*
+ $(STRIP) $(gcw0_bundle)/scummvm
+ ./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 41610dc0c7..4dc5929dab 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -390,7 +390,7 @@ Common::String OSystem_SDL::getSystemLanguage() const {
#else // WIN32
// Activating current locale settings
const Common::String locale = setlocale(LC_ALL, "");
-
+
// Restore default C locale to prevent issues with
// portability of sscanf(), atof(), etc.
// See bug #3615148
diff --git a/backends/platform/wii/osystem_events.cpp b/backends/platform/wii/osystem_events.cpp
index 0563639de3..13f5d1fbe0 100644
--- a/backends/platform/wii/osystem_events.cpp
+++ b/backends/platform/wii/osystem_events.cpp
@@ -70,73 +70,73 @@
#endif
#ifdef USE_WII_KBD
-static int keymap[][2] = {
- { KS_Return, Common::KEYCODE_RETURN },
- { KS_Up, Common::KEYCODE_UP },
- { KS_Down, Common::KEYCODE_DOWN },
- { KS_Left, Common::KEYCODE_LEFT },
- { KS_Right, Common::KEYCODE_RIGHT },
- { KS_Shift_L, Common::KEYCODE_LSHIFT },
- { KS_Shift_R, Common::KEYCODE_RSHIFT },
- { KS_Control_L, Common::KEYCODE_LCTRL },
- { KS_Control_R, Common::KEYCODE_RCTRL },
- { KS_Alt_L, Common::KEYCODE_LALT },
- { KS_Alt_R, Common::KEYCODE_RALT },
- { KS_Meta_L, Common::KEYCODE_LMETA },
- { KS_Meta_R, Common::KEYCODE_RMETA },
- { KS_KP_0, Common::KEYCODE_KP0 },
- { KS_KP_1, Common::KEYCODE_KP1 },
- { KS_KP_2, Common::KEYCODE_KP2 },
- { KS_KP_3, Common::KEYCODE_KP3 },
- { KS_KP_4, Common::KEYCODE_KP4 },
- { KS_KP_5, Common::KEYCODE_KP5 },
- { KS_KP_6, Common::KEYCODE_KP6 },
- { KS_KP_7, Common::KEYCODE_KP7 },
- { KS_KP_8, Common::KEYCODE_KP8 },
- { KS_KP_9, Common::KEYCODE_KP9 },
- { KS_Home, Common::KEYCODE_HOME },
- { KS_Insert, Common::KEYCODE_INSERT },
- { KS_End, Common::KEYCODE_END },
- { KS_Prior, Common::KEYCODE_PAGEUP },
- { KS_Next, Common::KEYCODE_PAGEDOWN },
- { KS_f1, Common::KEYCODE_F1 },
- { KS_f2, Common::KEYCODE_F2 },
- { KS_f3, Common::KEYCODE_F3 },
- { KS_f4, Common::KEYCODE_F4 },
- { KS_f5, Common::KEYCODE_F5 },
- { KS_f6, Common::KEYCODE_F6 },
- { KS_f7, Common::KEYCODE_F7 },
- { KS_f8, Common::KEYCODE_F8 },
- { KS_f9, Common::KEYCODE_F9 },
- { KS_f10, Common::KEYCODE_F10 },
- { KS_f11, Common::KEYCODE_F11 },
- { KS_f12, Common::KEYCODE_F12 },
- { KS_f13, Common::KEYCODE_F13 },
- { KS_f14, Common::KEYCODE_F14 },
- { KS_f15, Common::KEYCODE_F15 },
- { KS_F1, Common::KEYCODE_F1 },
- { KS_F2, Common::KEYCODE_F2 },
- { KS_F3, Common::KEYCODE_F3 },
- { KS_F4, Common::KEYCODE_F4 },
- { KS_F5, Common::KEYCODE_F5 },
- { KS_F6, Common::KEYCODE_F6 },
- { KS_F7, Common::KEYCODE_F7 },
- { KS_F8, Common::KEYCODE_F8 },
- { KS_F9, Common::KEYCODE_F9 },
- { KS_F10, Common::KEYCODE_F10 },
- { KS_F11, Common::KEYCODE_F11 },
- { KS_F12, Common::KEYCODE_F12 },
- { KS_F13, Common::KEYCODE_F13 },
- { KS_F14, Common::KEYCODE_F14 },
- { KS_F15, Common::KEYCODE_F15 },
- { KS_KP_Separator, Common::KEYCODE_KP_PERIOD },
- { KS_KP_Subtract, Common::KEYCODE_KP_DIVIDE },
- { KS_KP_Multiply, Common::KEYCODE_KP_MULTIPLY },
- { KS_KP_Add, Common::KEYCODE_KP_PLUS },
- { KS_KP_Subtract, Common::KEYCODE_KP_MINUS },
- { KS_KP_Equal, Common::KEYCODE_KP_EQUALS },
- { KS_KP_Enter, Common::KEYCODE_KP_ENTER },
- { 0, 0 }
+static int keymap[][3] = {
+ { KS_Return, Common::KEYCODE_RETURN, Common::ASCII_RETURN },
+ { KS_Up, Common::KEYCODE_UP, 0 },
+ { KS_Down, Common::KEYCODE_DOWN, 0 },
+ { KS_Left, Common::KEYCODE_LEFT, 0 },
+ { KS_Right, Common::KEYCODE_RIGHT, 0 },
+ { KS_Shift_L, Common::KEYCODE_LSHIFT, 0 },
+ { KS_Shift_R, Common::KEYCODE_RSHIFT, 0 },
+ { KS_Control_L, Common::KEYCODE_LCTRL, 0 },
+ { KS_Control_R, Common::KEYCODE_RCTRL, 0 },
+ { KS_Alt_L, Common::KEYCODE_LALT, 0 },
+ { KS_Alt_R, Common::KEYCODE_RALT, 0 },
+ { KS_Meta_L, Common::KEYCODE_LMETA, 0 },
+ { KS_Meta_R, Common::KEYCODE_RMETA, 0 },
+ { KS_KP_0, Common::KEYCODE_KP0, '0' },
+ { KS_KP_1, Common::KEYCODE_KP1, '1' },
+ { KS_KP_2, Common::KEYCODE_KP2, '2' },
+ { KS_KP_3, Common::KEYCODE_KP3, '3' },
+ { KS_KP_4, Common::KEYCODE_KP4, '4' },
+ { KS_KP_5, Common::KEYCODE_KP5, '5' },
+ { KS_KP_6, Common::KEYCODE_KP6, '6' },
+ { KS_KP_7, Common::KEYCODE_KP7, '7' },
+ { KS_KP_8, Common::KEYCODE_KP8, '8' },
+ { KS_KP_9, Common::KEYCODE_KP9, '9' },
+ { KS_Home, Common::KEYCODE_HOME, 0 },
+ { KS_Insert, Common::KEYCODE_INSERT, 0 },
+ { KS_End, Common::KEYCODE_END, 0 },
+ { KS_Prior, Common::KEYCODE_PAGEUP, 0 },
+ { KS_Next, Common::KEYCODE_PAGEDOWN, 0 },
+ { KS_f1, Common::KEYCODE_F1, Common::ASCII_F1 },
+ { KS_f2, Common::KEYCODE_F2, Common::ASCII_F2 },
+ { KS_f3, Common::KEYCODE_F3, Common::ASCII_F3 },
+ { KS_f4, Common::KEYCODE_F4, Common::ASCII_F4 },
+ { KS_f5, Common::KEYCODE_F5, Common::ASCII_F5 },
+ { KS_f6, Common::KEYCODE_F6, Common::ASCII_F6 },
+ { KS_f7, Common::KEYCODE_F7, Common::ASCII_F7 },
+ { KS_f8, Common::KEYCODE_F8, Common::ASCII_F8 },
+ { KS_f9, Common::KEYCODE_F9, Common::ASCII_F9 },
+ { KS_f10, Common::KEYCODE_F10, Common::ASCII_F10 },
+ { KS_f11, Common::KEYCODE_F11, Common::ASCII_F11 },
+ { KS_f12, Common::KEYCODE_F12, Common::ASCII_F12 },
+ { KS_f13, Common::KEYCODE_F13, 0 },
+ { KS_f14, Common::KEYCODE_F14, 0 },
+ { KS_f15, Common::KEYCODE_F15, 0 },
+ { KS_F1, Common::KEYCODE_F1, Common::ASCII_F1 },
+ { KS_F2, Common::KEYCODE_F2, Common::ASCII_F2 },
+ { KS_F3, Common::KEYCODE_F3, Common::ASCII_F3 },
+ { KS_F4, Common::KEYCODE_F4, Common::ASCII_F4 },
+ { KS_F5, Common::KEYCODE_F5, Common::ASCII_F5 },
+ { KS_F6, Common::KEYCODE_F6, Common::ASCII_F6 },
+ { KS_F7, Common::KEYCODE_F7, Common::ASCII_F7 },
+ { KS_F8, Common::KEYCODE_F8, Common::ASCII_F8 },
+ { KS_F9, Common::KEYCODE_F9, Common::ASCII_F9 },
+ { KS_F10, Common::KEYCODE_F10, Common::ASCII_F10 },
+ { KS_F11, Common::KEYCODE_F11, Common::ASCII_F11 },
+ { KS_F12, Common::KEYCODE_F12, Common::ASCII_F12 },
+ { KS_F13, Common::KEYCODE_F13, 0 },
+ { KS_F14, Common::KEYCODE_F14, 0 },
+ { KS_F15, Common::KEYCODE_F15, 0 },
+ { KS_KP_Separator, Common::KEYCODE_KP_PERIOD, '.' },
+ { KS_KP_Divide, Common::KEYCODE_KP_DIVIDE, '/' },
+ { KS_KP_Multiply, Common::KEYCODE_KP_MULTIPLY, '*' },
+ { KS_KP_Add, Common::KEYCODE_KP_PLUS, '+' },
+ { KS_KP_Subtract, Common::KEYCODE_KP_MINUS, '-' },
+ { KS_KP_Equal, Common::KEYCODE_KP_EQUALS, '=' },
+ { KS_KP_Enter, Common::KEYCODE_KP_ENTER, Common::ASCII_RETURN },
+ { 0, 0, 0 }
};
#endif
@@ -262,7 +262,7 @@ bool OSystem_Wii::pollKeyboard(Common::Event &event) {
while (keymap[i][0] != 0) {
if (keymap[i][0] == kbdEvent.symbol) {
event.kbd.keycode = static_cast<Common::KeyCode>(keymap[i][1]);
- event.kbd.ascii = 0;
+ event.kbd.ascii = keymap[i][2];
return true;
}
diff --git a/base/version.cpp b/base/version.cpp
index ef02ff9d21..fcb2740de9 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -146,4 +146,12 @@ const char *gScummVMFeatures = ""
#ifdef USE_PNG
"PNG "
#endif
+
+#ifdef ENABLE_KEYMAPPER
+ "keymapper "
+#endif
+
+#ifdef ENABLE_VKEYBD
+ "virtual keyboard "
+#endif
;
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp
index b92116cbe7..cf65946d50 100644
--- a/common/EventMapper.cpp
+++ b/common/EventMapper.cpp
@@ -45,7 +45,7 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) {
if (ev.type == EVENT_MBUTTONUP) {
if ((g_system->getMillis() - vkeybdThen) >= vkeybdTime) {
mappedEvent.type = EVENT_VIRTUAL_KEYBOARD;
-
+
// Avoid blocking event from engine.
addDelayedEvent(100, ev);
}
@@ -59,7 +59,7 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) {
#ifdef ENABLE_VKEYBD
else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F7) {
mappedEvent.type = EVENT_VIRTUAL_KEYBOARD;
-
+
// Avoid blocking CTRL-F7 events from engine.
addDelayedEvent(100, ev);
}
@@ -67,7 +67,7 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) {
#ifdef ENABLE_KEYMAPPER
else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F8) {
mappedEvent.type = EVENT_KEYMAPPER_REMAP;
-
+
// Avoid blocking CTRL-F8 events from engine.
addDelayedEvent(100, ev);
}
diff --git a/common/c++11-compat.h b/common/c++11-compat.h
index 14e0642821..a56b79514c 100644
--- a/common/c++11-compat.h
+++ b/common/c++11-compat.h
@@ -32,13 +32,19 @@
// though.
//
#if !defined(nullptr) // XCode 5.0.1 has __cplusplus=199711 but defines this
+// MSVC 2010 and newer fully support nullptr: http://msdn.microsoft.com/en-us/library/hh567368.aspx
+#if !defined(_MSC_VER) || _MSC_VER < 1600
#define nullptr 0
#endif
+#endif
//
// Replacement for the override keyword. This allows compilation of code
// which uses it, but does not feature any semantic.
//
+// MSVC 2012 and newer fully support override: http://msdn.microsoft.com/en-us/library/hh567368.aspx
+#if !defined(_MSC_VER) || _MSC_VER < 1700
#define override
+#endif
#endif
diff --git a/common/scummsys.h b/common/scummsys.h
index c30bc4a52a..0c4687e03e 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -148,7 +148,7 @@
#endif
#endif
-// The following math constants are usually defined by the system math.h header, but
+// The following math constants are usually defined by the system math.h header, but
// they are not part of the ANSI C++ standards and so can NOT be relied upon to be
// present i.e. when -std=c++11 is passed to GCC, enabling strict ANSI compliance.
// As we rely on these being present, we define them if they are not set.
diff --git a/common/unzip.cpp b/common/unzip.cpp
index 716c8c2d5e..1f4e601989 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -334,8 +334,10 @@ int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len);
#define SIZEZIPLOCALHEADER (0x1e)
+#if 0
const char unz_copyright[] =
" unzip 0.15 Copyright 1998 Gilles Vollant ";
+#endif
/* unz_file_info_interntal contain internal info about a file in zipfile*/
typedef struct {
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index c80d5e15be..67a3d36cec 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -69,7 +69,7 @@ bool XMLParser::loadBuffer(const byte *buffer, uint32 size, DisposeAfterUse::Fla
bool XMLParser::loadStream(SeekableReadStream *stream) {
_stream = stream;
_fileName = "File Stream";
- return true;
+ return _stream != nullptr;
}
void XMLParser::close() {
diff --git a/config.guess b/config.guess
index 43f0cdbcfd..6c32c8645c 100755
--- a/config.guess
+++ b/config.guess
@@ -1,14 +1,12 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# Copyright 1992-2014 Free Software Foundation, Inc.
-timestamp='2011-10-01'
+timestamp='2014-11-04'
# This file 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
+# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -17,26 +15,22 @@ timestamp='2011-10-01'
# 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.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner. Please send patches (context
-# diff format) to <config-patches@gnu.org> and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches@gnu.org>.
+
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -56,9 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -140,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -202,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -304,7 +321,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -562,8 +579,9 @@ EOF
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
@@ -803,9 +821,15 @@ EOF
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
@@ -851,15 +875,22 @@ EOF
exit ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
@@ -871,59 +902,54 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
- echo cris-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
- echo frv-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
- echo hexagon-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
@@ -942,54 +968,63 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
- or32:Linux:*:*)
- echo or32-unknown-linux-gnu
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
+ echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
+ echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
+ echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1193,6 +1228,9 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1219,19 +1257,31 @@ EOF
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1248,7 +1298,7 @@ EOF
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
+ NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
@@ -1317,158 +1367,10 @@ EOF
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
+esac
cat >&2 <<EOF
$0: unable to guess system type
diff --git a/config.sub b/config.sub
index 5b8736823d..7ffe373784 100755
--- a/config.sub
+++ b/config.sub
@@ -1,38 +1,31 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# Copyright 1992-2014 Free Software Foundation, Inc.
-timestamp='2011-10-08'
+timestamp='2014-12-03'
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file 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
+# This file 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 3 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.
+# 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.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
@@ -75,9 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
-Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -125,13 +116,17 @@ esac
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -154,7 +149,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze)
+ -apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
@@ -223,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
@@ -247,13 +248,16 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
+ | aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
- | be32 | be64 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
| bfin \
- | c4x | clipper \
+ | c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
@@ -261,10 +265,11 @@ case $basic_machine in
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | mcore | mep | metag \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -278,24 +283,27 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
- | nios | nios2 \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | open8 \
- | or32 \
+ | open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | rx \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
@@ -305,6 +313,7 @@ case $basic_machine in
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
@@ -319,8 +328,10 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | picochip)
- # Motorola 68HC11/12.
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -333,7 +344,10 @@ case $basic_machine in
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
-
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
xscaleeb)
basic_machine=armeb-unknown
;;
@@ -356,15 +370,16 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
+ | aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
- | clipper-* | craynv-* | cydra-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
@@ -373,11 +388,13 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -391,23 +408,27 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
+ | or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* | rx-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
@@ -420,6 +441,7 @@ case $basic_machine in
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
+ | visium-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@@ -719,7 +741,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -758,6 +779,9 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
@@ -777,11 +801,15 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
- microblaze)
+ microblaze*)
basic_machine=microblaze-xilinx
;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
mingw32)
- basic_machine=i386-pc
+ basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
@@ -809,6 +837,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -816,6 +848,10 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
mvs)
basic_machine=i370-ibm
os=-mvs
@@ -1004,7 +1040,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
- rdos)
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -1331,29 +1371,29 @@ case $os in
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* \
+ | -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1477,9 +1517,6 @@ case $os in
-aros*)
os=-aros
;;
- -kaos*)
- os=-kaos
- ;;
-zvmoe)
os=-zvmoe
;;
@@ -1528,6 +1565,12 @@ case $basic_machine in
c4x-* | tic4x-*)
os=-coff
;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
tic54x-*)
os=-coff
;;
@@ -1555,9 +1598,6 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
diff --git a/configure b/configure
index 5264e32410..eba1ebcb32 100755
--- a/configure
+++ b/configure
@@ -822,9 +822,9 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
- --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gph,
- iphone, linuxmoto, maemo, n64, null, openpandora, ps2,
- psp, samsungtv, sdl, webos, wii, wince) [sdl]
+ --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gcw0,
+ gph, iphone, linuxmoto, maemo, n64, null, openpandora,
+ ps2, psp, samsungtv, sdl, webos, wii, wince) [sdl]
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -859,6 +859,7 @@ Special configuration feature:
dreamcast for Sega Dreamcast
ds for Nintendo DS
gamecube for Nintendo GameCube
+ gcw0 for GCW Zero
gp2x for GP2X
gp2xwiz for GP2X Wiz
iphone for Apple iPhone
@@ -1298,7 +1299,7 @@ caanoo)
_host_cpu=arm
_host_alias=arm-none-linux-gnueabi
;;
-dingux)
+dingux | gcw0)
_host_os=linux
_host_cpu=mipsel
_host_alias=mipsel-linux
@@ -2588,6 +2589,25 @@ if test -n "$_host"; then
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
add_line_to_config_h "#define USE_WII_DI"
;;
+ gcw0)
+ DEFINES="$DEFINES -DDINGUX -DGCW0"
+ DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE"
+ ASFLAGS="$ASFLAGS"
+ CXXFLAGS="$CXXFLAGS -mips32"
+ _backend="dingux"
+ _mt32emu=no
+ _optimization_level=-O3
+ # Disable alsa midi to get the port build on OpenDingux toolchain
+ _alsa=no
+ _vkeybd=yes
+ _build_hq_scalers=no
+ _keymapper=yes
+ # Force disable vorbis on dingux, it has terrible performance compared to tremor
+ _vorbis=no
+ # Force disable seq on dingux, no way to use it and it would get enabled by default with configure
+ _seq_midi=no
+ _port_mk="backends/platform/dingux/dingux.mk"
+ ;;
gp2x)
DEFINES="$DEFINES -DGP2X"
CXXFLAGS="$CXXFLAGS -march=armv4t"
@@ -2743,6 +2763,9 @@ if test -n "$_host"; then
_port_mk="backends/platform/openpandora/op-bundle.mk"
;;
ppc-amigaos)
+ # PPC Linker requires this to fix relocation errors
+ CXXFLAGS="$CXXFLAGS -mlongcall"
+
# Only static builds link successfully on buildbot
LDFLAGS=`echo $LDFLAGS | sed 's/-use-dynld//'`
LDFLAGS="$LDFLAGS -static"
diff --git a/devtools/create_translations/po_parser.cpp b/devtools/create_translations/po_parser.cpp
index 7882502ca4..ecc3ba540c 100644
--- a/devtools/create_translations/po_parser.cpp
+++ b/devtools/create_translations/po_parser.cpp
@@ -332,6 +332,13 @@ PoMessageEntryList *parsePoFile(const char *file, PoMessageList& messages) {
strcat(currentBuf, stripLine(line));
}
}
+ if (currentBuf == msgstrBuf) {
+ // add last entry
+ if (*msgstrBuf != '\0' && !fuzzy) {
+ messages.insert(msgidBuf);
+ list->addMessageEntry(msgstrBuf, msgidBuf, msgctxtBuf);
+ }
+ }
fclose(inFile);
return list;
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 0960011802..1c2ece80ed 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -786,6 +786,7 @@ begin_credits("Credits");
begin_section("Wintermute");
add_person("Einar Johan T. S&oslash;m&aring;en", "somaen", "");
+ add_person("Tobia Tesan", "t0by", "");
end_section();
begin_section("ZVision");
@@ -1205,7 +1206,7 @@ begin_credits("Credits");
add_person("Ivan Dubrov", "", "For contributing the initial version of the Gobliiins engine");
add_person("Henrik Engqvist", "qvist", "For generously providing hosting for our buildbot, SVN repository, planet and doxygen sites as well as tons of HD space");
add_person("DOSBox Team", "", "For their awesome OPL2 and OPL3 emulator");
- add_person("Yusuke Kamiyamane", "", "For contributing some GUI icons ");
+ add_person("Yusuke Kamiyamane", "", "For contributing some GUI icons");
add_person("Till Kresslein", "Krest", "For design of modern ScummVM GUI");
add_person("", "Jezar", "For his freeverb filter implementation");
add_person("Jim Leiterman", "", "Various info on his FM-TOWNS/Marty SCUMM ports");
@@ -1266,7 +1267,7 @@ begin_credits("Credits");
add_paragraph(
"Janusz Wi&#347;niewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon ".
- "for providing full source code for So&#322;tys and letting us redistribute the game.");
+ "for providing full source code for So&#322;tys and Sfinx and letting us redistribute the games.");
add_paragraph(
"Jan Nedoma for providing the sources to the Wintermute-engine, and for his ".
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt
index f0cb577237..62925e98fa 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -21,9 +21,6 @@
# - Source
# -> The source of the information, useful in case it has to be verified
#
-# TODO: We really should have a separate target for "Misc FM-TOWNS demos", so
-# that their description in the launcher doesn't start with "Zak McKracken"
-#
#
# Table of email addresse of contributors: Sometimes we need to add new
# information to this table, or need to verify the correctness of an
@@ -55,6 +52,7 @@
maniac Maniac Mansion
2d624d1b214f7faf0094daea65c6d1a6 -1 en 2gs Apple II - -
+ 2cb46375dd5cdfd023e2f07e0a21b530 -1 en C64 C64 Demo - Robert Crossfield
eea4d9ac2fb6f145945a308e8866915b -1 en C64 C64 - -
439a7f4adf510489981ac52308e7d7a2 -1 de C64 C64 - -
@@ -483,9 +481,9 @@ fbpack Fatty Bear's Fun Pack
freddi Freddi Fish 1: The Case of the Missing Kelp Seeds
d4cccb5af88f3e77f370896e9ba8c5f9 -1 All Windows HE 71 - - sev
- c0039ad982999c92d0de81910d640fa0 -1 nl Windows HE 71 - - adutchguy
+ c0039ad982999c92d0de81910d640fa0 26159 nl Windows HE 71 - - adutchguy
68530d2e15f339fbbf3150b78b4d2ffb -1 en Mac HE 73 - - satz
- 6d1baa1065ac5f7b210be8ebe4235e49 -1 nl Mac HE 73 - - daniel9
+ 6d1baa1065ac5f7b210be8ebe4235e49 26384 nl Mac HE 73 - - daniel9
c782fbbe74a987c3df8ac73cd3e289ed -1 se Mac HE 73 - - Torbjörn Andersson
5ebb57234b2fe5c5dff641e00184ad81 -1 fr Windows HE 73 - - gist974
cf8ef3a1fb483c5c4b1c584d1167b2c4 -1 de Windows HE 73 - - Oncer
@@ -516,7 +514,7 @@ freddi Freddi Fish 1: The Case of the Missing Kelp Seeds
freddi2 Freddi Fish 2: The Case of the Haunted Schoolhouse
0a295b80f9a9edf818e8e161a0e83830 -1 fr All HE 80 - - gist974, ThierryFR
fce4b8010704b103acfeea9413788f32 -1 de All HE 80 - - Joachim Eberhard
- 8e9830a6f2702be5b22c8fa0a6aaf977 -1 nl Mac HE 80 - - daniel9
+ 8e9830a6f2702be5b22c8fa0a6aaf977 65305 nl All HE 80 - - daniel9
5057fb0e99e5aa29df1836329232f101 -1 All Windows HE 80 - - sev
ac62d50e39492ee3738b4e83a5ac780f -1 nl Windows HE 80 - - joostp
151071053a1d0021198216713939521d -1 en Windows HE 80 - - vampir_raziel
@@ -564,7 +562,11 @@ freddi4 Freddi Fish 4: The Case of the Hogfish Rustlers of Briny Gulch
fa84cb1018103a4ee4e5fa8041c1d0d1 13609 de Windows - Demo - George Kormendi
ebd324dcf06a4c49e1ba5c231eee1060 -1 us All HE 99 Demo - sev
688328c5bdc4c8ec4145688dfa077bf2 -1 de All HE 99 Demo - Joachim Eberhard
- 03d3b18ee3fd68114e2a687c871e38d5 -1 us Windows HE 99 Mini Game - eriktorbjorn
+ 03d3b18ee3fd68114e2a687c871e38d5 13609 us Windows HE 99 Mini Game - eriktorbjorn
+ 9340b552b0f2dffe6d4f3d13ebebe832 13609 nl Windows HE 99 Mini Game - Ben Castricum
+ c486e4cfa7bd6f8efcd0740f96f7dde3 13609 fr Windows HE 99 Mini Game - Ben Castricum
+ 7a2b6d8e8a645c9d534c8c4edc38a9c9 13609 it Windows HE 99 Mini Game - Ben Castricum
+ 09b0be55c16cd9e88b5080bf89ff281d 13609 de Windows HE 99 Mini Game - Ben Castricum
16effd200aa6b8abe9c569c3e578814d -1 nl All HE 99 Demo - joostp
499c958affc394f2a3868f1eb568c3ee -1 nl All HE 99 Demo - adutchguy
5fdb2ac2483908b065c6e77988338a54 -1 nl Windows HE 99 Demo - Ben
@@ -577,6 +579,7 @@ freddicove Freddi Fish 5: The Case of the Creature of Coral Cove
590e6546aacd0d374b7f3a4f53013ab1 -1 All All - - - cyx
21abe302e1b1e2b66d6f5c12e241ebfd -1 ru Windows unenc Unencrypted - sev
b8955d7d23b4972229060d1592489fef -1 nl All HE 100 - - adutchguy, daniel9
+ 8f345db2f3f5a25ed6305001957e6f72 41182 nl All HE 100 - - Ben Castricum
b100abf7ff83146df50db78dbd5e9cfa -1 fr All HE 100 - - alamaz, gist974
4ce2d5b355964bbcb5e5ce73236ef868 -1 ru Windows HE 100 - - sev
@@ -624,9 +627,11 @@ farm Let's Explore the Farm with Buzzy
a5c5388da9bf0e6662fdca8813a79d13 86962 en Windows - - - George Kormendi
a85856675429fe88051744f755b72f93 -1 en Windows - - - Kirben
a2386da005672cbd5136f4f27a626c5f 87061 nl Windows - - - George Kormendi
+ eeb606c2d2ec877a712a9f20c10bcdda 87034 nl Mac - - - Ben Castricum
5dda73606533d66a4c3f4f9ea6e842af 87061 ru Windows - - - sev
39fd6db10d0222d817025c4d3346e3b4 -1 en Mac - Demo - Joachim Eberhard
+ 6c375c2236d99f56e6c2cf540e74e474 34333 nl Windows - Demo - Kirben
bf8b52fdd9a69c67f34e8e9fec72661c -1 en Windows HE 71 Demo - khalek, sev
0557df19f046a84c2fdc63507c6616cb -1 nl Windows HE 72 Demo - adutchguy
8d479e36f35e80257dfc102cf4b8a912 34333 en Windows HE 72 Demo - khalek, sev
@@ -678,7 +683,7 @@ pajama3 Pajama Sam 3: You Are What You Eat From Your Head to Your Feet
f7711f9264d4d43c2a1518ec7c10a607 79382 us All - - - Kirben
2e8a1f76ea33bc5e04347646feee173d -1 de All - - - Joachim Eberhard
aefa244ea034b7cd2041f0a44be7d9ba -1 en Mac - - - pix_climber
- 06c3cf4f31daad8b1cd93153491db9e6 -1 nl Mac - - - daniel9
+ 06c3cf4f31daad8b1cd93153491db9e6 79382 nl All - - - daniel9
7410a8ba9795020cd42f171c4320659e -1 fr Windows - - - gist974
20176076d708bf14407bcc9bdcd7a418 -1 ru Windows - - - sev
@@ -686,7 +691,11 @@ pajama3 Pajama Sam 3: You Are What You Eat From Your Head to Your Feet
a654fb60c3b67d6317a7894ffd9f25c5 -1 us All - Demo - sev
a9f2f04b1ecaab9495b59befffe9bf88 -1 us All - Demo - sev
0c45eb4baff0c12c3d9dfa889c8070ab 13884 de All - Demo - Joachim Eberhard
- 4fe6a2e8df3c4536b278fdd2fbcb181e -1 en Windows - Mini Game - Trekky
+ 4fe6a2e8df3c4536b278fdd2fbcb181e 13911 en Windows - Mini Game - Trekky
+ 24942a4200d99bdb4bdb78f9c7e07027 13911 nl Windows - Mini Game - Ben Castricum
+ faa89ab5e67ba4eebb4399f584f7490c 13911 fr Windows - Mini Game - Ben Castricum
+ d1a73e87564477c7c2dcc2b8f616ad0b 13911 it Windows - Mini Game - Ben Castricum
+ a8fcc3084ad5e3e569722755f205b1ef 13911 de Windows - Mini Game - Ben Castricum
679855cf61932f9bf995c8f3677380ed -1 fr Windows - Demo - Mevi
c8c5baadcbfc8d0372ed4335abace8a7 -1 fr Windows - Demo - Mevi
784b499c98d07260a30952685758636b 13911 de Windows - Demo - George Kormendi
@@ -723,6 +732,7 @@ puttrace Putt-Putt Enters the Race
62050da376483d8edcbd98cd26b6cb57 -1 ru Windows HE 99 - - sev
0ac41e2e3d2174e5a042a6b565328dba 13110 us All HE 98 Demo - sev
+ ee8cfeb76e55d43a01c25e0865a9db76 13135 nl Mac HE 98 Demo - Ben Castricum
6af2419fe3db5c2fdb091ae4e5833770 -1 nl All HE 98.5 Demo - Kirben
663743c03ae0c007f3d665cf631c0e6b 13135 de All HE 99 Demo - Joachim Eberhard
aaa587701cde7e74692c68c1024b85eb -1 nl All HE 99 Demo - joostp
@@ -812,7 +822,10 @@ PuttTime Putt-Putt Travels Through Time
59d5cfcc5e672a6e07baae01328b918b -1 fr All HE 90 Demo - Kirben
fbb697d89d2beca87360a145f467bdae -1 de All HE 90 Demo - Joachim Eberhard
6b19d0e25cbf720d05822379b8b90ed9 -1 nl All HE 90 Demo - adutchguy
- 0a6d7b81b850ed4a77811c60c9b5c555 -1 us Windows HE 99 Mini Game - eriktorbjorn
+ 0a6d7b81b850ed4a77811c60c9b5c555 18458 us Windows HE 99 Mini Game - eriktorbjorn
+ a71014c53a6d18c66ef2ea0ee42328e9 18458 nl Windows HE 99 Mini Game - Ben Castricum
+ 8dd4d590685c19bf651b5016e749ead2 18458 fr Windows HE 99 Mini Game - Ben Castricum
+ aef415cc5dc063e3668359c2657169f3 18458 de Windows HE 99 Mini Game - Ben Castricum
0ab19be9e2a3f6938226638b2a3744fe -1 us All HE 100 Demo - khalek
balloon Putt-Putt and Pep's Balloon-O-Rama
@@ -820,7 +833,7 @@ balloon Putt-Putt and Pep's Balloon-O-Rama
bab0fb81dcb12b8930c5d850b8f2a7de 12800 de Windows HE 80 - - George Kormendi
145bd3373574feb668cc2eea2ec6cf86 -1 ru Windows HE 80 - - sev
27b2ef1653089fe5b897d9cc89ce784f -1 ru Windows HE 80 - - George Kormendi
- 2232b0b9411575b1f9961713ebc9de61 -1 All Windows HE 80 - ES and NL exiltd (ES), Ben Castricum (NL)
+ 2232b0b9411575b1f9961713ebc9de61 -1 nl Windows HE 80 - - Ben Castricum
a22af0ad0e3126d19d22707b0267a37d -1 nl Windows HE 80 - - Ben Castricum
a56a05c6b865b9956639f8c51269e5ab -1 nl Mac HE 80 - - Ben Castricum
d7b247c26bf1f01f8f7daf142be84de3 -1 en Windows HE 99 Updated - iziku
@@ -876,12 +889,16 @@ spyfox2 SPY Fox 2: Some Assembly Required
bc4700bc0e12879f6d25d14d6be6cfdd -1 de All - - - Joachim Eberhard
cea91e3dd47f2518ea418e41611aa77f -1 ru All - - - sev
9fd66fb3b04703bd50da4356e4202558 51295 en Mac - - - pix_climber
- 71fe97c3108678cf604f14abe342341b -1 nl Windows - - - adutchguy
+ 71fe97c3108678cf604f14abe342341b 51286 nl All - - - adutchguy
1c792d28376d45e145cb916bca0400a2 -1 nl All - Demo - joostp
7222f260253f325c21fcfa68b5bfab67 -1 us All - Demo - Kirben
732845548b1d6c2da572cb6a1bf81b07 -1 de All - Demo - Joachim Eberhard
- e62056ba675ad65d8854ab3c5ad4b3c0 -1 en Windows - Mini Game - Trekky
+ e62056ba675ad65d8854ab3c5ad4b3c0 14689 en Windows - Mini Game - Trekky
+ 22c7432dc97a821fcfccd480e93e3911 14689 nl Windows - Mini Game - Ben Castricum
+ 6b10c9977cad9de503642059359792b1 14689 fr Windows - Mini Game - Ben Castricum
+ 9684c161258d68e0d464d6cab7024b9c 14689 it Windows - Mini Game - Ben Castricum
+ 7f2578d8d33a9ff525488a2d9ba617e4 14689 de Windows - Mini Game - Ben Castricum
22de86b2f7ec6e5db745ed1123310b44 15832 fr Windows - Demo - George Kormendi
204453e33456c4faa26e276229fe5b76 14689 de Windows - Demo - George Kormendi
19bf6938a94698296bcb0c99c31c91a7 -1 gb Windows - Demo - eriktorbjorn
diff --git a/dists/gcw0/default.gcw0.desktop b/dists/gcw0/default.gcw0.desktop
new file mode 100644
index 0000000000..46bd2be092
--- /dev/null
+++ b/dists/gcw0/default.gcw0.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Name=ScummVM
+Comment=Interpreter for several adventure games
+Comment[pl]=Interpreter graficznych gier przygodowych
+Comment[sv]=Tolk för flera äventyrsspel
+Comment[he]=פרשן למספר משחקי הרפתק×ות
+Comment[de]=Interpreter für diverse Abenteuerspiele
+Comment[es]=Intérprete para varias aventuras gráficas
+Comment[ca]=Intèrpret per diverses aventures gràfiques
+Exec=scummvm.sh
+Icon=scummvm
+Terminal=false
+Type=Application
+Categories=games
+StartupNotify=false
+X-OD-Manual=README
diff --git a/dists/gcw0/opk_make.sh b/dists/gcw0/opk_make.sh
new file mode 100755
index 0000000000..b1bfd03efb
--- /dev/null
+++ b/dists/gcw0/opk_make.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+#
+# opk_make.sh
+#
+# This script is meant to ease generation of a opk file. Please consult the output
+# when running --help for a list of available parameters and an explaination of
+# those.
+#
+# Required tools when running the script:
+# bash
+# echo, cat, mv, rm, mksquashfs
+
+check_for_tool()
+{
+ which $1 &> /dev/null
+ if [ "$?" -ne "0" ];
+ then
+ cecho "ERROR: Could not find the program '$1'. Please make sure
+that it is available in your PATH since it is required to complete your request." $red
+ exit 1
+ fi
+}
+
+print_help()
+{
+ cat << EOSTREAM
+opk_make.sh - A script to package "something" into a OPK.
+
+Usage:
+ $(basename ${0}) {--directory|-d} <folder> {--opk|-o} <file> [{--help|-h}]
+
+
+Switches:
+ --directory / -d Sets the folder that is to be used for the resulting opk
+ to <folder>. This option is mandatory for the script to
+ function correctly.
+
+ --help / -h Displays this help text.
+
+ --opkname / -o Sets the output filename of the resulting opk to <file>.
+ This option is mandatory for the script to function
+ correctly.
+
+A version >=4.0 of squashfs is required to be available in your PATH.
+EOSTREAM
+}
+
+
+# Parse command line parameters
+while [ "${1}" != "" ]; do
+ if [ "${1}" = "--directory" ] || [ "${1}" = "-d" ];
+ then
+ FOLDER=$2
+ shift 2
+ elif [ "${1}" = "--help" ] || [ "${1}" = "-h" ];
+ then
+ print_help
+ exit 0
+ elif [ "${1}" = "--opkname" ] || [ "${1}" = "-o" ];
+ then
+ OPKNAME=$2
+ shift 2
+ else
+ echo "ERROR: '$1' is not a known argument. Printing --help and aborting."
+ print_help
+ exit 1
+ fi
+done
+
+
+# Probe if required variables were set
+echo "Checking if all required variables were set."
+if [ ! $OPKNAME ] || [ ! $FOLDER ];
+then
+ echo "ERROR: Not all required options were set! Please see the --help information below."
+ print_help
+ exit 1
+else
+ echo "OPKNAME set to '$OPKNAME'."
+fi
+# Check if the selected folder actually exists
+if [ ! -d $FOLDER ];
+then
+ echo "ERROR: '$FOLDER' doesn't exist or is not a folder."
+ exit 1
+else
+ echo "FOLDER set to '$FOLDER'."
+fi
+
+# Make iso from folder
+echo "Creating an iso file based on '$FOLDER'."
+
+check_for_tool mksquashfs
+if [ $(mksquashfs -version | awk 'BEGIN{r=0} $3>=4{r=1} END{print r}') -eq 0 ];
+then
+ echo "ERROR: Your squashfs version is older then version 4, please upgrade to 4.0 or later"
+ exit 1
+fi
+mksquashfs $FOLDER $OPKNAME.opk -noappend -no-exports -no-xattrs
+
+# Final message
+if [ -f $OPKNAME ];
+then
+ echo "Successfully finished creating the opk '$OPKNAME'."
+else
+ echo "There seems to have been a problem and '$OPKNAME' was not created. Please check
+the output above for any error messages. A possible cause for this is that there was
+not enough space available."
+ exit 1
+fi
+
diff --git a/dists/gcw0/scummvm.png b/dists/gcw0/scummvm.png
new file mode 100644
index 0000000000..128e59efc4
--- /dev/null
+++ b/dists/gcw0/scummvm.png
Binary files differ
diff --git a/dists/gcw0/scummvm.sh b/dists/gcw0/scummvm.sh
new file mode 100755
index 0000000000..c12a3030cc
--- /dev/null
+++ b/dists/gcw0/scummvm.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+cd `dirname $0`
+
+if [ ! -f $HOME/.scummvmrc ] ; then
+ cp ./scummvmrc $HOME/.scummvmrc
+fi
+
+exec ./scummvm
diff --git a/dists/gcw0/scummvmrc b/dists/gcw0/scummvmrc
new file mode 100644
index 0000000000..c2087c222a
--- /dev/null
+++ b/dists/gcw0/scummvmrc
@@ -0,0 +1,9 @@
+[scummvm]
+fullscreen=true
+gfx_mode=1x
+aspect_ratio=true
+themepath=./themes
+browser_lastpath=/media
+extrapath=./engine-data
+pluginspath=./plugins
+joystick_num=0
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 6bdbabd33e..1e663ec29a 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -492,14 +492,10 @@ struct GameSettings {
const char *detectname;
};
-static const GameSettings agiSettings[] = {
- {"agi", "AGI game", GID_AGI, MDT_ADLIB, "OBJECT"},
- {NULL, NULL, 0, 0, NULL}
-};
-
AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
// Assign default values to the config manager, in case settings are missing
ConfMan.registerDefault("originalsaveload", "false");
+ ConfMan.registerDefault("altamigapalette", "false");
_noSaveLoadAllowed = false;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 1d58900056..e7285d8112 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -145,6 +145,13 @@ static const ExtraGuiOption agiExtraGuiOption = {
false
};
+static const ExtraGuiOption agiExtraGuiOptionAmiga = {
+ _s("Use an alternative palette"),
+ _s("Use an alternative palette, common for all Amiga games. This was the old behavior"),
+ "altamigapalette",
+ false
+};
+
#include "agi/detection_tables.h"
using namespace Agi;
@@ -230,6 +237,8 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
const ExtraGuiOptions AgiMetaEngine::getExtraGuiOptions(const Common::String &target) const {
ExtraGuiOptions options;
options.push_back(agiExtraGuiOption);
+ if (target.contains("-amiga"))
+ options.push_back(agiExtraGuiOptionAmiga);
return options;
}
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 34651c70b2..2b1bd8c829 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/config-manager.h"
#include "common/file.h"
#include "common/textconsole.h"
@@ -220,7 +221,7 @@ static const uint8 amigaAgiPaletteV3[16 * 3] = {
/**
* 16 color amiga-ish palette.
*/
-static const uint8 newPalette[16 * 3] = {
+static const uint8 altAmigaPalette[16 * 3] = {
0x00, 0x00, 0x00,
0x00, 0x00, 0x3f,
0x00, 0x2A, 0x00,
@@ -904,6 +905,7 @@ static const byte sciMouseCursor[] = {
0,0,0,0,0,0,1,2,2,1,0
};
+#if 0
/**
* A black and white Apple IIGS style arrow cursor (9x11).
* 0 = Transparent.
@@ -923,6 +925,7 @@ static const byte appleIIgsMouseCursor[] = {
2,2,2,0,2,1,1,2,0,
0,0,0,0,0,2,2,2,0
};
+#endif
/**
* RGB-palette for the black and white SCI and Apple IIGS arrow cursors.
@@ -1030,8 +1033,22 @@ int GfxMgr::initVideo() {
initPalette(vgaPalette, 256, 8);
else if (_vm->_renderMode == Common::kRenderEGA)
initPalette(egaPalette);
- else
- initPalette(newPalette);
+ else if (_vm->_renderMode == Common::kRenderAmiga) {
+ if (!ConfMan.getBool("altamigapalette")) {
+ // Set the correct Amiga palette
+ if (_vm->getVersion() < 0x2936)
+ // TODO: This palette isn't used for Apple IIGS games yet, as
+ // we don't set a separate render mode for them yet
+ initPalette(amigaAgiPaletteV1, 16, 4);
+ else if (_vm->getVersion() == 0x2936)
+ initPalette(amigaAgiPaletteV2, 16, 4);
+ else if (_vm->getVersion() > 0x2936)
+ initPalette(amigaAgiPaletteV3, 16, 4);
+ } else
+ // Set the old common alternative Amiga palette
+ initPalette(altAmigaPalette);
+ } else
+ error("initVideo: Unhandled render mode");
if ((_agiScreen = (uint8 *)calloc(GFX_WIDTH, GFX_HEIGHT)) == NULL)
return errNotEnoughMemory;
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index 4ca8d00824..a1572d7f1f 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -892,6 +892,7 @@ void MickeyEngine::drawRoom() {
drawRoomAnimation();
}
+#if 0
const uint8 colorBCG[16][2] = {
{ 0x00, 0x00 }, // 0 (black, black)
{ 0, 0 },
@@ -910,6 +911,7 @@ const uint8 colorBCG[16][2] = {
{ 0, 0 },
{ 0xFF, 0xFF } // F (white, white)
};
+#endif
void MickeyEngine::drawLogo() {
// TODO: clean this up and make it work properly, the logo is drawn way off to the right
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index 77fc88c6bb..2f4709c49e 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -1259,6 +1259,32 @@ static const AGOSGameDescription gameDescriptions[] = {
GF_TALKIE | GF_OLD_BUNDLE | GF_PLANAR
},
+ // Simon the Sorcerer 1 - English Amiga CD32 demo, from the cover disc of
+ // issue 5 (October 1994) of Amiga CD32 Gamer
+ {
+ {
+ "simon1",
+ "CD32 Demo",
+
+ {
+ { "gameamiga", GAME_BASEFILE, "e243f9229f9728b3476e54d2cf5f18a1", 27998},
+ { "icon.pkd", GAME_ICONFILE, "565ef7a98dcc21ef526a2bb10b6f42ed", 18979},
+ { "stripped.txt", GAME_STRFILE, "94413c71c86c32ed9baaa1c74a151cb3", 243},
+ { "tbllist", GAME_TBLFILE, "f9d5bf2ce09f82289c791c3ca26e1e4b", 696},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_CD | ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOMIDI)
+ },
+
+ GType_SIMON1,
+ GID_SIMON1CD32,
+ GF_TALKIE | GF_OLD_BUNDLE | GF_PLANAR
+ },
+
+
// Simon the Sorcerer 1 - English DOS Floppy Demo
{
{
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 33145b7d0d..5a1f9f1917 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -547,7 +547,7 @@ void AGOSEngine_Simon1::drawMaskedImage(VC10_state *state) {
if ((dst[count * 2] & 0xF0) == 0x20)
dst[count * 2] = src[count * 2];
if (mask[count + state->x_skip] & 0x0F)
- if ((dst[count * 2 + 1] & 0x0F) == 0x20)
+ if ((dst[count * 2 + 1] & 0xF0) == 0x20)
dst[count * 2 + 1] = src[count * 2 + 1];
} else {
/* no transparency */
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index 8a4e87017a..687a8ef1cf 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -460,7 +460,7 @@ void AGOSEngine_Simon1::handleMouseWheelUp() {
_saveLoadEdit = false;
listSaveGames();
}
- } else {
+ } else {
AGOSEngine::handleMouseWheelUp();
}
}
@@ -472,11 +472,11 @@ void AGOSEngine_Simon1::handleMouseWheelDown() {
_saveLoadRowCurPos += 1;
if (_saveLoadRowCurPos >= _numSaveGameRows)
_saveLoadRowCurPos = _numSaveGameRows;
-
+
_saveLoadEdit = false;
listSaveGames();
}
- } else {
+ } else {
AGOSEngine::handleMouseWheelDown();
}
}
@@ -492,7 +492,7 @@ void AGOSEngine_Elvira2::handleMouseWheelUp() {
_saveLoadRowCurPos -= 3;
listSaveGames();
- } else {
+ } else {
AGOSEngine::handleMouseWheelUp();
}
}
@@ -506,7 +506,7 @@ void AGOSEngine_Elvira2::handleMouseWheelDown() {
_saveLoadRowCurPos = 1;
listSaveGames();
- } else {
+ } else {
AGOSEngine::handleMouseWheelDown();
}
}
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index c26fbe3331..045fd9dac5 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -52,7 +52,7 @@ MidiPlayer::MidiPlayer() {
_paused = false;
_currentTrack = 255;
- _loopTrack = 0;
+ _loopTrackDefault = false;
_queuedTrack = 255;
_loopQueuedTrack = 0;
}
@@ -166,13 +166,13 @@ void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
return;
} else if (_current == &_sfx) {
clearConstructs(_sfx);
- } else if (_loopTrack) {
+ } else if (_current->loopTrack) {
_current->parser->jumpToTick(0);
} else if (_queuedTrack != 255) {
_currentTrack = 255;
byte destination = _queuedTrack;
_queuedTrack = 255;
- _loopTrack = _loopQueuedTrack;
+ _current->loopTrack = _loopQueuedTrack;
_loopQueuedTrack = false;
// Remember, we're still inside the locked mutex.
@@ -300,7 +300,7 @@ void MidiPlayer::setVolume(int musicVol, int sfxVol) {
void MidiPlayer::setLoop(bool loop) {
Common::StackLock lock(_mutex);
- _loopTrack = loop;
+ _loopTrackDefault = loop;
}
void MidiPlayer::queueTrack(int track, bool loop) {
@@ -405,7 +405,7 @@ void MidiPlayer::loadSMF(Common::File *in, int song, bool sfx) {
uint32 timerRate = _driver->getBaseTempo();
- if (!memcmp(p->data, "GMF\x1", 4)) {
+ if (isGMF) {
// The GMF header
// 3 BYTES: 'GMF'
// 1 BYTE : Major version
@@ -426,11 +426,9 @@ void MidiPlayer::loadSMF(Common::File *in, int song, bool sfx) {
// It seems that 4 corresponds to our base tempo, so
// this should be the right way to calculate it.
timerRate = (4 * _driver->getBaseTempo()) / p->data[5];
-
- // According to bug #1004919 calling setLoop() from
- // within a lock causes a lockup, though I have no
- // idea when this actually happens.
- _loopTrack = (p->data[6] != 0);
+ p->loopTrack = (p->data[6] != 0);
+ } else {
+ p->loopTrack = _loopTrackDefault;
}
MidiParser *parser = MidiParser::createParser_SMF();
@@ -500,6 +498,8 @@ void MidiPlayer::loadMultipleSMF(Common::File *in, bool sfx) {
p->song_sizes[i] = size;
}
+ p->loopTrack = _loopTrackDefault;
+
if (!sfx) {
_currentTrack = 255;
resetVolumeTable();
@@ -531,6 +531,7 @@ void MidiPlayer::loadXMIDI(Common::File *in, bool sfx) {
in->seek(pos, 0);
p->data = (byte *)calloc(size, 1);
in->read(p->data, size);
+ p->loopTrack = _loopTrackDefault;
} else {
error("Expected 'FORM' tag but found '%c%c%c%c' instead", buf[0], buf[1], buf[2], buf[3]);
}
@@ -575,6 +576,7 @@ void MidiPlayer::loadS1D(Common::File *in, bool sfx) {
_currentTrack = 255;
resetVolumeTable();
}
+ p->loopTrack = _loopTrackDefault;
p->parser = parser; // That plugs the power cord into the wall
}
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index 3efadddc2f..398e445535 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -36,6 +36,7 @@ namespace AGOS {
struct MusicInfo {
MidiParser *parser;
byte *data;
+ bool loopTrack;
byte num_songs; // For Type 1 SMF resources
byte *songs[16]; // For Type 1 SMF resources
uint32 song_sizes[16]; // For Type 1 SMF resources
@@ -46,6 +47,7 @@ struct MusicInfo {
MusicInfo() { clear(); }
void clear() {
parser = 0; data = 0; num_songs = 0;
+ loopTrack = false;
memset(songs, 0, sizeof(songs));
memset(song_sizes, 0, sizeof(song_sizes));
memset(channel, 0, sizeof(channel));
@@ -71,7 +73,7 @@ protected:
// These are only used for music.
byte _currentTrack;
- bool _loopTrack;
+ bool _loopTrackDefault;
byte _queuedTrack;
bool _loopQueuedTrack;
diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index d2e13e525c..11e4b6cea7 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -60,7 +60,7 @@ static const BBPoint kInventorySlotPositions[] = {
{135, 93}, {134, 145}, { 96, 224}, {128, 224}, {160, 224},
{192, 224}, {224, 224}, {240, 224}, {256, 224}, { 0, 0}
};
-
+
static const BBRect kVerbRects[6] = {
{-32, -2, 19, 27}, {-33, -33, 19, 27}, { 12, -2, 19, 27},
{ 13, -33, 19, 27}, {-10, 8, 19, 27}, {-11, -49, 19, 27}
@@ -77,7 +77,7 @@ bool WalkArea::contains(const Common::Point &pt) const {
BbvsEngine::BbvsEngine(OSystem *syst, const ADGameDescription *gd) :
Engine(syst), _gameDescription(gd) {
-
+
_random = new Common::RandomSource("bbvs");
_currActionCommandIndex = -1;
_buttheadObject = nullptr;
@@ -148,14 +148,14 @@ Common::Error BbvsEngine::run() {
_gameModule = new GameModule();
_spriteModule = new SpriteModule();
_sound = new SoundMan();
-
+
allocSnapshot();
memset(_easterEggInput, 0, sizeof(_easterEggInput));
-
+
_gameTicks = 0;
_playVideoNumber = 0;
_bootSaveSlot = -1;
-
+
memset(_inventoryItemStatus, 0, sizeof(_inventoryItemStatus));
memset(_gameVars, 0, sizeof(_gameVars));
memset(_sceneVisited, 0, sizeof(_sceneVisited));
@@ -189,7 +189,7 @@ Common::Error BbvsEngine::run() {
_playVideoNumber = 0;
}
}
-
+
writeContinueSavegame();
freeSnapshot();
@@ -282,20 +282,20 @@ void BbvsEngine::updateGame() {
inputTicks = 1;
_gameTicks = _system->getMillis();
}
-
+
if (inputTicks > 20) {
inputTicks = 20;
_gameTicks = _system->getMillis();
}
-
+
if (inputTicks == 0)
return;
-
+
if (_mouseX >= 320 || _mouseY >= 240) {
_mouseY = -1;
_mouseX = -1;
}
-
+
bool done;
do {
@@ -304,14 +304,14 @@ void BbvsEngine::updateGame() {
_mouseButtons &= ~kRightButtonClicked;
_keyCode = Common::KEYCODE_INVALID;
} while (--inputTicks && _playVideoNumber == 0 && _gameTicks > 0 && !done);
-
+
if (!done && _playVideoNumber == 0 && _gameTicks > 0) {
DrawList drawList;
buildDrawList(drawList);
_screen->drawDrawList(drawList, _spriteModule);
drawScreen();
}
-
+
_system->delayMillis(10);
}
@@ -329,7 +329,7 @@ void BbvsEngine::updateBackgroundSounds() {
_backgroundSoundsActive[i] = 0;
}
}
-}
+}
bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCode keyCode) {
@@ -339,7 +339,7 @@ bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCo
_bootSaveSlot = -1;
return false;
}
-
+
if (_newSceneNum != 0) {
_gameTicks = 0;
return changeScene();
@@ -413,7 +413,7 @@ bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCo
}
updateInventory(mouseButtons & kLeftButtonClicked);
break;
-
+
case kGSVerbs:
_isSaveAllowed = false;
updateVerbs();
@@ -426,7 +426,7 @@ bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCo
}
}
break;
-
+
case kGSWait:
case kGSWaitDialog:
_isSaveAllowed = false;
@@ -438,14 +438,14 @@ bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCo
else
updateCommon();
break;
-
+
case kGSDialog:
_isSaveAllowed = true;
saveSnapshot();
updateDialog(mouseButtons & kLeftButtonClicked);
updateCommon();
break;
-
+
}
return true;
@@ -503,7 +503,7 @@ void BbvsEngine::buildDrawList(DrawList &drawList) {
// Verbs background
drawList.add(_gameModule->getGuiSpriteIndex(13), _verbPos.x - _cameraPos.x,
_verbPos.y - _cameraPos.y, 500);
- // Selected inventory item
+ // Selected inventory item
if (_currInventoryItem >= 0) {
drawList.add(_gameModule->getInventoryItemSpriteIndex(2 * _currInventoryItem), _verbPos.x - _cameraPos.x,
_verbPos.y - _cameraPos.y + 27, 500);
@@ -538,7 +538,7 @@ void BbvsEngine::updateVerbs() {
_mouseCursorSpriteIndex = 0;
return;
}
-
+
for (int i = 0; i < 6; ++i) {
const BBRect &verbRect = kVerbRects[i];
const int16 x = _verbPos.x + verbRect.x;
@@ -551,7 +551,7 @@ void BbvsEngine::updateVerbs() {
break;
}
}
-
+
switch (_currVerbNum) {
case kVerbLook:
case kVerbUse:
@@ -585,7 +585,7 @@ void BbvsEngine::updateDialog(bool clicked) {
_gameState = kGSScene;
return;
}
-
+
int slotX = (_mousePos.x - _cameraPos.x) / 32;
if (slotX >= _dialogSlotCount) {
@@ -597,7 +597,7 @@ void BbvsEngine::updateDialog(bool clicked) {
_mouseCursorSpriteIndex = _gameModule->getGuiSpriteIndex(5);
_activeItemType = kITDialog;
-
+
// Find the selected dialog item index
for (int i = 0; i < 50 && slotX >= 0; ++i) {
if (_dialogItemStatus[i]) {
@@ -605,7 +605,7 @@ void BbvsEngine::updateDialog(bool clicked) {
_activeItemIndex = i;
}
}
-
+
// Select the dialog item action if it was clicked
if (clicked) {
for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
@@ -622,7 +622,7 @@ void BbvsEngine::updateDialog(bool clicked) {
}
void BbvsEngine::updateInventory(bool clicked) {
-
+
Common::Rect kInvButtonRects[3] = {
Common::Rect(97, 13, 97 + 20, 13 + 26),
Common::Rect(135, 15, 135 + 46, 15 + 25),
@@ -636,10 +636,10 @@ void BbvsEngine::updateInventory(bool clicked) {
if (_currVerbNum != kVerbLook && _currVerbNum != kVerbUse && _currVerbNum != kVerbInvItem)
_currVerbNum = kVerbUse;
-
+
const int16 mx = _mousePos.x - _cameraPos.x;
const int16 my = _mousePos.y - _cameraPos.y;
-
+
// Check inventory exit left/right edge of screen
if (mx < 40 || mx > 280) {
_mouseCursorSpriteIndex = _gameModule->getGuiSpriteIndex(10);
@@ -652,7 +652,7 @@ void BbvsEngine::updateInventory(bool clicked) {
return;
}
- // Check hovered/clicked inventory button
+ // Check hovered/clicked inventory button
_inventoryButtonIndex = -1;
if (kInvButtonRects[0].contains(mx, my)) {
_inventoryButtonIndex = 0;
@@ -677,10 +677,10 @@ void BbvsEngine::updateInventory(bool clicked) {
// Find hovered/clicked inventory item
int currItem = -1;
-
+
if (_currVerbNum == kVerbInvItem)
currItem = _currInventoryItem;
-
+
_activeItemType = kITEmpty;
for (int i = 0; i < 50; ++i) {
@@ -769,7 +769,7 @@ void BbvsEngine::updateScene(bool clicked) {
}
}
}
-
+
for (int i = 0; i < _gameModule->getBgObjectsCount(); ++i) {
BgObject *bgObject = _gameModule->getBgObject(i);
if (lastPriority <= bgObject->rect.bottom && bgObject->rect.contains(_mousePos)) {
@@ -921,7 +921,7 @@ bool BbvsEngine::performActionCommand(ActionCommand *actionCommand) {
return false;
case kActionCmdWalkObject:
- {
+ {
SceneObject *sceneObject = &_sceneObjects[actionCommand->sceneObjectIndex];
debug(5, "[%s] walks from (%d, %d) to (%d, %d)", sceneObject->sceneObjectDef->name,
sceneObject->x >> 16, sceneObject->y >> 16, actionCommand->walkDest.x, actionCommand->walkDest.y);
@@ -998,14 +998,14 @@ bool BbvsEngine::performActionCommand(ActionCommand *actionCommand) {
bool BbvsEngine::processCurrAction() {
bool actionsFinished = false;
-
+
if (_sceneObjectActions.size() == 0) {
-
+
for (uint i = 0; i < _currAction->actionCommands.size(); ++i) {
ActionCommand *actionCommand = &_currAction->actionCommands[i];
if (actionCommand->timeStamp != 0)
break;
-
+
if (actionCommand->cmd == kActionCmdMoveObject || actionCommand->cmd == kActionCmdAnimObject) {
SceneObjectAction *sceneObjectAction = 0;
// See if there's already an entry for the SceneObject
@@ -1027,14 +1027,14 @@ bool BbvsEngine::processCurrAction() {
sceneObjectAction->animationIndex = actionCommand->param;
}
}
-
+
if (actionCommand->cmd == kActionCmdSetCameraPos) {
_currCameraNum = actionCommand->param;
_newCameraPos = _gameModule->getCameraInit(actionCommand->param)->cameraPos;
}
}
-
+
// Delete entries for SceneObjects without anim
for (uint i = 0; i < _sceneObjectActions.size();) {
if (!_sceneObjects[_sceneObjectActions[i].sceneObjectIndex].anim)
@@ -1107,7 +1107,7 @@ void BbvsEngine::updateCommon() {
if (doActionCommands) {
ActionCommand *actionCommand = &_currAction->actionCommands[_currActionCommandIndex];
-
+
while (actionCommand->timeStamp == _currActionCommandTimeStamp &&
_currActionCommandIndex < (int)_currAction->actionCommands.size()) {
if (!performActionCommand(actionCommand)) {
@@ -1161,7 +1161,7 @@ void BbvsEngine::updateCommon() {
}
updateWalkObject(sceneObject);
}
-
+
if (sceneObject->walkCount > 0 && sceneObject->turnCount == 0) {
debug(5, "walk step, xIncr: %d, yIncr: %d", sceneObject->xIncr, sceneObject->yIncr);
sceneObject->x += sceneObject->xIncr;
@@ -1226,7 +1226,7 @@ void BbvsEngine::updateCommon() {
}
}
}
-
+
if (_cameraPos.x < _newCameraPos.x)
++_cameraPos.x;
if (_cameraPos.x > _newCameraPos.x)
@@ -1235,7 +1235,7 @@ void BbvsEngine::updateCommon() {
++_cameraPos.y;
if (_cameraPos.y > _newCameraPos.y)
--_cameraPos.y;
-
+
// Check if Butthead is inside a scene exit
if (_newSceneNum == 0 && !_currAction && _buttheadObject) {
int16 buttheadX = _buttheadObject->x >> 16;
@@ -1314,13 +1314,13 @@ void BbvsEngine::stopSounds() {
bool BbvsEngine::runMinigame(int minigameNum) {
debug(0, "BbvsEngine::runMinigame() minigameNum: %d", minigameNum);
-
+
bool fromMainGame = _currSceneNum != kMainMenu;
-
+
_sound->unloadSounds();
-
+
Minigame *minigame = 0;
-
+
switch (minigameNum) {
case kMinigameBbLoogie:
minigame = new MinigameBbLoogie(this);
@@ -1338,9 +1338,9 @@ bool BbvsEngine::runMinigame(int minigameNum) {
error("Incorrect minigame number %d", minigameNum);
break;
}
-
+
bool minigameResult = minigame->run(fromMainGame);
-
+
delete minigame;
// Check if the principal was hit with a megaloogie in the loogie minigame
@@ -1370,11 +1370,11 @@ void BbvsEngine::checkEasterEgg(char key) {
"SKCUS",
"NAMTAH"
};
-
+
static const int kEasterEggLengths[] = {
7, 5, 5, 6
};
-
+
if (_currSceneNum == kCredits) {
memcpy(&_easterEggInput[1], &_easterEggInput[0], 6);
_easterEggInput[0] = key;
diff --git a/engines/bbvs/bbvs.h b/engines/bbvs/bbvs.h
index 6a9a13905c..bbd8046a8b 100644
--- a/engines/bbvs/bbvs.h
+++ b/engines/bbvs/bbvs.h
@@ -149,7 +149,7 @@ struct BBPoint {
struct BBRect {
int16 x, y, width, height;
-};
+};
struct BBPolygon {
const BBPoint *points;
@@ -229,66 +229,66 @@ public:
private:
const ADGameDescription *_gameDescription;
Graphics::PixelFormat _pixelFormat;
-public:
+public:
Common::RandomSource *_random;
-
+
GameModule *_gameModule;
SpriteModule *_spriteModule;
SoundMan *_sound;
-
+
Screen *_screen;
-
+
int _bootSaveSlot;
-
+
int _mouseX, _mouseY;
uint _mouseButtons;
Common::KeyCode _keyCode;
-
+
int _mouseCursorSpriteIndex;
int _gameState;
int _gameTicks;
-
+
Common::Point _mousePos;
Common::Point _verbPos;
Common::Point _walkMousePos;
-
+
int _activeItemType;
int _activeItemIndex;
int _currTalkObjectIndex;
-
+
Common::Point _cameraPos, _newCameraPos;
-
+
int _newSceneNum, _prevSceneNum, _currSceneNum;
int _playVideoNumber;
-
+
int _dialogSlotCount;
byte _dialogItemStatus[kDialogItemStatusCount];
-
+
byte _gameVars[kGameVarsCount];
byte _sceneVisited[kSceneVisitedCount];
int _currVerbNum;
-
+
int _currInventoryItem;
byte _inventoryItemStatus[kInventoryItemStatusCount];
int _inventoryButtonIndex;
-
+
Action *_currAction;
uint32 _currActionCommandTimeStamp;
int _currActionCommandIndex;
-
+
Common::Array<Action*> _walkAreaActions;
-
+
SceneObject _sceneObjects[kSceneObjectsCount];
Common::Array<SceneObjectAction> _sceneObjectActions;
-
+
SceneObject *_buttheadObject, *_beavisObject;
int _currCameraNum;
-
+
byte _backgroundSoundsActive[kSceneSoundsCount];
Audio::SoundHandle _speechSoundHandle;
-
+
int _walkAreasCount;
WalkArea _walkAreas[80];
int _walkInfosCount;
@@ -298,40 +298,40 @@ public:
Common::Rect _tempWalkableRects1[256];
Common::Rect _tempWalkableRects2[256];
WalkInfo *_walkInfoPtrs[256];
-
+
WalkArea *_sourceWalkArea, *_destWalkArea;
Common::Point _sourceWalkAreaPt, _destWalkAreaPt, _finalWalkPt;
int _currWalkDistance;
bool _walkReachedDestArea;
-
+
bool _hasSnapshot;
byte *_snapshot;
Common::SeekableMemoryWriteStream *_snapshotStream;
-
+
char _easterEggInput[7];
-
+
void updateEvents();
int getRandom(int max);
void drawDebugInfo();
void drawScreen();
-
+
void updateGame();
bool evalCondition(Conditions &conditions);
bool evalCameraCondition(Conditions &conditions, int value);
int evalDialogCondition(Conditions &conditions);
void evalActionResults(ActionResults &results);
-
+
void updateBackgroundSounds();
void loadScene(int sceneNum);
void initScene(bool sounds);
- bool changeScene();
+ bool changeScene();
bool update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCode keyCode);
-
+
void buildDrawList(DrawList &drawList);
-
+
void updateVerbs();
void updateDialog(bool clicked);
void updateInventory(bool clicked);
@@ -342,7 +342,7 @@ public:
void skipCurrAction();
void updateCommon();
-
+
void updateWalkableRects();
void startWalkObject(SceneObject *sceneObject);
void updateWalkObject(SceneObject *sceneObject);
@@ -360,20 +360,20 @@ public:
void walkFindPath(WalkArea *sourceWalkArea, int infoCount);
int calcDistance(const Common::Point &pt1, const Common::Point &pt2);
void walkFoundPath(int count);
-
+
void updateSceneObjectsTurnValue();
void updateDialogConditions();
-
- void playSpeech(int soundNum);
+
+ void playSpeech(int soundNum);
void stopSpeech();
-
+
void playSound(uint soundNum, bool loop = false);
void stopSound(uint soundNum);
void stopSounds();
-
+
bool runMinigame(int minigameNum);
void playVideo(int videoNum);
-
+
void runMainMenu();
void checkEasterEgg(char key);
@@ -409,13 +409,13 @@ public:
bool existsSavegame(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
-
+
void allocSnapshot();
void freeSnapshot();
void saveSnapshot();
-
+
void writeContinueSavegame();
-
+
};
} // End of namespace Bbvs
diff --git a/engines/bbvs/detection.cpp b/engines/bbvs/detection.cpp
index e7383163f5..3e247aad99 100644
--- a/engines/bbvs/detection.cpp
+++ b/engines/bbvs/detection.cpp
@@ -133,7 +133,7 @@ SaveStateDescriptor BbvsMetaEngine::querySaveMetaInfos(const char *target, int s
Bbvs::BbvsEngine::kReadSaveHeaderError error;
error = Bbvs::BbvsEngine::readSaveHeader(in, true, header);
delete in;
- if (error == Bbvs::BbvsEngine::kRSHENoError) {
+ if (error == Bbvs::BbvsEngine::kRSHENoError) {
SaveStateDescriptor desc(slot, header.description);
// Slot 0 is used for the "Continue" save
desc.setDeletableFlag(slot != 0);
diff --git a/engines/bbvs/dialogs.cpp b/engines/bbvs/dialogs.cpp
index 5247a58ec8..af95f06c1e 100644
--- a/engines/bbvs/dialogs.cpp
+++ b/engines/bbvs/dialogs.cpp
@@ -34,7 +34,7 @@ struct MenuButton {
static const MenuButton kMenuButtons[] = {
// Main menu
- {"New Game", kCmdNewGame},
+ {"New Game", kCmdNewGame},
{"Continue", kCmdContinue},
{"Options", kCmdOptions},
{"Mini Games", kCmdMiniGames},
@@ -61,7 +61,7 @@ MainMenu::~MainMenu() {
}
void MainMenu::init() {
- _buttons[0] = new GUI::ButtonWidget(this, 0, 0, 1, 1, "", 0, 0);
+ _buttons[0] = new GUI::ButtonWidget(this, 0, 0, 1, 1, "", 0, 0);
_buttons[1] = new GUI::ButtonWidget(this, 0, 0, 1, 1, "", 0, 0);
_buttons[2] = new GUI::ButtonWidget(this, 0, 0, 1, 1, "", 0, 0);
_buttons[3] = new GUI::ButtonWidget(this, 0, 0, 1, 1, "", 0, 0);
@@ -76,14 +76,14 @@ void MainMenu::reflowLayout() {
const int buttonWidth = screenW * 70 / 320;
const int buttonHeight = screenH * 14 / 240;
const int buttonPadding = screenW * 3 / 320;
-
+
_w = 2 * buttonWidth + buttonPadding;
_h = 3 * buttonHeight + 3 * buttonPadding;
_x = (screenW - _w) / 2;
_y = screenH - _h;
int x = 0, y = 0;
-
+
x = 0;
y = 0;
_buttons[0]->resize(x, y, buttonWidth, buttonHeight);
diff --git a/engines/bbvs/dialogs.h b/engines/bbvs/dialogs.h
index 2dce2a110b..7db0b182b7 100644
--- a/engines/bbvs/dialogs.h
+++ b/engines/bbvs/dialogs.h
@@ -67,13 +67,13 @@ protected:
BbvsEngine *_vm;
void init();
-
+
GUI::ButtonWidget *_buttons[5];
-
+
void gotoMenuScreen(int index);
bool canContinue();
void gotoScene(int sceneNum);
-
+
};
}
diff --git a/engines/bbvs/gamemodule.cpp b/engines/bbvs/gamemodule.cpp
index d6343084ab..80f0e81450 100644
--- a/engines/bbvs/gamemodule.cpp
+++ b/engines/bbvs/gamemodule.cpp
@@ -39,11 +39,11 @@ GameModule::~GameModule() {
void GameModule::load(const char *filename) {
debug(0, "GameModule::load()");
-
+
unload();
Common::File fd;
-
+
if (!fd.open(filename))
error("GameModule::load() Could not open %s", filename);
@@ -68,7 +68,7 @@ void GameModule::load(const char *filename) {
fd.seek(0x1A8);
_buttheadObjectIndex = fd.readUint32LE();
-
+
fd.close();
debug(0, "GameModule::load() OK");
@@ -177,7 +177,7 @@ int GameModule::getBgSpritePriority(int index) {
int GameModule::getSceneSoundsCount() {
return _sceneSoundsCount;
}
-
+
SceneSound *GameModule::getSceneSound(int index) {
assert(index < _sceneSoundsCount);
return &_sceneSounds[index];
@@ -257,7 +257,7 @@ void GameModule::unload() {
void GameModule::loadBgSprites(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadBgSprites()");
-
+
s.seek(0x14);
_bgSpriteCount = s.readUint32LE();
uint32 bgSpriteIndicesOffs = s.readUint32LE();
@@ -275,7 +275,7 @@ void GameModule::loadBgSprites(Common::SeekableReadStream &s) {
void GameModule::loadCameraInits(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadCameraInits()");
-
+
s.seek(0x20);
for (int i = 0; i < kCameraInitsCount; ++i) {
CameraInit &cameraInit = _cameraInits[i];
@@ -283,13 +283,13 @@ void GameModule::loadCameraInits(Common::SeekableReadStream &s) {
for (int j = 0; j < 8; ++j)
cameraInit.cameraLinks[j] = s.readByte();
for (int j = 0; j < 8; ++j)
- cameraInit.rects[j] = readRect(s);
+ cameraInit.rects[j] = readRect(s);
}
}
void GameModule::loadWalkRects(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadWalkRects()");
-
+
s.seek(0x150);
_walkRectsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -301,7 +301,7 @@ void GameModule::loadWalkRects(Common::SeekableReadStream &s) {
void GameModule::loadSceneExits(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadSceneExits()");
-
+
s.seek(0x158);
_sceneExitsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -329,13 +329,13 @@ void GameModule::loadBgObjects(Common::SeekableReadStream &s) {
void GameModule::loadAnimations(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadAnimations()");
-
+
s.seek(0x168);
_animationsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
_animations = new Animation[_animationsCount];
for (int i = 0; i < _animationsCount; ++i) {
- Animation &anim = _animations[i];
+ Animation &anim = _animations[i];
s.seek(offs + i * 20);
anim.frameCount = s.readUint32LE();
uint32 frameSpriteIndicesOffs = s.readUint32LE();
@@ -363,7 +363,7 @@ void GameModule::loadAnimations(Common::SeekableReadStream &s) {
void GameModule::loadSceneObjectDefs(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadSceneObjectDefs()");
-
+
s.seek(0x170);
_sceneObjectDefsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -379,7 +379,7 @@ void GameModule::loadSceneObjectDefs(Common::SeekableReadStream &s) {
void GameModule::loadSceneObjectInits(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadSceneObjectInits()");
-
+
s.seek(0x178);
_sceneObjectInitsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -396,7 +396,7 @@ void GameModule::loadSceneObjectInits(Common::SeekableReadStream &s) {
void GameModule::loadActions(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadActions()");
-
+
s.seek(0x180);
_actionsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -427,7 +427,7 @@ void GameModule::loadActions(Common::SeekableReadStream &s) {
void GameModule::loadGuiSpriteIndices(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadGuiSpriteIndices()");
-
+
s.seek(0x188);
uint32 offs = s.readUint32LE();
s.seek(offs);
@@ -437,7 +437,7 @@ void GameModule::loadGuiSpriteIndices(Common::SeekableReadStream &s) {
void GameModule::loadInventoryItemSpriteIndices(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadInventoryItemSpriteIndices()");
-
+
s.seek(0x18C);
uint32 offs = s.readUint32LE();
s.seek(offs);
@@ -447,7 +447,7 @@ void GameModule::loadInventoryItemSpriteIndices(Common::SeekableReadStream &s) {
void GameModule::loadInventoryItemInfos(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadInventoryItemInfos()");
-
+
s.seek(0x190);
uint32 offs = s.readUint32LE();
s.seek(offs);
@@ -462,7 +462,7 @@ void GameModule::loadInventoryItemInfos(Common::SeekableReadStream &s) {
void GameModule::loadDialogItemSpriteIndices(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadDialogItemSpriteIndices()");
-
+
s.seek(0x194);
uint32 offs = s.readUint32LE();
s.seek(offs);
@@ -473,7 +473,7 @@ void GameModule::loadDialogItemSpriteIndices(Common::SeekableReadStream &s) {
void GameModule::loadSceneSounds(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadSceneSounds()");
-
+
s.seek(0x1A0);
_sceneSoundsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
@@ -487,7 +487,7 @@ void GameModule::loadSceneSounds(Common::SeekableReadStream &s) {
void GameModule::loadPreloadSounds(Common::SeekableReadStream &s) {
debug(0, "GameModule::loadPreloadSounds()");
-
+
s.seek(0x198);
_preloadSoundsCount = s.readUint32LE();
uint32 offs = s.readUint32LE();
diff --git a/engines/bbvs/gamemodule.h b/engines/bbvs/gamemodule.h
index 4d4f5b90a1..b31b95dcee 100644
--- a/engines/bbvs/gamemodule.h
+++ b/engines/bbvs/gamemodule.h
@@ -134,29 +134,29 @@ class GameModule {
public:
GameModule();
~GameModule();
-
+
void load(const char *filename);
-
+
int getFieldC();
int getButtheadObjectIndex();
-
+
int getGuiSpriteIndex(int index);
int getInventoryItemSpriteIndex(int index);
int getDialogItemSpriteIndex(int index);
-
+
int getActionsCount();
Action *getAction(int index);
-
+
InventoryItemInfo *getInventoryItemInfo(int index);
CameraInit *getCameraInit(int cameraNum);
-
+
int getSceneExitsCount();
SceneExit *getSceneExit(int index);
-
+
int getWalkRectsCount();
Common::Rect *getWalkRects();
-
+
int getSceneObjectDefsCount();
SceneObjectDef *getSceneObjectDef(int index);
@@ -170,44 +170,44 @@ public:
int getBgSpriteIndex(int index);
int getBgSpritePriority(int index);
- int getSceneSoundsCount();
+ int getSceneSoundsCount();
SceneSound *getSceneSound(int index);
- uint getSceneSoundIndex(uint soundNum);
-
+ uint getSceneSoundIndex(uint soundNum);
+
uint getPreloadSoundsCount();
uint getPreloadSound(uint index);
Animation *getAnimation(int index);
-
+
protected:
-
+
int _bgSpriteCount;
int *_bgSpriteIndices;
int16 *_bgSpritePriorities;
-
+
CameraInit _cameraInits[kCameraInitsCount];
-
+
int _walkRectsCount;
Common::Rect *_walkRects;
-
+
int _sceneExitsCount;
SceneExit *_sceneExits;
-
+
int _bgObjectsCount;
BgObject *_bgObjects;
-
+
int _animationsCount;
Animation *_animations;
-
+
int _sceneObjectDefsCount;
SceneObjectDef *_sceneObjectDefs;
-
+
int _sceneObjectInitsCount;
SceneObjectInit *_sceneObjectInits;
int _actionsCount;
Action *_actions;
-
+
int _sceneSoundsCount;
SceneSound *_sceneSounds;
@@ -218,16 +218,16 @@ protected:
int _inventoryItemSpriteIndices[kInventoryItemSpriteCount];
InventoryItemInfo _inventoryItemInfos[kInventoryItemCount];
int _dialogItemSpriteIndices[kDialogItemSpriteCount];
-
+
int _fieldC;
int _buttheadObjectIndex;
Common::Point readPoint(Common::SeekableReadStream &s);
Common::Rect readRect(Common::SeekableReadStream &s);
Conditions readConditions(Common::SeekableReadStream &s);
-
+
void unload();
-
+
void loadBgSprites(Common::SeekableReadStream &s);
void loadCameraInits(Common::SeekableReadStream &s);
void loadWalkRects(Common::SeekableReadStream &s);
@@ -243,7 +243,7 @@ protected:
void loadDialogItemSpriteIndices(Common::SeekableReadStream &s);
void loadSceneSounds(Common::SeekableReadStream &s);
void loadPreloadSounds(Common::SeekableReadStream &s);
-
+
};
} // End of namespace Bbvs
diff --git a/engines/bbvs/graphics.cpp b/engines/bbvs/graphics.cpp
index 810d910abf..43840607c8 100644
--- a/engines/bbvs/graphics.cpp
+++ b/engines/bbvs/graphics.cpp
@@ -104,9 +104,9 @@ void Screen::drawSprite(Sprite &sprite, int x, int y) {
}
if (destX + width >= _surface->w)
width = _surface->w - destX;
-
+
debug(0, "drawSprite() (%d, %d, %d, %d); skipX: %d; skipY: %d; %d", destX, destY, width, height, skipX, skipY, sprite.type);
-
+
if (sprite.type == 1) {
for (int yc = 0; yc < height; ++yc) {
byte *source = sprite.getRow(skipY + yc);
diff --git a/engines/bbvs/minigames/bbairguitar.cpp b/engines/bbvs/minigames/bbairguitar.cpp
index f2e42313e3..1984dbb0fd 100644
--- a/engines/bbvs/minigames/bbairguitar.cpp
+++ b/engines/bbvs/minigames/bbairguitar.cpp
@@ -198,12 +198,12 @@ void MinigameBbAirGuitar::buildDrawList1(DrawList &drawList) {
if (_trackBarX > kTrackBarMaxX)
_trackBarX = kTrackBarMaxX;
-
+
_trackBarThumbRect.top = 208;
_trackBarThumbRect.bottom = 218;
_trackBarThumbRect.left = _trackBarX;
_trackBarThumbRect.right = _trackBarX + 6;
-
+
drawList.add(_objects[5].anim->frameIndices[0], _trackBarX, 208, 100);
if (_playerMode != 0) {
@@ -228,7 +228,7 @@ void MinigameBbAirGuitar::buildDrawList1(DrawList &drawList) {
drawList.add(_objects[i].anim->frameIndices[frameIndex], kPointsTbl2[i - 47].x, kPointsTbl2[i - 47].y, 254);
}
}
-
+
if (_backgroundSpriteIndex > 0)
drawList.add(_backgroundSpriteIndex, 0, 0, 0);
@@ -394,7 +394,7 @@ void MinigameBbAirGuitar::initObjects1() {
_track[0].noteNum = -1;
stop();
changePatch(0);
-
+
}
bool MinigameBbAirGuitar::updateStatus(int mouseX, int mouseY, uint mouseButtons) {
@@ -408,7 +408,7 @@ bool MinigameBbAirGuitar::updateStatus(int mouseX, int mouseY, uint mouseButtons
}
bool MinigameBbAirGuitar::updateStatus0(int mouseX, int mouseY, uint mouseButtons) {
-
+
if (mouseButtons & kAnyButtonDown) {
stopSound(1);
_rockTunePlaying = false;
@@ -436,14 +436,14 @@ bool MinigameBbAirGuitar::updateStatus0(int mouseX, int mouseY, uint mouseButton
}
}
-
+
return true;
}
bool MinigameBbAirGuitar::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
-
+
int currTicks = _vm->_system->getMillis();
-
+
if (_playerMode == 1 && _track[_trackIndex].ticks <= currTicks - _noteStartTime) {
noteOff(_track[_trackIndex].noteNum);
if (_trackIndex < _trackCount && _track[++_trackIndex].noteNum != -1)
@@ -481,17 +481,17 @@ bool MinigameBbAirGuitar::updateStatus1(int mouseX, int mouseY, uint mouseButton
} else {
++_vuMeterRight2;
}
-
+
if (_resetAnims && _vm->_system->getMillis() - _noteStartTime >= 1000)
resetObjs();
-
+
_objects[0].x = mouseX;
_objects[0].y = mouseY;
-
+
_trackBarMouseX = CLIP(mouseX, kTrackBarMinX, kTrackBarMaxX);
-
+
bool checkClick = false;
-
+
if (mouseButtons & kAnyButtonClicked) {
checkClick = true;
} else if (!(mouseButtons & kAnyButtonDown)) {
@@ -506,14 +506,14 @@ bool MinigameBbAirGuitar::updateStatus1(int mouseX, int mouseY, uint mouseButton
}
} else if (!_movingTrackBar)
checkClick = true;
-
+
if (checkClick) {
afterButtonReleased();
_objects[0].frameIndex = 1;
-
+
if (ptInRect(&kRect2, mouseX, mouseY)) {
-
+
if (_playerMode != 1 && ptInRect(&kPianoRect, mouseX, mouseY)) {
for (int i = 0; i <= 12; ++i) {
if (ptInPoly(&kPianoKeyAreas[i], mouseX, mouseY)) {
@@ -538,7 +538,7 @@ bool MinigameBbAirGuitar::updateStatus1(int mouseX, int mouseY, uint mouseButton
break;
}
}
-
+
if (playerButtonNum >= 0) {
_currButtonNum = playerButtonNum;
_currPlayerButtonRect = &kPlayerButtonRects[playerButtonNum];
@@ -673,12 +673,12 @@ bool MinigameBbAirGuitar::updateStatus1(int mouseX, int mouseY, uint mouseButton
}
}
}
-
+
if (_buttonClickTicks + 1000 < currTicks)
_buttonClickTicks = currTicks;
-
+
int newKind = _buttonClickTicks + 500 < currTicks ? 1 : 0;
-
+
switch (_playerMode) {
case 1:
@@ -770,20 +770,20 @@ bool MinigameBbAirGuitar::run(bool fromMainGame) {
_gameResult = false;
_gameDone = false;
initObjects();
-
+
_spriteModule = new SpriteModule();
_spriteModule->load("bbairg/bbairg.000");
Palette palette = _spriteModule->getPalette();
_vm->_screen->setPalette(palette);
-
+
loadSounds();
-
+
while (!_vm->shouldQuit() &&!_gameDone) {
_vm->updateEvents();
update();
}
-
+
_vm->_sound->unloadSounds();
delete _spriteModule;
@@ -803,15 +803,15 @@ void MinigameBbAirGuitar::update() {
inputTicks = 1;
_gameTicks = _vm->_system->getMillis();
}
-
+
if (_vm->_keyCode == Common::KEYCODE_ESCAPE) {
_gameDone = true;
return;
}
-
+
if (inputTicks == 0)
return;
-
+
bool done;
do {
@@ -820,9 +820,9 @@ void MinigameBbAirGuitar::update() {
_vm->_mouseButtons &= ~kRightButtonClicked;
_vm->_keyCode = Common::KEYCODE_INVALID;
} while (--inputTicks && _gameTicks > 0 && !done);
-
+
drawSprites();
-
+
_vm->_system->delayMillis(10);
}
@@ -1001,7 +1001,7 @@ void MinigameBbAirGuitar::calcTotalTicks1() {
}
void MinigameBbAirGuitar::noteOn(int noteNum) {
-
+
if (_currNoteNum != -2) {
if (noteNum == _currNoteNum)
return;
@@ -1087,7 +1087,7 @@ void MinigameBbAirGuitar::noteOn(int noteNum) {
}
void MinigameBbAirGuitar::noteOff(int noteNum) {
-
+
if (_currNoteNum != noteNum)
return;
diff --git a/engines/bbvs/minigames/bbairguitar.h b/engines/bbvs/minigames/bbairguitar.h
index d4fd6ec30c..40b8a50a03 100644
--- a/engines/bbvs/minigames/bbairguitar.h
+++ b/engines/bbvs/minigames/bbairguitar.h
@@ -32,7 +32,7 @@ public:
MinigameBbAirGuitar(BbvsEngine *vm) : Minigame(vm) {};
bool run(bool fromMainGame);
public:
-
+
struct Obj {
int kind;
int x, y;
@@ -44,24 +44,24 @@ public:
int16 frameIndexAdd;
int16 unk2;
};
-
+
enum {
kMaxObjectsCount = 256,
kMaxTracks = 2049
};
-
+
struct PianoKeyInfo {
int x, y;
int frameIndex;
};
-
+
struct TrackEvt {
int8 noteNum;
int16 ticks;
};
-
+
Obj _objects[kMaxObjectsCount];
-
+
int _playerMode;
bool _modified;
@@ -82,24 +82,24 @@ public:
int *_currFrameIndex;
int _btn3KindToggle;
-
+
const BBPolygon *_currPianoKeyArea;
const Rect *_currPlayerButtonRect;
-
+
bool _movingTrackBar;
int _trackBarMouseX;
int _trackBarX;
Rect _trackBarThumbRect;
-
+
int _currTrackPos, _totalTrackLength;
int _ticksDelta;
-
+
int _actionStartTrackPos, _actionTrackPos;
int _actionStartTime;
int _currNoteNum;
int _currPatchNum;
-
+
const ObjAnimation *getAnimation(int animIndex);
bool ptInRect(const Rect *r, int x, int y);
bool ptInPoly(const BBPolygon *poly, int x, int y);
@@ -109,14 +109,14 @@ public:
void buildDrawList1(DrawList &drawList);
void drawSprites();
-
+
void initObjs();
Obj *getFreeObject();
-
+
void initObjects();
void initObjects0();
void initObjects1();
-
+
bool updateStatus(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus0(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus1(int mouseX, int mouseY, uint mouseButtons);
@@ -124,7 +124,7 @@ public:
void updateObjs();
void update();
-
+
void play();
void record();
void setPlayerMode3();
@@ -136,9 +136,9 @@ public:
void noteOn(int noteNum);
void noteOff(int noteNum);
void resetObjs();
-
+
void loadSounds();
- void playNote(int noteNum);
+ void playNote(int noteNum);
void stopNote(int noteNum);
};
diff --git a/engines/bbvs/minigames/bbant.cpp b/engines/bbvs/minigames/bbant.cpp
index 9786682ada..3678934345 100644
--- a/engines/bbvs/minigames/bbant.cpp
+++ b/engines/bbvs/minigames/bbant.cpp
@@ -94,7 +94,7 @@ void MinigameBbAnt::buildDrawList1(DrawList &drawList) {
drawNumber(drawList, _score, 68, 16);
drawList.add(getAnimation(166)->frameIndices[0], 230, 2, 2000);
drawNumber(drawList, _levelTimeLeft, 280, 16);
-
+
for (int i = 0; i < _stompCount; ++i)
drawList.add(getAnimation(130)->frameIndices[0], 20 + i * 30, 230, 2000);
@@ -116,7 +116,7 @@ void MinigameBbAnt::buildDrawList3(DrawList &drawList) {
drawNumber(drawList, _hiScore, 208, 107);
}
-void MinigameBbAnt::drawMagnifyingGlass(DrawList &drawList) {
+void MinigameBbAnt::drawMagnifyingGlass(DrawList &drawList) {
scale2x(_objects[0].x - 28, _objects[0].y - 27);
drawList.clear();
drawList.add(_objects[0].anim->frameIndices[0], _objects[0].x, _objects[0].y, _objects[0].priority);
@@ -358,7 +358,7 @@ bool MinigameBbAnt::updateStatus0(int mouseX, int mouseY, uint mouseButtons) {
_objects[0].x = 0;
if (_objects[0].y < 0)
_objects[0].y = 0;
-
+
if ((mouseButtons & kLeftButtonDown) || (mouseButtons & kRightButtonDown)) {
_gameState = 1;
initObjects();
@@ -447,7 +447,7 @@ bool MinigameBbAnt::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
int maxKindCount = 0, objKind = 0;
_stompCounter2 = _stompCounter1;
-
+
for (int i = 0; i < 4; ++i)
testTbl[i] = _vm->getRandom(_bugsChanceByKind[i] - _bugsCountByKind[i]);
@@ -471,7 +471,7 @@ bool MinigameBbAnt::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
if (_stompCounter1 > 20)
--_stompCounter1;
}
-
+
return true;
}
@@ -701,7 +701,7 @@ void MinigameBbAnt::updateBugObjAnim(int objIndex) {
void MinigameBbAnt::updateObjAnim2(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
obj->animIndexIncr += _vm->getRandom(3) - 1;
if (obj->animIndexIncr < 0)
obj->animIndexIncr = 7;
@@ -736,7 +736,7 @@ bool MinigameBbAnt::isBugOutOfScreen(int objIndex) {
void MinigameBbAnt::updateObjAnim3(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
obj->animIndexIncr += _vm->getRandom(3) - 1;
if (obj->animIndexIncr < 0)
obj->animIndexIncr = 7;
@@ -752,7 +752,7 @@ void MinigameBbAnt::updateBugObj1(int objIndex) {
Obj *obj = &_objects[objIndex];
bool flag1 = false;
bool flag2 = false;
-
+
if (--obj->ticks == 0) {
++obj->frameIndex;
if (obj->anim->frameCount == obj->frameIndex) {
@@ -911,7 +911,7 @@ void MinigameBbAnt::updateStompObj(int objIndex) {
void MinigameBbAnt::updateSmokeObj(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
obj->x += obj->xIncr;
obj->y += obj->yIncr;
@@ -1047,7 +1047,7 @@ bool MinigameBbAnt::isMagGlassAtBug(int objIndex) {
Obj *obj = &_objects[objIndex];
Obj *obj0 = &_objects[0];
bool result = false;
-
+
if (obj->kind >= 1 && obj->kind <= 5) {
const BBRect &frameRect1 = obj0->anim->frameRects[0];
const int obj1X1 = obj0->x + frameRect1.x;
@@ -1102,7 +1102,7 @@ bool MinigameBbAnt::testObj5(int objIndex) {
}
void MinigameBbAnt::updateObjs(uint mouseButtons) {
-
+
for (int i = 12; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
@@ -1162,7 +1162,7 @@ void MinigameBbAnt::updateObjs(uint mouseButtons) {
}
}
-
+
}
}
@@ -1170,9 +1170,9 @@ void MinigameBbAnt::updateObjs(uint mouseButtons) {
bool MinigameBbAnt::run(bool fromMainGame) {
memset(_objects, 0, sizeof(_objects));
-
+
_numbersAnim = getAnimation(167);
-
+
_backgroundSpriteIndex = 303;
_titleScreenSpriteIndex = 304;
@@ -1187,23 +1187,23 @@ bool MinigameBbAnt::run(bool fromMainGame) {
_gameDone = false;
initObjects();
initVars();
-
+
_spriteModule = new SpriteModule();
_spriteModule->load("bbant/bbant.000");
Palette palette = _spriteModule->getPalette();
_vm->_screen->setPalette(palette);
-
+
loadSounds();
_gameTicks = 0;
playSound(12, true);
-
+
while (!_vm->shouldQuit() &&!_gameDone) {
_vm->updateEvents();
update();
}
-
+
_vm->_sound->unloadSounds();
if (!_fromMainGame)
@@ -1243,19 +1243,19 @@ void MinigameBbAnt::update() {
_vm->_mouseButtons &= ~kRightButtonClicked;
_vm->_keyCode = Common::KEYCODE_INVALID;
} while (--inputTicks && _gameTicks > 0 && !done);
-
+
drawSprites();
-
+
_vm->_system->delayMillis(10);
}
void MinigameBbAnt::scale2x(int x, int y) {
- Graphics::Surface *surface = _vm->_screen->_surface;
-
+ Graphics::Surface *surface = _vm->_screen->_surface;
+
int srcX = x + 14, srcY = y + 14;
int srcW = kScaleDim, srcH = kScaleDim;
-
+
if (srcX < 0) {
srcW += srcX;
srcX = 0;
@@ -1265,21 +1265,21 @@ void MinigameBbAnt::scale2x(int x, int y) {
srcH += srcY;
srcY = 0;
}
-
+
if (srcX + srcW >= 320)
srcW = 320 - srcX - 1;
-
+
if (srcY + srcH >= 240)
srcH = 240 - srcY - 1;
-
+
for (int yc = 0; yc < srcH; ++yc) {
byte *src = (byte*)surface->getBasePtr(srcX, srcY + yc);
memcpy(&_scaleBuf[yc * kScaleDim], src, srcW);
}
-
+
int dstX = x, dstY = y;
int dstW = 2 * kScaleDim, dstH = 2 * kScaleDim;
-
+
if (dstX < 0) {
dstW += dstX;
dstX = 0;
@@ -1289,15 +1289,15 @@ void MinigameBbAnt::scale2x(int x, int y) {
dstH += dstY;
dstY = 0;
}
-
+
if (dstX + dstW >= 320)
dstW = 320 - dstX - 1;
-
+
if (dstY + dstH >= 240)
dstH = 240 - dstY - 1;
-
+
int w = MIN(srcW * 2, dstW), h = MIN(srcH * 2, dstH);
-
+
for (int yc = 0; yc < h; ++yc) {
byte *src = _scaleBuf + kScaleDim * (yc / 2);
byte *dst = (byte*)surface->getBasePtr(dstX, dstY + yc);
diff --git a/engines/bbvs/minigames/bbant.h b/engines/bbvs/minigames/bbant.h
index be2afe688d..88b4af9c71 100644
--- a/engines/bbvs/minigames/bbant.h
+++ b/engines/bbvs/minigames/bbant.h
@@ -32,7 +32,7 @@ public:
MinigameBbAnt(BbvsEngine *vm) : Minigame(vm) {};
bool run(bool fromMainGame);
public:
-
+
struct Obj {
int kind;
int x, y, priority;
@@ -55,21 +55,21 @@ public:
int status2;
int flag;
};
-
+
enum {
kMaxObjectsCount = 256,
kScaleDim = 28
};
-
+
struct ObjInit {
const ObjAnimation *anim1;
const ObjAnimation *anim2;
const ObjAnimation *anim3;
int x, y;
};
-
+
Obj _objects[kMaxObjectsCount];
-
+
int _score, _hiScore;
int _totalBugsCount;
@@ -96,37 +96,37 @@ public:
int _countdown6;
int _countdown5;
int _countdown7;
-
+
byte _scaleBuf[kScaleDim * kScaleDim];
const ObjAnimation *getAnimation(int animIndex);
const ObjInit *getObjInit(int index);
const ObjAnimation * const *getObjKindAnimTable(int kind);
const ObjAnimation *getObjAnim(int index);
-
+
void buildDrawList0(DrawList &drawList);
void buildDrawList1(DrawList &drawList);
void buildDrawList2(DrawList &drawList);
void buildDrawList3(DrawList &drawList);
void drawMagnifyingGlass(DrawList &drawList);
-
+
void drawSprites();
void drawSprites0();
void drawSprites1();
void drawSprites2();
void drawSprites3();
-
+
Obj *getFreeObject();
-
+
void initObjects();
void initObjects0();
void initObjects1();
-
+
void initVars();
void initVars1();
void initVars2();
void initVars3();
-
+
bool updateStatus(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus0(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus1(int mouseX, int mouseY, uint mouseButtons);
@@ -161,7 +161,7 @@ public:
void updateObjs(uint mouseButtons);
void update();
-
+
void scale2x(int x, int y);
void loadSounds();
diff --git a/engines/bbvs/minigames/bbloogie.cpp b/engines/bbvs/minigames/bbloogie.cpp
index 4601e9ff93..68a3147f9a 100644
--- a/engines/bbvs/minigames/bbloogie.cpp
+++ b/engines/bbvs/minigames/bbloogie.cpp
@@ -117,7 +117,7 @@ void MinigameBbLoogie::buildDrawList0(DrawList &drawList) {
}
void MinigameBbLoogie::buildDrawList1(DrawList &drawList) {
-
+
for (int i = 0; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
switch (obj->kind) {
@@ -163,7 +163,7 @@ void MinigameBbLoogie::buildDrawList1(DrawList &drawList) {
}
void MinigameBbLoogie::buildDrawList2(DrawList &drawList) {
-
+
buildDrawList1(drawList);
if (_level > 0 && (_bonusDisplayDelay1 > 0 || _bonusDisplayDelay2 > 0)) {
@@ -180,7 +180,7 @@ void MinigameBbLoogie::buildDrawList2(DrawList &drawList) {
}
void MinigameBbLoogie::buildDrawList3(DrawList &drawList) {
-
+
for (int i = 0; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
if (obj->kind == 2)
@@ -191,7 +191,7 @@ void MinigameBbLoogie::buildDrawList3(DrawList &drawList) {
if (_backgroundSpriteIndex)
drawList.add(_backgroundSpriteIndex, 0, 0, 0);
-
+
drawList.add(getAnimation(10)->frameIndices[0], 230, 2, 2000);
drawNumber(drawList, _levelTimeLeft, 280, 16);
@@ -201,7 +201,7 @@ void MinigameBbLoogie::buildDrawList3(DrawList &drawList) {
int numberX2 = drawNumber(drawList, _currScore, 68, 16);
drawList.add(getAnimation(9)->frameIndices[10], numberX2, 16, 2000);
drawNumber(drawList, _dispLevelScore, numberX2 + 10, 16);
-
+
drawList.add(getAnimation(20)->frameIndices[0], 120, 70, 2000);
drawList.add(getAnimation(13)->frameIndices[0], 95, 95, 2000);
@@ -416,7 +416,7 @@ bool MinigameBbLoogie::updateStatus(int mouseX, int mouseY, uint mouseButtons) {
}
bool MinigameBbLoogie::updateStatus0(int mouseX, int mouseY, uint mouseButtons) {
-
+
_objects[0].x = mouseX;
_objects[0].y = mouseY;
@@ -445,7 +445,7 @@ bool MinigameBbLoogie::updateStatus0(int mouseX, int mouseY, uint mouseButtons)
_objects[4].kind = 0;
_objects[2].kind = 1;
}
-
+
for (int i = 0; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
if (obj->kind == 11) {
@@ -487,12 +487,12 @@ bool MinigameBbLoogie::updateStatus0(int mouseX, int mouseY, uint mouseButtons)
initVars();
_gameTicks = 0;
}
-
+
return true;
}
bool MinigameBbLoogie::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
-
+
if (--_levelTimeDelay == 0) {
_levelTimeDelay = 58;
--_levelTimeLeft;
@@ -568,9 +568,9 @@ bool MinigameBbLoogie::updateStatus2(int mouseX, int mouseY, uint mouseButtons)
}
bool MinigameBbLoogie::updateStatus3(int mouseX, int mouseY, uint mouseButtons) {
-
+
_objects[0].x = mouseX;
-
+
for (int i = 0; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
if (obj->kind == 2) {
@@ -582,7 +582,7 @@ bool MinigameBbLoogie::updateStatus3(int mouseX, int mouseY, uint mouseButtons)
}
}
}
-
+
return true;
}
@@ -620,7 +620,7 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
break;
}
}
-
+
if (--_carDelay == 0) {
// Car
Obj *obj = getFreeObject();
@@ -633,7 +633,7 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
obj->yIncr = 0;
_carDelay = _vm->getRandom(256) + 800;
}
-
+
if (--_bikeDelay == 0) {
// Bike
Obj *obj = getFreeObject();
@@ -646,7 +646,7 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
obj->yIncr = 0;
_bikeDelay = _vm->getRandom(512) + 500;
}
-
+
if (--_squirrelDelay == 0) {
// Squirrel
Obj *obj = getFreeObject();
@@ -662,7 +662,7 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
playSound(9);
_squirrelDelay = _vm->getRandom(512) + 300;
}
-
+
if (--_paperPlaneDelay == 0) {
// Paper plane
Obj *obj = getFreeObject();
@@ -685,7 +685,7 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
}
_paperPlaneDelay = 400;
}
-
+
if (_principalDelay >= 0 && --_principalDelay == 0) {
// Principal
Obj *obj = getFreeObject();
@@ -703,13 +703,13 @@ void MinigameBbLoogie::updateObjs(uint mouseButtons) {
_principalFirstFrameIndex = 11;
_principalLastFrameIndex = 16;
}
-
+
}
void MinigameBbLoogie::updatePlayer(int objIndex, uint mouseButtons) {
Obj *obj = &_objects[0];
-
+
switch (obj->status) {
case 1:
@@ -817,7 +817,7 @@ void MinigameBbLoogie::updateLoogie(int objIndex) {
obj->y -= kLoogieOffY[obj->unk2 / 8];
--obj->unk2;
}
-
+
if (obj->ticks-- == 0) {
obj->ticks = getAnimation(5)->frameTicks[0];
++obj->frameIndex;
@@ -832,9 +832,9 @@ void MinigameBbLoogie::updateLoogie(int objIndex) {
void MinigameBbLoogie::updateCar(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
obj->x += obj->xIncr;
-
+
if (obj->ticks-- == 0) {
if (obj->frameIndex++ == 3 || obj->frameIndex == 6)
obj->frameIndex = 0;
@@ -867,7 +867,7 @@ void MinigameBbLoogie::updateCar(int objIndex) {
void MinigameBbLoogie::updateBike(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
obj->x += obj->xIncr;
if (obj->ticks-- == 0) {
@@ -965,7 +965,7 @@ void MinigameBbLoogie::updatePaperPlane(int objIndex) {
loogieObj = findLoogieObj(loogieObjIndex++);
}
}
-
+
}
void MinigameBbLoogie::updateIndicator(int objIndex) {
@@ -995,7 +995,7 @@ void MinigameBbLoogie::updateIndicator(int objIndex) {
obj->kind = 0;
obj->anim = getAnimation(6);
}
-
+
}
void MinigameBbLoogie::updatePrincipal(int objIndex) {
@@ -1281,22 +1281,22 @@ bool MinigameBbLoogie::run(bool fromMainGame) {
_gameDone = false;
initObjects();
initVars();
-
+
_spriteModule = new SpriteModule();
_spriteModule->load("bbloogie/bbloogie.000");
Palette palette = _spriteModule->getPalette();
_vm->_screen->setPalette(palette);
-
+
loadSounds();
playSound(32, true);
-
+
while (!_vm->shouldQuit() &&!_gameDone) {
_vm->updateEvents();
update();
}
-
+
_vm->_sound->unloadSounds();
if (!_fromMainGame)
@@ -1319,15 +1319,15 @@ void MinigameBbLoogie::update() {
inputTicks = 1;
_gameTicks = _vm->_system->getMillis();
}
-
+
if (_vm->_keyCode == Common::KEYCODE_ESCAPE) {
_gameDone = true;
return;
}
-
+
if (inputTicks == 0)
return;
-
+
bool done;
do {
@@ -1336,9 +1336,9 @@ void MinigameBbLoogie::update() {
_vm->_mouseButtons &= ~kRightButtonClicked;
_vm->_keyCode = Common::KEYCODE_INVALID;
} while (--inputTicks && _gameTicks > 0 && !done);
-
+
drawSprites();
-
+
_vm->_system->delayMillis(10);
}
diff --git a/engines/bbvs/minigames/bbloogie.h b/engines/bbvs/minigames/bbloogie.h
index 1dd4049b41..04ead51a1e 100644
--- a/engines/bbvs/minigames/bbloogie.h
+++ b/engines/bbvs/minigames/bbloogie.h
@@ -32,7 +32,7 @@ public:
MinigameBbLoogie(BbvsEngine *vm) : Minigame(vm) {};
bool run(bool fromMainGame);
public:
-
+
struct Obj {
int kind;
int x, y;
@@ -44,33 +44,33 @@ public:
int16 frameIndexAdd;
int16 unk2;
};
-
+
enum {
kMaxObjectsCount = 256
};
-
+
enum {
kGSTitleScreen = 0, // Title screen
kGSMainGame = 1, // Game when called as part of the main game
kGSStandaloneGame = 2, // Game when called as standalone game
kGSScoreCountUp = 3 // Score countup and next level text
};
-
+
Obj _objects[kMaxObjectsCount];
-
+
int _playerKind;
const ObjAnimation *_playerAnim;
const uint *_playerSounds1, *_playerSounds2;
uint _playerSounds1Count, _playerSounds2Count;
-
+
int _level, _levelTimeLeft, _levelTimeDelay;
- int _numberOfHits, _currScore, _hiScore;
+ int _numberOfHits, _currScore, _hiScore;
int _doubleScore, _megaLoogieCount;
-
+
int _dispLevelScore, _nextLevelScore;
int _timeBonusCtr, _bonusDisplayDelay1, _bonusDisplayDelay2, _bonusDisplayDelay3;
-
+
int _carDelay;
int _bikeDelay;
int _squirrelDelay;
@@ -78,37 +78,37 @@ public:
int _paperPlaneDelay;
int _principalDelay;
- int _prevPrincipalStatus;
+ int _prevPrincipalStatus;
int _principalCtr, _principalFirstFrameIndex, _principalLastFrameIndex;
bool _principalAngry;
-
+
const ObjAnimation *getAnimation(int animIndex);
-
+
void buildDrawList(DrawList &drawList);
void buildDrawList0(DrawList &drawList);
void buildDrawList1(DrawList &drawList);
void buildDrawList2(DrawList &drawList);
void buildDrawList3(DrawList &drawList);
-
+
void drawSprites();
-
+
void initObjs();
Obj *getFreeObject();
Obj *findLoogieObj(int startObjIndex);
bool isHit(Obj *obj1, Obj *obj2);
bool isCursorAtObj(int objIndex);
-
+
void initObjects();
void initObjects0();
void initObjects1();
void initObjects3();
-
+
void initVars();
void initVars0();
void initVars1();
void initVars2();
void initVars3();
-
+
bool updateStatus(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus0(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus1(int mouseX, int mouseY, uint mouseButtons);
@@ -129,7 +129,7 @@ public:
void incNumberOfHits();
void incScore(int incrAmount);
void playRndSound();
-
+
void update();
void loadSounds();
diff --git a/engines/bbvs/minigames/bbtennis.cpp b/engines/bbvs/minigames/bbtennis.cpp
index ddd5cfc804..7763548330 100644
--- a/engines/bbvs/minigames/bbtennis.cpp
+++ b/engines/bbvs/minigames/bbtennis.cpp
@@ -86,7 +86,7 @@ void MinigameBbTennis::buildDrawList(DrawList &drawList) {
}
void MinigameBbTennis::buildDrawList0(DrawList &drawList) {
-
+
drawList.add(_objects[0].anim->frameIndices[_objects[0].frameIndex], _objects[0].x, _objects[0].y, 2000);
for (int i = 0; i < kMaxObjectsCount; ++i) {
@@ -154,7 +154,7 @@ void MinigameBbTennis::buildDrawList1(DrawList &drawList) {
break;
}
-
+
drawList.add(index, x, y, priority);
}
@@ -174,16 +174,16 @@ void MinigameBbTennis::buildDrawList1(DrawList &drawList) {
drawList.add(getAnimation(9)->frameIndices[0], 256, 52, 500);
drawList.add(getAnimation(10)->frameIndices[0], 60, 162, 500);
drawList.add(getAnimation(21)->frameIndices[0], 36, 18, 2000);
-
+
drawNumber(drawList, _score, 70, 18);
-
+
for (int i = 0; i < _numHearts; ++i)
drawList.add(getAnimation(7)->frameIndices[0], 20 + i * 20, 236, 990);
}
void MinigameBbTennis::buildDrawList2(DrawList &drawList) {
-
+
for (int i = 0; i < kMaxObjectsCount; ++i) {
Obj *obj = &_objects[i];
if (obj->kind)
@@ -384,7 +384,7 @@ bool MinigameBbTennis::updateStatus1(int mouseX, int mouseY, uint mouseButtons)
_objects[0].x = mouseX;
_objects[0].y = mouseY;
-
+
if (_allHeartsGone) {
_gameState = 2;
initObjects();
@@ -427,13 +427,13 @@ bool MinigameBbTennis::updateStatus1(int mouseX, int mouseY, uint mouseButtons)
if (_newBallTimer > 0)
--_newBallTimer;
-
+
if (++_delayDecreaseTimer == 30) {
_delayDecreaseTimer = 0;
if (_playerDecrease < 199)
++_playerDecrease;
}
-
+
updateObjs();
if (!_playedThisIsTheCoolest && _score > 3 && _vm->getRandom(10) == 1 && !isAnySoundPlaying(kAllSounds, 11)) {
@@ -482,7 +482,7 @@ void MinigameBbTennis::updateObjs() {
break;
}
}
-
+
if (_rapidFireBallsCount == 0) {
--_squirrelDelay;
if (--_squirrelDelay == 0) {
@@ -763,7 +763,7 @@ void MinigameBbTennis::updateTennisPlayer(int objIndex) {
}
++_tennisPlayerDelay;
break;
-
+
case 2:
if (--obj->ticks == 0) {
++obj->frameIndex;
@@ -1077,7 +1077,7 @@ void MinigameBbTennis::updateNetPlayer(int objIndex) {
void MinigameBbTennis::updateEnemyTennisBall(int objIndex) {
Obj *obj = &_objects[objIndex];
-
+
if (--obj->ticks == 0) {
--obj->frameIndex;
obj->ticks = getAnimation(6)->frameTicks[obj->frameIndex];
@@ -1103,7 +1103,7 @@ void MinigameBbTennis::updateEnemyTennisBall(int objIndex) {
obj->x = (int)obj->fltX;
obj->fltY = obj->fltY - obj->fltStepY;
obj->y = (int)obj->fltY;
-
+
}
void MinigameBbTennis::makeEnemyBall(int x, int y, int frameIndex) {
@@ -1184,7 +1184,7 @@ void MinigameBbTennis::hitSomething() {
bool MinigameBbTennis::run(bool fromMainGame) {
memset(_objects, 0, sizeof(_objects));
-
+
_numbersAnim = getAnimation(20);
_backgroundSpriteIndex = 272;
@@ -1201,23 +1201,23 @@ bool MinigameBbTennis::run(bool fromMainGame) {
_gameDone = false;
initObjects();
initVars();
-
+
_spriteModule = new SpriteModule();
_spriteModule->load("bbtennis/bbtennis.000");
Palette palette = _spriteModule->getPalette();
_vm->_screen->setPalette(palette);
-
+
loadSounds();
_gameTicks = 0;
playSound(29, true);
-
+
while (!_vm->shouldQuit() &&!_gameDone) {
_vm->updateEvents();
update();
}
-
+
_vm->_sound->unloadSounds();
if (!_fromMainGame)
@@ -1240,15 +1240,15 @@ void MinigameBbTennis::update() {
inputTicks = 1;
_gameTicks = _vm->_system->getMillis();
}
-
+
if (_vm->_keyCode == Common::KEYCODE_ESCAPE) {
_gameDone = true;
return;
}
-
+
if (inputTicks == 0)
return;
-
+
bool done;
do {
@@ -1257,9 +1257,9 @@ void MinigameBbTennis::update() {
_vm->_mouseButtons &= ~kRightButtonClicked;
_vm->_keyCode = Common::KEYCODE_INVALID;
} while (--inputTicks && _gameTicks > 0 && !done);
-
+
drawSprites();
-
+
_vm->_system->delayMillis(10);
}
diff --git a/engines/bbvs/minigames/bbtennis.h b/engines/bbvs/minigames/bbtennis.h
index 690bd724a0..7eac904c4d 100644
--- a/engines/bbvs/minigames/bbtennis.h
+++ b/engines/bbvs/minigames/bbtennis.h
@@ -32,7 +32,7 @@ public:
MinigameBbTennis(BbvsEngine *vm) : Minigame(vm) {};
bool run(bool fromMainGame);
public:
-
+
struct Obj {
int kind;
int x, y;
@@ -51,20 +51,20 @@ public:
int ballStepCtr;
int netPlayDirection;
};
-
+
enum {
kMaxObjectsCount = 256
};
-
+
enum {
kGSTitleScreen = 0, // Title screen
kGSMainGame = 1, // Game when called as part of the main game
kGSStandaloneGame = 2, // Game when called as standalone game
kGSScoreCountUp = 3 // Score countup and next level text
};
-
+
Obj _objects[kMaxObjectsCount];
-
+
int _numHearts;
int _squirrelDelay;
int _tennisPlayerDelay;
@@ -85,29 +85,29 @@ public:
bool _endSoundPlaying;
const ObjAnimation *getAnimation(int animIndex);
-
+
void buildDrawList(DrawList &drawList);
void buildDrawList0(DrawList &drawList);
void buildDrawList1(DrawList &drawList);
void buildDrawList2(DrawList &drawList);
-
+
void drawSprites();
-
+
void initObjs();
Obj *getFreeObject();
Obj *findTennisBall(int startObjIndex);
bool isHit(Obj *obj1, Obj *obj2);
-
+
void initObjects();
void initObjects0();
void initObjects1();
void initObjects2();
-
+
void initVars();
void initVars0();
void initVars1();
void initVars2();
-
+
bool updateStatus(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus0(int mouseX, int mouseY, uint mouseButtons);
bool updateStatus1(int mouseX, int mouseY, uint mouseButtons);
diff --git a/engines/bbvs/minigames/minigame.cpp b/engines/bbvs/minigames/minigame.cpp
index aae18072d9..58d98a9df8 100644
--- a/engines/bbvs/minigames/minigame.cpp
+++ b/engines/bbvs/minigames/minigame.cpp
@@ -44,13 +44,13 @@ Minigame::~Minigame() {
int Minigame::drawNumber(DrawList &drawList, int number, int x, int y) {
int digits = 1, rightX = x;
-
+
for (int mag = 10; number / mag != 0; mag *= 10)
++digits;
-
+
rightX = x + digits * 10;
x = rightX;
-
+
while (digits--) {
const int n = number % 10;
x -= 10;
diff --git a/engines/bbvs/minigames/minigame.h b/engines/bbvs/minigames/minigame.h
index 675dec360d..1c24110519 100644
--- a/engines/bbvs/minigames/minigame.h
+++ b/engines/bbvs/minigames/minigame.h
@@ -51,30 +51,30 @@ public:
virtual ~Minigame();
virtual bool run(bool fromMainGame) = 0;
protected:
- BbvsEngine *_vm;
+ BbvsEngine *_vm;
SpriteModule *_spriteModule;
-
+
int _gameState;
int _gameTicks;
bool _gameResult;
bool _gameDone;
bool _fromMainGame;
int _hiScoreTable[kMinigameCount];
-
+
int _backgroundSpriteIndex, _titleScreenSpriteIndex;
-
+
const ObjAnimation *_numbersAnim;
-
+
int drawNumber(DrawList &drawList, int number, int x, int y);
void playSound(uint index, bool loop = false);
void stopSound(uint index);
bool isSoundPlaying(uint index);
bool isAnySoundPlaying(const uint *indices, uint count);
-
+
void saveHiscore(int minigameNum, int score);
int loadHiscore(int minigameNum);
-
+
};
} // End of namespace Bbvs
diff --git a/engines/bbvs/saveload.cpp b/engines/bbvs/saveload.cpp
index ff53cc457b..e7725713fd 100644
--- a/engines/bbvs/saveload.cpp
+++ b/engines/bbvs/saveload.cpp
@@ -73,7 +73,7 @@ void BbvsEngine::savegame(const char *filename, const char *description) {
byte descriptionLen = strlen(description);
out->writeByte(descriptionLen);
out->write(description, descriptionLen);
-
+
Graphics::saveThumbnail(*out);
// Not used yet, reserved for future usage
@@ -86,7 +86,7 @@ void BbvsEngine::savegame(const char *filename, const char *description) {
out->writeUint32LE(saveTime);
out->writeUint32LE(playTime);
// Header end
-
+
out->write(_snapshot, _snapshotStream->pos());
out->finalize();
@@ -103,15 +103,15 @@ void BbvsEngine::loadgame(const char *filename) {
SaveHeader header;
kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
-
+
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
delete in;
return;
}
-
+
g_engine->setTotalPlayTime(header.playTime * 1000);
-
+
memset(_sceneObjects, 0, sizeof(_sceneObjects));
for (int i = 0; i < kSceneObjectsCount; ++i) {
_sceneObjects[i].walkDestPt.x = -1;
@@ -120,7 +120,7 @@ void BbvsEngine::loadgame(const char *filename) {
_currSceneNum = 0;
_newSceneNum = in->readUint32LE();
-
+
initScene(false);
_prevSceneNum = in->readUint32LE();
@@ -157,16 +157,16 @@ void BbvsEngine::loadgame(const char *filename) {
obj->frameIndex = in->readUint32LE();
obj->frameTicks = in->readUint32LE();
obj->walkCount = in->readUint32LE();
- obj->xIncr = in->readUint32LE();
+ obj->xIncr = in->readUint32LE();
obj->yIncr = in->readUint32LE();
- obj->turnValue = in->readUint32LE();
- obj->turnCount = in->readUint32LE();
+ obj->turnValue = in->readUint32LE();
+ obj->turnCount = in->readUint32LE();
obj->turnTicks = in->readUint32LE();
obj->walkDestPt.x = in->readUint16LE();
obj->walkDestPt.y = in->readUint16LE();
obj->anim = obj->animIndex > 0 ? _gameModule->getAnimation(obj->animIndex) : 0;
}
-
+
updateWalkableRects();
// Restart scene background sounds
@@ -259,10 +259,10 @@ void BbvsEngine::saveSnapshot() {
_snapshotStream->writeUint32LE(obj->frameIndex);
_snapshotStream->writeUint32LE(obj->frameTicks);
_snapshotStream->writeUint32LE(obj->walkCount);
- _snapshotStream->writeUint32LE(obj->xIncr);
+ _snapshotStream->writeUint32LE(obj->xIncr);
_snapshotStream->writeUint32LE(obj->yIncr);
- _snapshotStream->writeUint32LE(obj->turnValue);
- _snapshotStream->writeUint32LE(obj->turnCount);
+ _snapshotStream->writeUint32LE(obj->turnValue);
+ _snapshotStream->writeUint32LE(obj->turnCount);
_snapshotStream->writeUint32LE(obj->turnTicks);
_snapshotStream->writeUint16LE(obj->walkDestPt.x);
_snapshotStream->writeUint16LE(obj->walkDestPt.y);
diff --git a/engines/bbvs/scene.cpp b/engines/bbvs/scene.cpp
index 0d86eb4dbc..a89c88fd82 100644
--- a/engines/bbvs/scene.cpp
+++ b/engines/bbvs/scene.cpp
@@ -34,7 +34,7 @@ static const int kAfterVideoSceneNum[] = {
void BbvsEngine::loadScene(int sceneNum) {
debug(0, "BbvsEngine::loadScene() sceneNum: %d", sceneNum);
-
+
Common::String sprFilename = Common::String::format("vnm/vspr%04d.vnm", sceneNum);
Common::String gamFilename = Common::String::format("vnm/game%04d.vnm", sceneNum);
@@ -42,7 +42,7 @@ void BbvsEngine::loadScene(int sceneNum) {
_spriteModule->load(sprFilename.c_str());
_gameModule->load(gamFilename.c_str());
-
+
Palette palette = _spriteModule->getPalette();
_screen->setPalette(palette);
@@ -106,10 +106,10 @@ void BbvsEngine::initScene(bool sounds) {
loadScene(_newSceneNum);
_currSceneNum = _newSceneNum;
_newSceneNum = 0;
-
+
for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i)
_sceneObjects[i].sceneObjectDef = _gameModule->getSceneObjectDef(i);
-
+
for (int i = 0; i < _gameModule->getSceneObjectInitsCount(); ++i) {
SceneObjectInit *soInit = _gameModule->getSceneObjectInit(i);
if (evalCondition(soInit->conditions)) {
@@ -149,10 +149,10 @@ void BbvsEngine::initScene(bool sounds) {
}
}
}
-
+
_cameraPos = _gameModule->getCameraInit(_currCameraNum)->cameraPos;
_newCameraPos = _cameraPos;
-
+
_walkAreaActions.clear();
for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
Action *action = _gameModule->getAction(i);
@@ -165,7 +165,7 @@ void BbvsEngine::initScene(bool sounds) {
_activeItemIndex = 0;
_activeItemType = kITEmpty;
-
+
for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
Action *action = _gameModule->getAction(i);
if (evalCondition(action->conditions)) {
@@ -183,7 +183,7 @@ void BbvsEngine::initScene(bool sounds) {
break;
}
}
-
+
if (sounds)
updateBackgroundSounds();
@@ -192,7 +192,7 @@ void BbvsEngine::initScene(bool sounds) {
bool BbvsEngine::changeScene() {
writeContinueSavegame();
-
+
if (_newSceneNum >= 27 && _newSceneNum <= 30) {
// Run minigames
stopSpeech();
@@ -221,7 +221,7 @@ bool BbvsEngine::changeScene() {
}
return true;
-
+
}
} // End of namespace Bbvs
diff --git a/engines/bbvs/spritemodule.cpp b/engines/bbvs/spritemodule.cpp
index 8eae7f9a6a..f8b0d9afd5 100644
--- a/engines/bbvs/spritemodule.cpp
+++ b/engines/bbvs/spritemodule.cpp
@@ -41,15 +41,15 @@ SpriteModule::~SpriteModule() {
void SpriteModule::load(const char *filename) {
unload();
-
+
Common::File fd;
if (!fd.open(filename))
error("SpriteModule::load() Could not open %s", filename);
-
+
fd.readUint32LE(); // Skip magic
fd.readUint32LE(); // Skip unused
fd.readUint32LE(); // Skip filesize
-
+
_paletteOffs = fd.readUint32LE();
fd.readUint32LE(); // Skip unused flagsTbl1Ofs
fd.readUint32LE(); // Skip unused flagsTbl2Ofs
@@ -57,18 +57,18 @@ void SpriteModule::load(const char *filename) {
_paletteStart = fd.readUint32LE();
_paletteCount = fd.readUint32LE();
_spritesCount = fd.readUint32LE();
-
+
debug(0, "_paletteOffs: %08X", _paletteOffs);
debug(0, "_spriteTblOffs: %08X", _spriteTblOffs);
debug(0, "_paletteStart: %d", _paletteStart);
debug(0, "_paletteCount: %d", _paletteCount);
debug(0, "_spritesCount: %d", _spritesCount);
-
+
_spriteDataSize = fd.size();
_spriteData = new byte[_spriteDataSize];
fd.seek(0);
fd.read(_spriteData, _spriteDataSize);
-
+
// Convert palette
byte *palette = _spriteData + _paletteOffs;
for (int i = 0; i < _paletteCount; ++i) {
diff --git a/engines/bbvs/videoplayer.cpp b/engines/bbvs/videoplayer.cpp
index fda9372ade..9ea73ad10b 100644
--- a/engines/bbvs/videoplayer.cpp
+++ b/engines/bbvs/videoplayer.cpp
@@ -42,7 +42,7 @@ void BbvsEngine::playVideo(int videoNum) {
warning("Couldn't switch to a RGB color video mode to play a video.");
return;
}
-
+
Video::VideoDecoder *videoDecoder = new Video::AVIDecoder();
if (!videoDecoder->loadFile(videoFilename)) {
delete videoDecoder;
@@ -74,7 +74,7 @@ void BbvsEngine::playVideo(int videoNum) {
}
delete videoDecoder;
-
+
initGraphics(320, 240, false);
}
diff --git a/engines/bbvs/walk.cpp b/engines/bbvs/walk.cpp
index 077110b867..5ef14101a0 100644
--- a/engines/bbvs/walk.cpp
+++ b/engines/bbvs/walk.cpp
@@ -46,7 +46,7 @@ static const int8 kWalkAnimTbl[32] = {
void BbvsEngine::startWalkObject(SceneObject *sceneObject) {
if (_buttheadObject != sceneObject && _beavisObject != sceneObject)
return;
-
+
initWalkAreas(sceneObject);
_sourceWalkAreaPt.x = sceneObject->x >> 16;
_sourceWalkAreaPt.y = sceneObject->y >> 16;
@@ -60,7 +60,7 @@ void BbvsEngine::startWalkObject(SceneObject *sceneObject) {
_destWalkArea = getWalkAreaAtPos(_destWalkAreaPt);
if (!_destWalkArea)
return;
-
+
if (_sourceWalkArea != _destWalkArea) {
_currWalkDistance = kMaxDistance;
walkFindPath(_sourceWalkArea, 0);
@@ -68,12 +68,12 @@ void BbvsEngine::startWalkObject(SceneObject *sceneObject) {
}
walkObject(sceneObject, _destWalkAreaPt, sceneObject->sceneObjectDef->walkSpeed);
-
+
}
void BbvsEngine::updateWalkObject(SceneObject *sceneObject) {
int animIndex;
-
+
if (sceneObject->walkCount > 0 && (sceneObject->xIncr != 0 || sceneObject->yIncr != 0)) {
if (ABS(sceneObject->xIncr) <= ABS(sceneObject->yIncr))
sceneObject->turnValue = sceneObject->yIncr >= 0 ? 0 : 4;
@@ -89,7 +89,7 @@ void BbvsEngine::updateWalkObject(SceneObject *sceneObject) {
Animation *anim = 0;
if (animIndex > 0)
anim = _gameModule->getAnimation(animIndex);
-
+
if (sceneObject->anim != anim) {
if (anim) {
sceneObject->anim = anim;
@@ -305,12 +305,12 @@ bool BbvsEngine::canButtheadWalkToDest(const Common::Point &destPt) {
}
void BbvsEngine::canWalkToDest(WalkArea *walkArea, int infoCount) {
-
+
if (_destWalkArea == walkArea) {
_walkReachedDestArea = true;
return;
}
-
+
if (_gameModule->getFieldC() <= 320 || infoCount <= 20) {
walkArea->checked = true;
for (int linkIndex = 0; linkIndex < walkArea->linksCount; ++linkIndex) {
@@ -364,10 +364,10 @@ int BbvsEngine::calcDistance(const Common::Point &pt1, const Common::Point &pt2)
void BbvsEngine::walkFoundPath(int count) {
debug(5, "BbvsEngine::walkFoundPath(%d)", count);
-
+
Common::Point midPt = _sourceWalkAreaPt;
int totalMidPtDistance = 0;
-
+
if (count > 0) {
Common::Point lastMidPt;
int halfCount = (count + 1) >> 1;
@@ -384,13 +384,13 @@ void BbvsEngine::walkFoundPath(int count) {
if (distance >= _currWalkDistance)
return;
-
+
debug(5, "BbvsEngine::walkFoundPath() distance smaller");
_currWalkDistance = distance;
Common::Point destPt = _destWalkAreaPt, newDestPt;
-
+
while (1) {
int index = 0;
@@ -408,7 +408,7 @@ void BbvsEngine::walkFoundPath(int count) {
WalkInfo *walkInfo = _walkInfoPtrs[--count];
destPt.x = walkInfo->x;
destPt.y = walkInfo->y;
-
+
if (walkInfo->direction) {
newDestPt.x = walkInfo->x;
newDestPt.y = walkInfo->y + walkInfo->delta - 1;
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp
index babcb7e667..4d3a103663 100644
--- a/engines/cge/vga13h.cpp
+++ b/engines/cge/vga13h.cpp
@@ -640,7 +640,7 @@ Vga::Vga(CGEEngine *vm) : _frmCnt(0), _msg(NULL), _name(NULL), _setPal(false), _
if (ConfMan.getBool("enable_color_blind"))
_mono = 1;
-
+
_oldColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
_newColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
diff --git a/engines/cge2/cge2.cpp b/engines/cge2/cge2.cpp
index 37d87ba09c..ee62e20ac6 100644
--- a/engines/cge2/cge2.cpp
+++ b/engines/cge2/cge2.cpp
@@ -97,7 +97,7 @@ CGE2Engine::CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription)
_midiNotify = nullptr;
_spriteNotify = nullptr;
_startGameSlot = 0;
-
+
_sayCap = ConfMan.getBool("subtitles");
_sayVox = !ConfMan.getBool("speech_mute");
_muteAll = ConfMan.getBool("mute");
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index 50b418f294..fbe4cb3abc 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -269,7 +269,7 @@ public:
void snRoom(Sprite *spr, bool on);
void snGhost(Bitmap *bmp);
void snSay(Sprite *spr, int val);
-
+
void hide1(Sprite *spr);
Sprite *expandSprite(Sprite *spr);
void qGame();
diff --git a/engines/cge2/cge2_main.cpp b/engines/cge2/cge2_main.cpp
index 3e3d615a91..4e3d229618 100644
--- a/engines/cge2/cge2_main.cpp
+++ b/engines/cge2/cge2_main.cpp
@@ -58,7 +58,7 @@ void System::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
if (_vm->_gamePhase != kPhaseInGame)
return;
_vm->_infoLine->setText(nullptr);
-
+
if (mask & kMouseLeftUp) {
if (pos.y >= 0) { // world
if (!_vm->_talk && pos.y < _vm->_mouseTop)
@@ -184,7 +184,7 @@ Sprite *CGE2Engine::loadSprite(const char *fname, int ref, int scene, V3D &pos)
if (line.empty())
continue;
Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
-
+
char *p = token(tmpStr);
if (*p == '@') {
if (label != kNoByte)
@@ -327,7 +327,7 @@ void CGE2Engine::loadScript(const char *fname, bool onlyToolbar) {
lcnt++;
Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
-
+
ok = false; // not OK if break
V3D P;
@@ -419,7 +419,7 @@ void CGE2Engine::sceneUp(int cav) {
_map->load(_now);
_spare->takeScene(_now);
openPocket();
-
+
for (int i = 0; i < 2; i++) {
Hero *h = _heroTab[i]->_ptr;
if (h && h->_scene == _now) {
@@ -432,7 +432,7 @@ void CGE2Engine::sceneUp(int cav) {
h->setContact();
}
}
-
+
_sound->stop();
_fx->clear();
@@ -596,7 +596,7 @@ void CGE2Engine::tick() {
for (Sprite *spr = _vga->_showQ->first(); spr; spr = spr->_next) {
if (spr->_time && (--spr->_time == 0))
spr->tick();
-
+
if (_waitRef && (_waitRef == spr->_ref) && spr->seqTest(_waitSeq))
_waitRef = 0;
}
@@ -658,10 +658,10 @@ void CGE2Engine::loadUser() {
void CGE2Engine::loadHeroes() { // Original name: loadGame()
// load sprites & pocket
-
+
Sprite *s;
Hero *h = nullptr;
-
+
// initialize Andzia/Anna
s = _spare->take(142);
if (s) {
@@ -698,7 +698,7 @@ void CGE2Engine::loadPos() {
if (_resman->exist("CGE.HXY")) {
for (int cav = 0; cav < kSceneMax; cav++)
_heroTab[1]->_posTab[cav] = new V2D(this, 180, 10);
-
+
EncryptedStream file(this, "CGE.HXY");
for (int cav = 0; cav < kSceneMax; cav++) {
@@ -752,7 +752,7 @@ void CGE2Engine::cge2_main() {
runGame();
_gamePhase = kPhaseOver;
}
-
+
_vga->sunset();
} else
_vga->sunset();
@@ -767,7 +767,7 @@ char *CGE2Engine::mergeExt(char *buf, const char *name, const char *ext) {
return buf;
}
-void CGE2Engine::setEye(const V3D &e) {
+void CGE2Engine::setEye(const V3D &e) {
*_eye = e;
}
@@ -931,7 +931,7 @@ void CGE2Engine::offUse() {
// This fixes the issue of empty speech bubbles in the original.
// Now we only let this cycle pass if it randoms a valid value for getText().
int txt = 0;
- do {
+ do {
txt = kOffUseText + _sex * offUseCount + newRandom(offUseCount);
} while (_text->getText(txt) == nullptr);
diff --git a/engines/cge2/cge2_main.h b/engines/cge2/cge2_main.h
index 88cca1cc1e..4d92c33e50 100644
--- a/engines/cge2/cge2_main.h
+++ b/engines/cge2/cge2_main.h
@@ -40,7 +40,7 @@ public:
Sprite *_blinkSprite;
System(CGE2Engine *vm);
-
+
virtual void touch(uint16 mask, V2D pos, Common::KeyCode keyCode);
void tick();
private:
diff --git a/engines/cge2/configure.engine b/engines/cge2/configure.engine
index 6ccbfee088..79d091fec5 100644
--- a/engines/cge2/configure.engine
+++ b/engines/cge2/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine cge2 "CGE2" no
+add_engine cge2 "CGE2" yes
diff --git a/engines/cge2/events.cpp b/engines/cge2/events.cpp
index ed1ec66bb1..85743c8011 100644
--- a/engines/cge2/events.cpp
+++ b/engines/cge2/events.cpp
@@ -132,7 +132,7 @@ Mouse::Mouse(CGE2Engine *vm) : Sprite(vm), _busy(nullptr), _hold(nullptr), _hx(0
_busy = nullptr;
_active = false;
_flags._kill = false;
-
+
setSeq(_stdSeq8);
BitmapPtr MC = new Bitmap[2];
@@ -260,7 +260,7 @@ void EventManager::handleEvents() {
if (e._spritePtr) {
if (e._mask & kEventKeyb)
e._spritePtr->touch(e._mask, _vm->_mouse->_point, e._keyCode);
- else
+ else
e._spritePtr->touch(e._mask, _vm->_mouse->_point - e._spritePtr->_pos2D, e._keyCode);
} else if (_vm->_sys)
_vm->_sys->touch(e._mask, _vm->_mouse->_point, e._keyCode);
diff --git a/engines/cge2/hero.cpp b/engines/cge2/hero.cpp
index 225df54bd1..42ae67cc2b 100644
--- a/engines/cge2/hero.cpp
+++ b/engines/cge2/hero.cpp
@@ -205,7 +205,7 @@ Sprite *Hero::expand() {
int i = stepSize() / 2;
_maxDist = (int)sqrt(double(i * i * 2));
setCurrent();
-
+
return this;
}
@@ -558,9 +558,9 @@ int CGE2Engine::mapCross(const V2D &a, const V2D &b) {
if (p) {
if (cross(a, b, *n0, *n))
++cnt;
-
+
if (*n == *p)
- p = nullptr;
+ p = nullptr;
} else {
p = n;
}
@@ -587,7 +587,7 @@ void Hero::operator--() {
bool Sprite::works(Sprite *spr) {
if (!spr || !spr->_ext)
return false;
-
+
bool ok = false;
Action a = _vm->_heroTab[_vm->_sex]->_ptr->action();
@@ -615,7 +615,7 @@ bool Sprite::works(Sprite *spr) {
}
}
}
-
+
return ok;
}
diff --git a/engines/cge2/map.cpp b/engines/cge2/map.cpp
index 8c1f00048f..275e15f55a 100644
--- a/engines/cge2/map.cpp
+++ b/engines/cge2/map.cpp
@@ -48,7 +48,7 @@ void Map::load(int scene) {
return;
EncryptedStream file(_vm, fileName.c_str());
-
+
Common::String line;
for (line = file.readLine(); !file.eos(); line = file.readLine()) {
if (line.empty())
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp
index fd60422dff..7735c077a6 100644
--- a/engines/cge2/saveload.cpp
+++ b/engines/cge2/saveload.cpp
@@ -104,7 +104,7 @@ bool CGE2Engine::loadGame(int slotNumber) {
saveFile->read(dataBuffer, size);
readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
delete saveFile;
-
+
// Check to see if it's a ScummVM savegame or not
char buffer[kSavegameStrSize + 1];
readStream->read(buffer, kSavegameStrSize + 1);
@@ -132,7 +132,7 @@ bool CGE2Engine::loadGame(int slotNumber) {
delete readStream;
loadHeroes();
-
+
return true;
}
diff --git a/engines/cge2/snail.cpp b/engines/cge2/snail.cpp
index 8e1ddf2d9b..7580ef4425 100644
--- a/engines/cge2/snail.cpp
+++ b/engines/cge2/snail.cpp
@@ -92,7 +92,7 @@ void CommandHandler::runCommand() {
}
_textDelay = false;
}
-
+
if (_vm->_talk && tailCmd._commandType != kCmdPause)
break;
}
@@ -332,7 +332,7 @@ void CGE2Engine::snRSeq(Sprite *spr, int val) {
void CGE2Engine::snSend(Sprite *spr, int val) {
if (!spr)
return;
-
+
// Sending", spr->_file
// from scene", spr->_scene
// to scene", val
@@ -691,7 +691,7 @@ Sprite *CGE2Engine::expandSprite(Sprite *spr) {
void CGE2Engine::qGame() {
// Write out the user's progress
saveGame(0, Common::String("Automatic Savegame"));
-
+
busy(false);
_vga->sunset();
_endGame = true;
@@ -853,13 +853,13 @@ void CGE2Engine::feedSnail(Sprite *spr, Action snq, Hero *hero) {
if (s == spr)
break;
}
-
+
_commandHandler->addCommand(c->_commandType, c->_ref, c->_val, spr);
++c;
}
}
-
+
}
} // End of namespace CGE2.
diff --git a/engines/cge2/spare.h b/engines/cge2/spare.h
index 7dc6ce60f5..24a97712ff 100644
--- a/engines/cge2/spare.h
+++ b/engines/cge2/spare.h
@@ -38,7 +38,7 @@ class Spare {
public:
Spare(CGE2Engine *vm) : _vm(vm) {}
~Spare() { clear(); }
- void store(Sprite *spr);
+ void store(Sprite *spr);
Sprite *locate(int ref);
Sprite *take(int ref);
void takeScene(int cav);
diff --git a/engines/cge2/talk.cpp b/engines/cge2/talk.cpp
index 9109da90f1..8e6be6cac2 100644
--- a/engines/cge2/talk.cpp
+++ b/engines/cge2/talk.cpp
@@ -121,7 +121,7 @@ Talk::Talk(CGE2Engine *vm, const char *text, TextBoxStyle mode, ColorBank color,
Talk::Talk(CGE2Engine *vm, ColorBank color)
: Sprite(vm), _mode(kTBPure), _created(false), _wideSpace(false), _vm(vm) {
_color = _vm->_font->_colorSet[color];
-
+
if (color == kCBRel)
_vm->setAutoColors();
}
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
index 227633579e..f4064f3565 100644
--- a/engines/cge2/vga13h.cpp
+++ b/engines/cge2/vga13h.cpp
@@ -45,13 +45,13 @@ void V3D::sync(Common::Serializer &s) {
_z.sync(s);
}
-FXP FXP::operator*(const FXP& x) const {
- FXP y;
+FXP FXP::operator*(const FXP& x) const {
+ FXP y;
int32 t1 = (v >> 8) * x.v;
int32 t2 = ((v & 0xFF) * x.v) >> 8;
y.v = t1 + t2;
- return y;
+ return y;
}
FXP FXP::operator/(const FXP& x) const {
@@ -613,7 +613,7 @@ void Sprite::gotoxyz(V2D pos) {
++trim;
}
_pos2D.x = pos.x;
-
+
if (pos.y < -kPanHeight) {
pos.y = -kPanHeight;
++trim;
diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp
index bb0838395d..ebaff32550 100644
--- a/engines/fullpipe/fullpipe.cpp
+++ b/engines/fullpipe/fullpipe.cpp
@@ -163,7 +163,7 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc)
for (int i = 0; i < 11; i++)
_currSoundList1[i] = 0;
-
+
for (int i = 0; i < 200; i++)
_mapTable[i] = 0;
@@ -285,7 +285,7 @@ Common::Error FullpipeEngine::run() {
freeGameLoader();
_currentScene = 0;
_updateTicks = 0;
-
+
loadGam("fullpipe.gam");
_needRestart = false;
}
diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp
index 61fbf7192f..42846850ca 100644
--- a/engines/fullpipe/gfx.cpp
+++ b/engines/fullpipe/gfx.cpp
@@ -153,7 +153,7 @@ bool PictureObject::load(MfcArchive &file, bool bigPicture) {
if (count > 0) {
GameObject *o = new GameObject();
-
+
o->load(file);
_pictureObject2List->push_back(o);
}
@@ -286,9 +286,9 @@ bool GameObject::load(MfcArchive &file) {
_okeyCode = 0;
_flags = 0;
_field_20 = 0;
-
+
_id = file.readUint16LE();
-
+
_objectName = file.readPascalString();
_ox = file.readUint32LE();
_oy = file.readUint32LE();
@@ -498,7 +498,7 @@ bool Picture::load(MfcArchive &file) {
_x = file.readUint32LE();
_y = file.readUint32LE();
_field_44 = file.readUint16LE();
-
+
assert(g_fp->_gameProjectVersion >= 2);
_width = file.readUint32LE();
diff --git a/engines/fullpipe/input.cpp b/engines/fullpipe/input.cpp
index 7c97461a24..b681f4fbe7 100644
--- a/engines/fullpipe/input.cpp
+++ b/engines/fullpipe/input.cpp
@@ -70,7 +70,7 @@ void setInputDisabled(bool state) {
void InputController::addCursor(CursorInfo *cursor) {
CursorInfo *newc = new CursorInfo(cursor);
Common::Point p;
-
+
cursor->picture->getDimensions(&p);
newc->width = p.x;
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
index 49cf88434e..9573e0517b 100644
--- a/engines/fullpipe/motion.cpp
+++ b/engines/fullpipe/motion.cpp
@@ -1040,11 +1040,11 @@ MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int
if (!mq || !mq->getExCommandByIndex(0))
return 0;
-
+
ExCommand *ex = mq->getExCommandByIndex(0);
- if ((ex->_messageKind != 1 && ex->_messageKind != 20) ||
- ex->_messageNum != subj->_movement->_id ||
+ if ((ex->_messageKind != 1 && ex->_messageKind != 20) ||
+ ex->_messageNum != subj->_movement->_id ||
(ex->_field_14 >= 1 && ex->_field_14 <= subj->_movement->_currDynamicPhaseIndex))
subj->playIdle();
}
@@ -1416,8 +1416,8 @@ Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int fla
movarr = new MovArr;
movarr->_link = lnk;
- movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) +
- (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) /
+ movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) +
+ (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) /
lnk->_distance / lnk->_distance;
movarr->_point = point;
@@ -1445,8 +1445,8 @@ Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int fla
} else {
movarr = new MovArr;
movarr->_link = lnk;
- movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) +
- (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) /
+ movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) +
+ (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) /
lnk->_distance / lnk->_distance;
movarr->_point.x = x;
movarr->_point.y = y;
diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp
index 8463b3ab40..00dd70c1b2 100644
--- a/engines/fullpipe/scene.cpp
+++ b/engines/fullpipe/scene.cpp
@@ -162,7 +162,7 @@ bool Scene::load(MfcArchive &file) {
Background::load(file);
_sceneId = file.readUint16LE();
-
+
_sceneName = file.readPascalString();
debug(0, "scene: <%s> %d", transCyrillic((byte *)_sceneName), _sceneId);
diff --git a/engines/fullpipe/scenes/scene02.cpp b/engines/fullpipe/scenes/scene02.cpp
index 109a20a07a..fd542d580d 100644
--- a/engines/fullpipe/scenes/scene02.cpp
+++ b/engines/fullpipe/scenes/scene02.cpp
@@ -134,5 +134,5 @@ int sceneHandler02(ExCommand *ex) {
return res;
}
-
+
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene14.cpp b/engines/fullpipe/scenes/scene14.cpp
index 21dbe8101f..446f477133 100644
--- a/engines/fullpipe/scenes/scene14.cpp
+++ b/engines/fullpipe/scenes/scene14.cpp
@@ -57,7 +57,7 @@ void scene14_initScene(Scene *sc) {
ball->_flags &= 0xFFFB;
g_vars->scene14_balls.push_back(ball);
-
+
for (uint i = 0; i < 3; i++) {
ball = new StaticANIObject(ball); // create a copy
diff --git a/engines/fullpipe/scenes/scene15.cpp b/engines/fullpipe/scenes/scene15.cpp
index 452f2edeca..efc69a5fa6 100644
--- a/engines/fullpipe/scenes/scene15.cpp
+++ b/engines/fullpipe/scenes/scene15.cpp
@@ -71,7 +71,7 @@ void scene15_initScene(Scene *sc) {
grandma->hide();
g_fp->setObjectState(sO_LeftPipe_15, g_fp->getObjectEnumState(sO_LeftPipe_15, sO_IsOpened));
}
-
+
g_vars->scene15_plusminus = sc->getStaticANIObject1ById(ANI_PLUSMINUS, -1);
if (g_fp->getObjectState(sO_Guard_2) == g_fp->getObjectEnumState(sO_Guard_2, sO_Off))
diff --git a/engines/fullpipe/scenes/scene16.cpp b/engines/fullpipe/scenes/scene16.cpp
index ed3c51a6c2..e9d3a37efd 100644
--- a/engines/fullpipe/scenes/scene16.cpp
+++ b/engines/fullpipe/scenes/scene16.cpp
@@ -57,9 +57,9 @@ void scene16_initScene(Scene *sc) {
boy[1] = new StaticANIObject(boy[0]);
sc->addStaticANIObject(boy[1], 1);
-
+
int idx = 0;
-
+
for (int i = 0; i < 3; i++) {
g_vars->scene16_figures.push_back(boy[idx]);
@@ -68,7 +68,7 @@ void scene16_initScene(Scene *sc) {
if (idx >= 2)
idx = 0;
}
-
+
g_vars->scene16_figures.push_back(sc->getStaticANIObject1ById(ANI_GIRL, -1));
for (int i = 0; i < 4; i++) {
@@ -259,7 +259,7 @@ void sceneHandler16_drink() {
mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC16_BOYKICK), 0, 1);
mq->replaceKeyCode(-1, g_vars->scene16_walkingBoy->_okeyCode);
-
+
ex = new ExCommand(ANI_MAN, 34, 384, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags |= 3u;
ex->_field_14 = 384;
diff --git a/engines/fullpipe/scenes/scene23.cpp b/engines/fullpipe/scenes/scene23.cpp
index ccfbac9223..f66ea12b4b 100644
--- a/engines/fullpipe/scenes/scene23.cpp
+++ b/engines/fullpipe/scenes/scene23.cpp
@@ -146,7 +146,7 @@ void scene23_initScene(Scene *sc) {
sc->getStaticANIObject1ById(ANI_INV_LEVERHANDLE, -1)->hide();
}
-
+
g_fp->_currentScene = oldsc;
}
diff --git a/engines/fullpipe/scenes/scene28.cpp b/engines/fullpipe/scenes/scene28.cpp
index c21ce05502..de5a96e70d 100644
--- a/engines/fullpipe/scenes/scene28.cpp
+++ b/engines/fullpipe/scenes/scene28.cpp
@@ -46,7 +46,7 @@ void scene28_initScene(Scene *sc) {
g_vars->scene28_lift6inside = false;
g_fp->_floaters->init(g_fp->getGameLoaderGameVar()->getSubVarByName("SC_28"));
-
+
g_fp->initArcadeKeys("SC_28");
}
diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp
index 8f82e99ad1..222a541554 100644
--- a/engines/fullpipe/scenes/scene29.cpp
+++ b/engines/fullpipe/scenes/scene29.cpp
@@ -840,7 +840,7 @@ void sceneHandler29_shootersEscape() {
void sceneHandler29_manRideBack() {
g_vars->scene29_manX -= 2;
-
+
g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY);
}
diff --git a/engines/fullpipe/scenes/scene37.cpp b/engines/fullpipe/scenes/scene37.cpp
index 09da01f138..324d3ac92d 100644
--- a/engines/fullpipe/scenes/scene37.cpp
+++ b/engines/fullpipe/scenes/scene37.cpp
@@ -91,7 +91,7 @@ void scene37_initScene(Scene *sc) {
g_vars->scene37_rings.push_back(ring);
g_fp->setObjectState(sO_LeftPipe_37, g_fp->getObjectEnumState(sO_LeftPipe_37, sO_IsClosed));
-
+
Scene *oldsc = g_fp->_currentScene;
g_fp->_currentScene = sc;
diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp
index a4ca06f489..230d6c39a9 100644
--- a/engines/fullpipe/sound.cpp
+++ b/engines/fullpipe/sound.cpp
@@ -62,7 +62,7 @@ bool SoundList::load(MfcArchive &file, char *fname) {
}
return true;
-
+
}
bool SoundList::loadFile(const char *fname, char *libname) {
diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp
index 717de84925..880c2eb0df 100644
--- a/engines/fullpipe/statics.cpp
+++ b/engines/fullpipe/statics.cpp
@@ -246,7 +246,7 @@ bool StaticANIObject::load(MfcArchive &file) {
void StaticANIObject::setOXY(int x, int y) {
_ox = x;
_oy = y;
-
+
if (_movement)
_movement->setOXY(x, y);
}
@@ -713,7 +713,7 @@ void StaticANIObject::setSpeed(int speed) {
void StaticANIObject::setAlpha(int alpha) {
for (uint i = 0; i < _movements.size(); i++)
_movements[i]->setAlpha(alpha);
-
+
for (uint i = 0; i < _staticsList.size(); i++)
_staticsList[i]->setAlpha(alpha);
}
@@ -1813,7 +1813,7 @@ void Movement::initStatics(StaticANIObject *ani) {
_staticsObj2 = ani->addReverseStatics(_currMovement->_staticsObj2);
_staticsObj1 = ani->addReverseStatics(_currMovement->_staticsObj1);
-
+
_mx = _currMovement->_mx;
_my = _currMovement->_my;
@@ -2279,7 +2279,7 @@ bool StaticPhase::load(MfcArchive &file) {
_initialCountdown = file.readUint16LE();
_field_6A = file.readUint16LE();
-
+
if (g_fp->_gameProjectVersion >= 12) {
_exCommand = (ExCommand *)file.readClass();
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index b85277fac7..e0c198f377 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -63,7 +63,7 @@ void GraphicsMan::update() {
// Clear the buffer when ending the fade out
if (_fading == 2)
- _foreground.fillRect(Common::Rect(640, 320), 0);
+ _foreground.fillRect(Common::Rect(640, _foreground.h), 0);
}
}
@@ -74,6 +74,22 @@ void GraphicsMan::update() {
}
}
+void GraphicsMan::switchToFullScreen(bool fullScreen) {
+ _foreground.free();
+ _background.free();
+
+ if (fullScreen) {
+ _foreground.create(640, 480, _vm->_pixelFormat);
+ _background.create(640, 480, _vm->_pixelFormat);
+ } else {
+ _vm->_system->fillScreen(0);
+ _foreground.create(640, 320, _vm->_pixelFormat);
+ _background.create(640, 320, _vm->_pixelFormat);
+ }
+
+ _changed = true;
+}
+
void GraphicsMan::change() {
_changed = true;
}
@@ -84,7 +100,7 @@ void GraphicsMan::mergeFgAndBg() {
countf = (byte *)_foreground.getPixels();
countb = (byte *)_background.getPixels();
- for (i = 640 * 320; i; i--) {
+ for (i = 640 * _foreground.h; i; i--) {
if (255 == *(countf)) {
*(countf) = *(countb);
}
@@ -94,7 +110,10 @@ void GraphicsMan::mergeFgAndBg() {
}
void GraphicsMan::updateScreen(Graphics::Surface *source) {
- _vm->_system->copyRectToScreen(source->getPixels(), 640, 0, 80, 640, 320);
+ if (!isFullScreen())
+ _vm->_system->copyRectToScreen(source->getPixels(), source->pitch, 0, 80, 640, 320);
+ else
+ _vm->_system->copyRectToScreen(source->getPixels(), source->pitch, 0, 0, 640, 480);
change();
}
diff --git a/engines/groovie/graphics.h b/engines/groovie/graphics.h
index 72ab01deb6..69934f9d68 100644
--- a/engines/groovie/graphics.h
+++ b/engines/groovie/graphics.h
@@ -38,6 +38,8 @@ public:
void update();
void change();
void mergeFgAndBg();
+ void switchToFullScreen(bool fullScreen);
+ bool isFullScreen() { return (_foreground.h == 480); }
void updateScreen(Graphics::Surface *source);
Graphics::Surface _foreground; // The main surface that most things are drawn to
Graphics::Surface _background; // Used occasionally, mostly (only?) in puzzles
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 379fcabc07..f14cacd6b8 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -28,6 +28,7 @@
#include "groovie/groovie.h"
#include "common/debug.h"
+#include "common/debug-channels.h"
#include "common/rect.h"
#include "common/substream.h"
#include "common/textconsole.h"
@@ -46,6 +47,7 @@ namespace Groovie {
ROQPlayer::ROQPlayer(GroovieEngine *vm) :
VideoPlayer(vm), _codingTypeCount(0),
+ _fg(&_vm->_graphicsMan->_foreground),
_bg(&_vm->_graphicsMan->_background),
_firstFrame(true) {
@@ -63,6 +65,22 @@ ROQPlayer::~ROQPlayer() {
}
uint16 ROQPlayer::loadInternal() {
+ if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
+ int8 i;
+ debugN(1, "Groovie::ROQ: New ROQ: bitflags are ");
+ for (i = 15; i >= 0; i--) {
+ debugN(1, "%d", _flags & (1 << i)? 1 : 0);
+ if (i % 4 == 0) {
+ debugN(1, " ");
+ }
+ }
+ debug(1, " <- 0 ");
+ }
+
+ // Flags:
+ // - 2 For overlay videos, show the whole video
+ _flagTwo = ((_flags & (1 << 2)) != 0);
+
// Begin reading the file
debugC(1, kDebugVideo, "Groovie::ROQ: Loading video");
@@ -106,13 +124,23 @@ uint16 ROQPlayer::loadInternal() {
}
void ROQPlayer::buildShowBuf() {
+ if (_alpha)
+ _fg->copyFrom(*_bg);
+
for (int line = 0; line < _bg->h; line++) {
- uint32 *out = (uint32 *)_bg->getBasePtr(0, line);
+ uint32 *out = _alpha ? (uint32 *)_fg->getBasePtr(0, line) : (uint32 *)_bg->getBasePtr(0, line);
uint32 *in = (uint32 *)_currBuf->getBasePtr(0, line / _scaleY);
for (int x = 0; x < _bg->w; x++) {
- // Copy a pixel
- *out++ = *in;
+ // Copy a pixel, checking the alpha channel first
+ if (_alpha && !(*in & 0xFF))
+ out++;
+ else if (_fg->h == 480 && *in == _vm->_pixelFormat.RGBToColor(255, 255, 255))
+ // Handle transparency in Gamepad videos
+ // TODO: For now, we detect these videos by checking for full screen
+ out++;
+ else
+ *out++ = *in;
// Skip to the next pixel
if (!(x % _scaleX))
@@ -145,19 +173,27 @@ bool ROQPlayer::playFrameInternal() {
}
// Wait until the current frame can be shown
- waitFrame();
+ // Don't wait if we're just showing one frame
+ if (!playFirstFrame())
+ waitFrame();
if (_dirty) {
// Update the screen
- _syst->copyRectToScreen(_bg->getPixels(), _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
+ void *src = (_alpha) ? _fg->getPixels() : _bg->getPixels();
+ _syst->copyRectToScreen(src, _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
_syst->updateScreen();
+ // For overlay videos, set the background buffer when the video ends
+ if (_alpha && (!_flagTwo || (_flagTwo && _file->eos())))
+ _bg->copyFrom(*_fg);
+
// Clear the dirty flag
_dirty = false;
}
- // Return whether the video has ended
- return _file->eos();
+ // Report the end of the video if we reached the end of the file or if we
+ // just wanted to play one frame.
+ return _file->eos() || playFirstFrame();
}
bool ROQPlayer::readBlockHeader(ROQBlockHeader &blockHeader) {
@@ -277,9 +313,17 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
_prevBuf->create(width, height, _vm->_pixelFormat);
}
+ // Switch from/to fullscreen, if needed
+ if (_bg->h != 480 && height == 480)
+ _vm->_graphicsMan->switchToFullScreen(true);
+ else if (_bg->h == 480 && height != 480)
+ _vm->_graphicsMan->switchToFullScreen(false);
+
// Clear the buffers with black
- _currBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
- _prevBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
+ if (!_alpha) {
+ _currBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
+ _prevBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
+ }
return true;
}
@@ -448,7 +492,7 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
}
// Initialize the audio stream if needed
- if (!_audioStream) {
+ if (!_audioStream && !playFirstFrame()) {
_audioStream = Audio::makeQueuingAudioStream(22050, false);
Audio::SoundHandle sound_handle;
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &sound_handle, _audioStream);
@@ -477,7 +521,10 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
#ifdef SCUMM_LITTLE_ENDIAN
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- _audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
+ if (!playFirstFrame())
+ _audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
+ else
+ free(buffer);
return true;
}
@@ -491,7 +538,7 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
}
// Initialize the audio stream if needed
- if (!_audioStream) {
+ if (!_audioStream && !playFirstFrame()) {
_audioStream = Audio::makeQueuingAudioStream(22050, true);
Audio::SoundHandle sound_handle;
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &sound_handle, _audioStream);
@@ -533,7 +580,10 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
#ifdef SCUMM_LITTLE_ENDIAN
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- _audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
+ if (!playFirstFrame())
+ _audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
+ else
+ free(buffer);
return true;
}
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index 7e7d38580e..ce1a3a2d58 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -57,6 +57,7 @@ private:
bool processBlockSoundMono(ROQBlockHeader &blockHeader);
bool processBlockSoundStereo(ROQBlockHeader &blockHeader);
bool processBlockAudioContainer(ROQBlockHeader &blockHeader);
+ bool playFirstFrame() { return _alpha && !_flagTwo; }
void paint2(byte i, int destx, int desty);
void paint4(byte i, int destx, int desty);
@@ -74,8 +75,11 @@ private:
uint32 _codebook2[256 * 4];
byte _codebook4[256 * 4];
+ // Flags
+ bool _flagTwo;
+
// Buffers
- Graphics::Surface *_bg;
+ Graphics::Surface *_fg, *_bg;
Graphics::Surface *_currBuf, *_prevBuf;
void buildShowBuf();
byte _scaleX, _scaleY;
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 7625151082..eef97b6ff9 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -179,12 +179,20 @@ void Script::directGameLoad(int slot) {
// TODO: Return to the main script, likely reusing most of o_returnscript()
- // HACK: We set variable 0x19 to the slot to load, and set the current
- // instruction to the one that actually loads the saved game specified
- // in that variable. This will change in other versions of the game and
- // in other games.
- setVariable(0x19, slot);
- _currentInstruction = 0x287;
+ // HACK: We set the slot to load in the appropriate variable, and set the
+ // current instruction to the one that actually loads the saved game
+ // specified in that variable. This differs depending on the game and its
+ // version.
+ if (_version == kGroovieT7G) {
+ // 7th Guest
+ setVariable(0x19, slot);
+ _currentInstruction = 0x287;
+ } else {
+ // 11th Hour
+ setVariable(0xF, slot);
+ // FIXME: This bypasses a lot of the game's initialization procedure
+ _currentInstruction = 0xE78E;
+ }
// TODO: We'll probably need to start by running the beginning of the
// script to let it do the soundcard initialization and then do the
@@ -350,9 +358,10 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
// Show hotspots when debugging
if (DebugMan.isDebugChannelEnabled(kDebugHotspots)) {
- rect.translate(0, -80);
+ if (!_vm->_graphicsMan->isFullScreen())
+ rect.translate(0, -80);
_vm->_graphicsMan->_foreground.frameRect(rect, 250);
- _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320);
+ _vm->_graphicsMan->updateScreen(&_vm->_graphicsMan->_foreground);
_vm->_system->updateScreen();
}
@@ -962,7 +971,7 @@ void Script::o_strcmpnejmp_var() { // 0x21
void Script::o_copybgtofg() { // 0x22
debugC(1, kDebugScript, "COPY_BG_TO_FG");
- memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * 320);
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h);
}
void Script::o_strcmpeqjmp() { // 0x23
@@ -1198,6 +1207,7 @@ void Script::o_copyrecttobg() { // 0x37
uint16 top = readScript16bits();
uint16 right = readScript16bits();
uint16 bottom = readScript16bits();
+ uint16 baseTop = (!_vm->_graphicsMan->isFullScreen()) ? 80 : 0;
// Sanity checks to prevent bad pointer access crashes
if (left > right) {
@@ -1216,9 +1226,9 @@ void Script::o_copyrecttobg() { // 0x37
bottom = top;
top = j;
}
- if (top < 80) {
- warning("COPYRECT top < 80... clamping");
- top = 80;
+ if (top < baseTop) {
+ warning("COPYRECT top < baseTop... clamping");
+ top = baseTop;
}
if (top >= 480) {
warning("COPYRECT top >= 480... clamping");
@@ -1243,13 +1253,13 @@ void Script::o_copyrecttobg() { // 0x37
debugC(1, kDebugScript, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
- fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - 80);
- bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - 80);
+ fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - baseTop);
+ bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop);
for (i = 0; i < height; i++) {
memcpy(bg + offset, fg + offset, width);
offset += 640;
}
- _vm->_system->copyRectToScreen(_vm->_graphicsMan->_background.getBasePtr(left, top - 80), 640, left, top, width, height);
+ _vm->_system->copyRectToScreen(_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop), 640, left, top, width, height);
_vm->_graphicsMan->change();
}
@@ -1595,8 +1605,7 @@ void Script::o_hotspot_outrect() {
bool contained = rect.contains(mousepos);
if (!contained) {
- error("hotspot-outrect unimplemented");
- // TODO: what to do with address?
+ _currentInstruction = address;
}
}
@@ -1670,15 +1679,29 @@ void Script::o2_vdxtransition() {
void Script::o2_copyscreentobg() {
uint16 val = readScript16bits();
+ // TODO: Parameter
+ if (val)
+ warning("o2_copyscreentobg: Param is %d", val);
+
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ _vm->_graphicsMan->_background.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 320)));
+ _vm->_system->unlockScreen();
+
debugC(1, kDebugScript, "CopyScreenToBG3: 0x%04X", val);
- error("Unimplemented Opcode 0x4F");
}
void Script::o2_copybgtoscreen() {
uint16 val = readScript16bits();
+ // TODO: Parameter
+ if (val)
+ warning("o2_copybgtoscreen: Param is %d", val);
+
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ _vm->_graphicsMan->_background.copyRectToSurface(*screen, 0, 80, Common::Rect(0, 0, 640, 320 - 80));
+ _vm->_system->unlockScreen();
+
debugC(1, kDebugScript, "CopyBG3ToScreen: 0x%04X", val);
- error("Unimplemented Opcode 0x50");
}
void Script::o2_setvideoskip() {
@@ -1686,6 +1709,12 @@ void Script::o2_setvideoskip() {
debugC(1, kDebugScript, "SetVideoSkip (0x%04X)", _videoSkipAddress);
}
+void Script::o2_stub42() {
+ uint8 arg = readScript8bits();
+ // TODO: Switch with 5 cases (0 - 5). Anything above 5 is a NOP
+ debugC(1, kDebugScript, "STUB42 (0x%02X)", arg);
+}
+
void Script::o2_stub52() {
uint8 arg = readScript8bits();
debugC(1, kDebugScript, "STUB52 (0x%02X)", arg);
@@ -1859,7 +1888,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_loadscript,
&Script::o_setvideoorigin, // 0x40
&Script::o_sub,
- &Script::o_cellmove,
+ &Script::o2_stub42,
&Script::o_returnscript,
&Script::o_sethotspotright, // 0x44
&Script::o_sethotspotleft,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 35e52593de..a9f6143509 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -238,6 +238,7 @@ private:
void o2_setvideoskip();
void o2_copyscreentobg();
void o2_copybgtoscreen();
+ void o2_stub42();
void o2_stub52();
void o2_setscriptend();
};
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index 84d5c631c7..18b16cb4c8 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -883,7 +883,7 @@ void ComputerManager::getScoreName() {
_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
byte *ptr = _vm->_fileIO->loadFile("ALPHA.SPR");
_vm->_graphicsMan->fadeInBreakout();
-
+
// Figure out the line to put the new high score on
int scoreLine = 0;
while (scoreLine < 5 && _breakoutScore < atol(_score[scoreLine]._score.c_str()))
diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp
index 6620f2878c..3100ed6cdc 100644
--- a/engines/hopkins/files.cpp
+++ b/engines/hopkins/files.cpp
@@ -74,7 +74,7 @@ int FileManager::readStream(Common::ReadStream &stream, void *buf, size_t nbytes
* It's now using the config manager and a per-engine GUI option.
*/
void FileManager::initCensorship() {
- _vm->_globals->_censorshipFl = ConfMan.getBool("enable_gore");
+ _vm->_globals->_censorshipFl = !ConfMan.getBool("enable_gore");
}
/**
diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp
index 773c714899..6660233740 100644
--- a/engines/hopkins/sound.cpp
+++ b/engines/hopkins/sound.cpp
@@ -261,9 +261,9 @@ void SoundManager::loadAnimSound() {
}
}
-void SoundManager::playAnimSound(int soundNumber) {
+void SoundManager::playAnimSound(int animFrame) {
if (!_vm->_globals->_censorshipFl && _specialSoundNum == 2) {
- switch (soundNumber) {
+ switch (animFrame) {
case 20:
playSample(5);
break;
@@ -273,44 +273,59 @@ void SoundManager::playAnimSound(int soundNumber) {
playSample(1);
break;
case 75:
- playSample(2);
+ // This removes the sound of the gun played while the guard is being shot, as this part of the scene has been
+ // removed in the Polish version of the game
+ if (_vm->getLanguage() != Common::PL_POL)
+ playSample(2);
+ break;
+ case 95:
+ // This fixes an original bug in the Polish version of the game, which was literally butchered for some reason
+ if (_vm->getLanguage() == Common::PL_POL)
+ playSample(3);
break;
case 109:
- playSample(3);
+ if (_vm->getLanguage() != Common::PL_POL)
+ playSample(3);
+ break;
+ case 108:
+ // This fixes an original bug in the Polish version of the game, which was literally butchered for some reason
+ if (_vm->getLanguage() == Common::PL_POL)
+ playSample(4);
break;
case 122:
- playSample(4);
+ if (_vm->getLanguage() != Common::PL_POL)
+ playSample(4);
break;
}
- } else if (_specialSoundNum == 1 && soundNumber == 17)
+ } else if (_specialSoundNum == 1 && animFrame == 17)
playSoundFile("SOUND42.WAV");
- else if (_specialSoundNum == 5 && soundNumber == 19)
+ else if (_specialSoundNum == 5 && animFrame == 19)
playWav(1);
- else if (_specialSoundNum == 14 && soundNumber == 625)
+ else if (_specialSoundNum == 14 && animFrame == 625)
playWav(1);
- else if (_specialSoundNum == 16 && soundNumber == 25)
+ else if (_specialSoundNum == 16 && animFrame == 25)
playWav(1);
else if (_specialSoundNum == 17) {
- if (soundNumber == 6)
+ if (animFrame == 6)
playSample(1);
- else if (soundNumber == 14)
+ else if (animFrame == 14)
playSample(2);
- else if (soundNumber == 67)
+ else if (animFrame == 67)
playSample(3);
- } else if (_specialSoundNum == 198 && soundNumber == 15)
+ } else if (_specialSoundNum == 198 && animFrame == 15)
playWav(1);
- else if (_specialSoundNum == 199 && soundNumber == 72)
+ else if (_specialSoundNum == 199 && animFrame == 72)
playWav(1);
- else if (_specialSoundNum == 208 && soundNumber == 40)
+ else if (_specialSoundNum == 208 && animFrame == 40)
playWav(1);
- else if (_specialSoundNum == 210 && soundNumber == 2)
+ else if (_specialSoundNum == 210 && animFrame == 2)
playWav(1);
- else if (_specialSoundNum == 211 && soundNumber == 22)
+ else if (_specialSoundNum == 211 && animFrame == 22)
playWav(1);
else if (_specialSoundNum == 229) {
- if (soundNumber == 15)
+ if (animFrame == 15)
playWav(1);
- else if (soundNumber == 91)
+ else if (animFrame == 91)
playWav(2);
}
}
diff --git a/engines/hopkins/sound.h b/engines/hopkins/sound.h
index 97cdcdc1dd..1fb4f9ae71 100644
--- a/engines/hopkins/sound.h
+++ b/engines/hopkins/sound.h
@@ -116,7 +116,7 @@ public:
~SoundManager();
void loadAnimSound();
- void playAnimSound(int soundNumber);
+ void playAnimSound(int animFrame);
void loadSample(int wavIndex, const Common::String &file);
void playSample(int wavIndex, int voiceMode = 9);
diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp
index df7b26c82c..00c4ab0332 100644
--- a/engines/hopkins/talk.cpp
+++ b/engines/hopkins/talk.cpp
@@ -68,7 +68,7 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename)
getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer);
getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer);
getStringFromBuffer(20, _answersFilename, (const char *)_characterBuffer);
-
+
switch (_vm->_globals->_language) {
case LANG_FR:
_answersFilename = _questionsFilename = "RUE.TXT";
diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp
index fb51c05e51..cfd5f6ffc6 100644
--- a/engines/kyra/vqa.cpp
+++ b/engines/kyra/vqa.cpp
@@ -532,7 +532,7 @@ void VQADecoder::VQAVideoTrack::handleVQFR(Common::SeekableReadStream *stream) {
uint32 tag = readTag(stream);
uint32 i;
size = stream->readUint32BE();
-
+
switch (tag) {
case MKTAG('C','B','F','0'): // Full codebook
stream->read(_codeBook, size);
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 63a7e40d1b..94653f9a39 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -556,7 +556,7 @@ void Game::writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &hea
if (!_saveThumb)
createThumbnail();
Graphics::saveThumbnail(*out, *_saveThumb);
-
+
_saveThumb->free();
delete _saveThumb;
_saveThumb = nullptr;
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
index 03afc70c3e..ee4268a650 100644
--- a/engines/mads/menu_views.cpp
+++ b/engines/mads/menu_views.cpp
@@ -37,7 +37,7 @@ MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
}
void MenuView::show() {
- Scene &scene = _vm->_game->_scene;
+ Scene &scene = _vm->_game->_scene;
EventsManager &events = *_vm->_events;
_vm->_screenFade = SCREEN_FADE_FAST;
@@ -195,7 +195,7 @@ void TextView::processCommand() {
paramP = commandStr + 10;
resetPalette();
int screenId = getParameter(&paramP);
-
+
SceneInfo *sceneInfo = SceneInfo::init(_vm);
sceneInfo->load(screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
scene._spriteSlots.fullRefresh();
@@ -230,7 +230,7 @@ void TextView::processCommand() {
int soundId = getParameter(&paramP);
_vm->_sound->command(soundId);
- } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') ||
+ } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') ||
(commandStr[5] == '1'))) {
// Set the text colors
int index = commandStr[5] - '0';
@@ -254,7 +254,7 @@ void TextView::processCommand() {
sceneInfo->_width = MADS_SCREEN_WIDTH;
sceneInfo->_height = MADS_SCENE_HEIGHT;
_spareScreens[spareIndex].setSize(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
- sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
+ sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
_spareScreens[spareIndex]);
delete sceneInfo;
@@ -409,7 +409,7 @@ void TextView::doFrame() {
Common::copy(srcP, srcP + MADS_SCREEN_WIDTH, destP);
}
- Common::copy(linesTemp, linesTemp + _pan.y * MADS_SCREEN_WIDTH,
+ Common::copy(linesTemp, linesTemp + _pan.y * MADS_SCREEN_WIDTH,
(byte *)scene._backgroundSurface.getPixels());
delete[] linesTemp;
}
@@ -429,7 +429,7 @@ void TextView::doFrame() {
if (tl._pos.y < 0) {
_textLines.remove_at(i);
} else {
- tl._textDisplayIndex = scene._textDisplay.add(tl._pos.x, tl._pos.y,
+ tl._textDisplayIndex = scene._textDisplay.add(tl._pos.x, tl._pos.y,
0x605, -1, tl._line, _font);
}
}
@@ -537,7 +537,7 @@ bool AnimationView::onEvent(Common::Event &event) {
void AnimationView::doFrame() {
Scene &scene = _vm->_game->_scene;
-
+
if (_resourceIndex == -1 || _currentAnimation->freeFlag()) {
if (++_resourceIndex == (int)_resources.size()) {
scriptDone();
@@ -565,7 +565,7 @@ void AnimationView::loadNextResource() {
if (resEntry._bgFlag)
palette.resetGamePalette(1, 8);
- palette._mainPalette[253 * 3] = palette._mainPalette[253 * 3 + 1]
+ palette._mainPalette[253 * 3] = palette._mainPalette[253 * 3 + 1]
= palette._mainPalette[253 * 3 + 2] = 0xb4;
palette.setPalette(&palette._mainPalette[253 * 3], 253, 1);
@@ -587,7 +587,7 @@ void AnimationView::loadNextResource() {
delete _currentAnimation;
_currentAnimation = Animation::init(_vm, &scene);
int flags = ANIMFLAG_ANIMVIEW | (resEntry._bgFlag ? ANIMFLAG_LOAD_BACKGROUND : 0);
- _currentAnimation->load(scene._backgroundSurface, scene._depthSurface,
+ _currentAnimation->load(scene._backgroundSurface, scene._depthSurface,
resEntry._resourceName, flags, &paletteCycles, _sceneInfo);
// Signal for a screen refresh
@@ -656,7 +656,7 @@ void AnimationView::processLines() {
if (c != '\r' && c != '\0')
_currentLine += c;
}
-
+
// Process the line
while (!_currentLine.empty()) {
if (_currentLine.hasPrefix("-")) {
@@ -672,7 +672,7 @@ void AnimationView::processLines() {
}
// Add resource into list along with any set state information
- _resources.push_back(ResourceEntry(resName, _sfx, _soundFlag,
+ _resources.push_back(ResourceEntry(resName, _sfx, _soundFlag,
_bgLoadFlag, _showWhiteBars));
// Fx resets between resource entries
@@ -753,7 +753,7 @@ int AnimationView::getParameter() {
while (!_currentLine.empty()) {
char c = _currentLine[0];
-
+
if (c >= '0' && c <= '9') {
_currentLine.deleteChar(0);
result = result * 10 + (c - '0');
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index ebfb1f437a..650d7fdaee 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -223,8 +223,6 @@ public:
};
class DepthSurface : public MSurface {
-private:
- MADSEngine *_vm;
public:
/**
* Depth style
@@ -234,7 +232,7 @@ public:
/**
* Constructor
*/
- DepthSurface(MADSEngine *vm) : _vm(vm), _depthStyle(0) {}
+ DepthSurface() : _depthStyle(0) {}
/**
* Returns the depth at a given position
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index f51d046951..f5355517bd 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -908,7 +908,7 @@ void GameDialog::refreshText() {
}
if (!skipFlag) {
- _lines[i]._textDisplayIndex = scene._textDisplay.add(_lines[i]._pos.x, _lines[i]._pos.y,
+ _lines[i]._textDisplayIndex = scene._textDisplay.add(_lines[i]._pos.x, _lines[i]._pos.y,
fontColor, _lines[i]._widthAdjust, _lines[i]._msg, _lines[i]._font);
}
}
diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h
index d00cd87ead..5dbe4da6f0 100644
--- a/engines/mads/nebular/dialogs_nebular.h
+++ b/engines/mads/nebular/dialogs_nebular.h
@@ -116,7 +116,7 @@ class GameDialog: public FullScreenDialog {
Common::String _msg;
Font *_font;
int _widthAdjust;
-
+
DialogLine();
DialogLine(const Common::String &s);
};
@@ -130,7 +130,7 @@ protected:
int _menuSpritesIndex;
int _lineIndex;
int _textLineCount;
-
+
/**
* Display the dialog
*/
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index eae74d6da0..fd669bc5cf 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -625,7 +625,7 @@ void GameNebular::doObjectAction() {
_objects.addToInventory(OBJ_DURAFAIL_CELLS);
if (_difficulty == DIFFICULTY_HARD) {
dialogs.showItem(OBJ_DURAFAIL_CELLS, 416);
- }
+ }
_globals[kHandsetCellStatus] = 0;
break;
case 3:
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index f2f90e2291..28de4e5650 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -48,7 +48,7 @@ MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
_highlightedIndex = -1;
_selectedIndex = -1;
_buttonDown = false;
-
+
for (int i = 0; i < 7; ++i)
_menuItems[i] = nullptr;
}
@@ -85,7 +85,7 @@ void MainMenu::display() {
Common::Point pt(frame0->_offset.x - (frame0->w / 2),
frame0->_offset.y - frame0->h);
screenObjects.add(
- Common::Rect(pt.x, pt.y + DIALOG_TOP, pt.x + frame0->w,
+ Common::Rect(pt.x, pt.y + DIALOG_TOP, pt.x + frame0->w,
pt.y + frame0->h + DIALOG_TOP), LAYER_GUI, CAT_COMMAND, i);
}
@@ -126,7 +126,7 @@ void MainMenu::doFrame() {
// If the user has chosen to skip the animation, show the full menu immediately
if (_skipFlag && _menuItemIndex >= 0) {
- // Quickly loop through all the menu items to display each's final frame
+ // Quickly loop through all the menu items to display each's final frame
for (; _menuItemIndex < 6; ++_menuItemIndex) {
if (_menuItemIndex == 4 && !shouldShowQuotes())
continue;
@@ -161,7 +161,7 @@ void MainMenu::doFrame() {
void MainMenu::addSpriteSlot() {
Scene &scene = _vm->_game->_scene;
SpriteSlots &spriteSlots = scene._spriteSlots;
-
+
int seqIndex = (_menuItemIndex < 6) ? _menuItemIndex : _frameIndex;
spriteSlots.deleteTimer(seqIndex);
@@ -255,7 +255,7 @@ bool MainMenu::onEvent(Common::Event &event) {
}
return true;
- case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_MOUSEMOVE:
if (_buttonDown) {
int menuIndex = getHighlightedItem(event.mouse);
if (menuIndex != _highlightedIndex) {
@@ -287,7 +287,7 @@ bool MainMenu::onEvent(Common::Event &event) {
default:
break;
}
-
+
return false;
}
@@ -317,7 +317,7 @@ void MainMenu::handleAction(MADSGameAction action) {
break;
case RESUME_GAME:
- // The original resumed the most recently saved game. Instead,
+ // The original resumed the most recently saved game. Instead,
// just show the load game scren
_vm->_dialogs->_pendingDialog = DIALOG_RESTORE;
return;
@@ -354,7 +354,7 @@ void AdvertView::show() {
uint32 expiryTime = g_system->getMillis() + 10 * 1000;
_vm->_palette->resetGamePalette(4, 8);
-
+
// Load the advert background onto the screen
SceneInfo *sceneInfo = SceneInfo::init(_vm);
sceneInfo->load(screenId, 0, Common::String(), 0, _vm->_game->_scene._depthSurface,
diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp
index 13ee1a3dc1..679039535f 100644
--- a/engines/mads/nebular/nebular_scenes6.cpp
+++ b/engines/mads/nebular/nebular_scenes6.cpp
@@ -3155,7 +3155,7 @@ bool Scene611::check2ChargedBatteries() {
}
bool Scene611::check4ChargedBatteries() {
- if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS)
+ if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS)
&& _globals[kDurafailRecharged])
return true;
diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp
index 930bb7c250..0f019c4b19 100644
--- a/engines/mads/nebular/nebular_scenes7.cpp
+++ b/engines/mads/nebular/nebular_scenes7.cpp
@@ -2616,7 +2616,7 @@ void Scene752::actions() {
default:
break;
}
- } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT) &&
+ } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT) &&
(!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) {
switch (_game._trigger) {
case 0:
diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp
index 14f36756de..62a1a262b0 100644
--- a/engines/mads/nebular/nebular_scenes8.cpp
+++ b/engines/mads/nebular/nebular_scenes8.cpp
@@ -1098,7 +1098,7 @@ void Scene804::actions() {
_action.isAction(VERB_OPEN, NOUN_SERVICE_PANEL)) {
_scene->_nextSceneId = 805;
} else if ((_action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) && _globals[kTopButtonPushed]) {
- if (!_globals[kInSpace]) {
+ if (!_globals[kInSpace]) {
// Top button pressed on panel in hanger control
if (!_globals[kBeamIsUp]) {
_globals[kFromCockpit] = true;
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index 1787b3c298..836d04f7c0 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -233,7 +233,7 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) {
// CHECKME: When pressing on F1 in the first screen, newPalIndex is set to 0xFF at this point
// which is a valid value for the index. Maybe a better check would be "< 256" ?
//assert(newPalIndex != -1);
-
+
int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0;
_vm->_palette->_palFlags[newPalIndex] |= var52 | rgbMask;
@@ -342,7 +342,7 @@ int PaletteUsage::checkRGB(const byte *rgb, int palStart, bool flag, int *palInd
if ((!(*flagsP & 1) || flag) && !(*flagsP & 2)) {
if (!memcmp(palP, rgb, 3)) {
*flagsP |= mask;
-
+
if (palIndex)
*palIndex = result;
match = true;
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index 18ceb3c813..d2b4b29622 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -31,7 +31,7 @@
namespace MADS {
Scene::Scene(MADSEngine *vm)
- : _vm(vm), _action(_vm), _depthSurface(vm),
+ : _vm(vm), _action(_vm), _depthSurface(),
_dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm),
_kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm),
_textDisplay(vm), _userInterface(vm) {
@@ -182,7 +182,7 @@ void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY;
_animationData = Animation::init(_vm, this);
- DepthSurface depthSurface(_vm);
+ DepthSurface depthSurface;
_animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr);
_vm->_palette->_paletteUsage.load(&_scenePaletteUsage);
@@ -611,7 +611,7 @@ void Scene::loadAnimation(const Common::String &resName, int trigger) {
if (_activeAnimation)
freeAnimation();
- DepthSurface depthSurface(_vm);
+ DepthSurface depthSurface;
UserInterface interfaceSurface(_vm);
_activeAnimation = Animation::init(_vm, this);
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index b0a5aa35c6..b5e219ed04 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -264,7 +264,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
assert(asset && _depthStyle != 2);
MSprite *spr = asset->getFrame(asset->getCount() - 1);
- bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,
+ bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,
si._scale, spr->getTransparencyIndex());
}
diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp
index 07b1451718..05f00afb5a 100644
--- a/engines/mads/sequence.cpp
+++ b/engines/mads/sequence.cpp
@@ -473,7 +473,7 @@ int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTic
int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point(
frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2));
- return add(srcSpriteIndex, flipped, sprites->getCount(), triggerCountdown, timeoutTicks,
+ return add(srcSpriteIndex, flipped, sprites->getCount(), triggerCountdown, timeoutTicks,
extraTicks, numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_REVERSIBLE, 0, 0);
}
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 3d0bccc47f..cda0683028 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -2513,7 +2513,7 @@ void RivenExternal::xthideinventory(uint16 argc, uint16 *argv) {
static const uint32 kMarbleCount = 6;
static const int kSmallMarbleWidth = 4;
static const int kSmallMarbleHeight = 2;
-static const int kLargeMarbleSize = 8;
+//static const int kLargeMarbleSize = 8;
static const int kMarbleHotspotSize = 13;
static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "tblue", "tviolet" };
diff --git a/engines/mortevielle/detection_tables.h b/engines/mortevielle/detection_tables.h
index 0aa27b89eb..d244d15365 100644
--- a/engines/mortevielle/detection_tables.h
+++ b/engines/mortevielle/detection_tables.h
@@ -75,7 +75,7 @@ static const MortevielleGameDescription MortevielleGameDescriptions[] = {
// DOS English version doesn't exist. Technically, they are French or German versions,
// using English strings stored mort.dat
-
+
// English on top of French version
{
{
diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h
index c3d1e4ae8b..5f7f175c26 100644
--- a/engines/mortevielle/mortevielle.h
+++ b/engines/mortevielle/mortevielle.h
@@ -421,7 +421,7 @@ public:
byte *_curPict;
byte *_curAnim;
byte *_rightFramePict;
-
+
PaletteManager _paletteManager;
GfxSurface _backgroundSurface;
Common::RandomSource _randomSource;
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp
index d5dec6a286..40136ad78b 100644
--- a/engines/mortevielle/utils.cpp
+++ b/engines/mortevielle/utils.cpp
@@ -3097,7 +3097,7 @@ void MortevielleEngine::putObject() {
*/
void MortevielleEngine::addObjectToInventory(int objectId) {
int i;
-
+
for (i = 1; (i <= 5) && (_coreVar._inventory[i] != 0); i++)
;
diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp
index 91ab3e767a..7ee6b30311 100644
--- a/engines/neverhood/console.cpp
+++ b/engines/neverhood/console.cpp
@@ -55,7 +55,7 @@ bool Console::Cmd_Scene(int argc, const char **argv) {
const char *sceneTypes[] = { "normal", "smacker", "navigation" };
- debugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]);
+ debugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]);
if (sceneType == kSceneTypeNormal) {
Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject;
diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp
index 3acb952db9..4bfc10abbf 100644
--- a/engines/neverhood/modules/module2400.cpp
+++ b/engines/neverhood/modules/module2400.cpp
@@ -168,11 +168,6 @@ static const uint32 kScene2401FileHashes2[] = {
0xD0910068, 0xD09100A8, 0
};
-static const uint32 kScene2401FileHashes3[] = {
- 0xD0910020, 0xD0910038, 0xD0910008,
- 0xD0910068, 0xD09100A8, 0
-};
-
static const NRect kScene2401Rects[] = {
{ 369, 331, 394, 389 },
{ 395, 331, 419, 389 },
@@ -264,11 +259,11 @@ void Scene2401::update() {
} else if (_pipeStatus >= 5) {
_ssWaterPipes[_pipeStatus]->setVisible(true);
_countdown1 = 8;
- playPipeSound(kScene2401FileHashes3[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]);
+ playPipeSound(kScene2401FileHashes2[getSubVar(VA_CURR_WATER_PIPES_LEVEL, _pipeStatus - 5)]);
} else {
_ssWaterPipes[_pipeStatus]->setVisible(true);
_countdown1 = _pipeStatus == 4 ? 16 : 8;
- playPipeSound(kScene2401FileHashes3[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]);
+ playPipeSound(kScene2401FileHashes2[getSubVar(VA_GOOD_WATER_PIPES_LEVEL, _pipeStatus)]);
}
_pipeStatus++;
}
diff --git a/engines/neverhood/modules/module2700_sprites.cpp b/engines/neverhood/modules/module2700_sprites.cpp
index e17cddc834..079e0b7afe 100644
--- a/engines/neverhood/modules/module2700_sprites.cpp
+++ b/engines/neverhood/modules/module2700_sprites.cpp
@@ -24,62 +24,6 @@
namespace Neverhood {
-static const NRect kScene2710ClipRect = { 0, 0, 626, 480 };
-
-static const uint32 kScene2710StaticSprites[] = {
- 0x0D2016C0,
- 0
-};
-
-static const NRect kScene2711ClipRect = { 0, 0, 521, 480 };
-
-static const uint32 kScene2711FileHashes1[] = {
- 0,
- 0x100801A1,
- 0x201081A0,
- 0x006800A4,
- 0x40390120,
- 0x000001B1,
- 0x001000A1,
- 0
-};
-
-static const uint32 kScene2711FileHashes2[] = {
- 0,
- 0x40403308,
- 0x71403168,
- 0x80423928,
- 0x224131A8,
- 0x50401328,
- 0x70423328,
- 0
-};
-
-static const uint32 kScene2711FileHashes3[] = {
- 0,
- 0x1088A021,
- 0x108120E5,
- 0x18A02321,
- 0x148221A9,
- 0x10082061,
- 0x188820E1,
- 0
-};
-
-static const NRect kScene2724ClipRect = { 0, 141, 640, 480 };
-
-static const uint32 kScene2724StaticSprites[] = {
- 0xC20D00A5,
- 0
-};
-
-static const NRect kScene2725ClipRect = { 0, 0, 640, 413 };
-
-static const uint32 kScene2725StaticSprites[] = {
- 0xC20E00A5,
- 0
-};
-
static const NPoint kCarShadowOffsets[] = {
{-63, 3}, {-48, 40}, {-33, 58},
{ 0, 65}, { 40, 53}, { 56, 27},
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index a59c3f8156..ab22390c7d 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -1477,21 +1477,6 @@ static const uint32 kScene2808FileHashes2[] = {
0xB0196098
};
-static const uint32 kClass428FileHashes[] = {
- 0x140022CA,
- 0x4C30A602,
- 0xB1633402,
- 0x12982135,
- 0x0540B728,
- 0x002A81E3,
- 0x08982841,
- 0x10982841,
- 0x20982841,
- 0x40982841,
- 0x80982841,
- 0x40800711
-};
-
Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _testTubeSetNum(which), _leaveResult(0), _isFlowing(false) {
diff --git a/engines/neverhood/modules/module2800_sprites.cpp b/engines/neverhood/modules/module2800_sprites.cpp
index f9a58de92d..ad814d2b5b 100644
--- a/engines/neverhood/modules/module2800_sprites.cpp
+++ b/engines/neverhood/modules/module2800_sprites.cpp
@@ -574,16 +574,6 @@ uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam &param,
return messageResult;
}
-static const uint32 kScene2808FileHashes1[] = {
- 0x90B0392,
- 0x90B0192
-};
-
-static const uint32 kScene2808FileHashes2[] = {
- 0xB0396098,
- 0xB0196098
-};
-
static const uint32 kClass428FileHashes[] = {
0x140022CA,
0x4C30A602,
diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp
index d4809611ad..0f84dbd18d 100644
--- a/engines/neverhood/modules/module3000.cpp
+++ b/engines/neverhood/modules/module3000.cpp
@@ -666,18 +666,6 @@ static const uint32 kScene3010ButtonNameHashes[] = {
0x01180951
};
-static const uint32 kScene3010DeadBoltButtonFileHashes1[] = {
- 0x301024C2,
- 0x20280580,
- 0x30200452
-};
-
-static const uint32 kScene3010DeadBoltButtonFileHashes2[] = {
- 0x50C025A8,
- 0x1020A0A0,
- 0x5000A7E8
-};
-
Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) {
diff --git a/engines/neverhood/modules/module3000_sprites.cpp b/engines/neverhood/modules/module3000_sprites.cpp
index 3f883eaa72..23a388efe4 100644
--- a/engines/neverhood/modules/module3000_sprites.cpp
+++ b/engines/neverhood/modules/module3000_sprites.cpp
@@ -46,42 +46,6 @@ enum {
kCTSCount = 14
};
-static const uint32 kScene3009CannonScopeVideos[] = {
- 0x1010000D,
- 0x340A0049,
- 0x340A0049,
- 0x0282081D,
- 0x0082080D,
- 0x0882080D,
- 0x0882080D,
- 0x0282081D,
- 0x004B000B,
- 0x014B000B,
- 0x044B000B,
- 0x0282081D,
- 0x0282081D,
- 0x0282081D,
- 0x340A0049
-};
-
-static const uint32 kScene3009CannonActionVideos[] = {
- 0x00000000,
- 0x8004001B, // 1 Fire cannon at wall, it breaks (lowered)
- 0x0004001A, // 2 Fire cannon at wall, nothing happens (lowered)
- 0x1048404B, // 3 Fire cannon at emptyness (raised)
- 0x50200109, // 4 Fire cannon, robot missed (raised)
- 0x12032109, // 5 Fire cannon, robot hit (raised)
- 0x10201109, // 6 Fire cannon, no robot (raised)
- 0x000A2030, // 7 Raise the cannon
- 0x000A0028, // 8
- 0x000A0028, // 9
- 0x000A0028, // 10
- 0x040A1069, // 11
- 0x040A1069, // 12
- 0x040A1069, // 13
- 0x240A1101 // 14 Lower the cannon
-};
-
static const uint32 kSsScene3009SymbolEdgesFileHashes[] = {
0x618827A0,
0xB1A92322
diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp
index d53243d4ba..b15bea4a64 100644
--- a/engines/neverhood/sound.cpp
+++ b/engines/neverhood/sound.cpp
@@ -560,7 +560,7 @@ int NeverhoodAudioStream::readBuffer(int16 *buffer, const int numSamples) {
} else {
while (samplesRead--) {
*buffer++ = READ_LE_UINT16(src);
- src += 2;
+ src += 2;
}
}
diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
index e1b7e25cd5..73c319bd8b 100644
--- a/engines/pegasus/input.cpp
+++ b/engines/pegasus/input.cpp
@@ -57,7 +57,7 @@ InputDeviceManager::InputDeviceManager() {
_keyMap[Common::KEYCODE_p] = false;
_keyMap[Common::KEYCODE_TILDE] = false;
_keyMap[Common::KEYCODE_BACKQUOTE] = false;
- _keyMap[Common::KEYCODE_KP7] = false;
+ _keyMap[Common::KEYCODE_KP7] = false;
_keyMap[Common::KEYCODE_BACKSPACE] = false;
_keyMap[Common::KEYCODE_KP_MULTIPLY] = false;
_keyMap[Common::KEYCODE_KP9] = false;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 0c8ea2e4ee..4262ad4c12 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -979,7 +979,7 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) {
resetIntroTimer();
break;
case kMenuCmdPauseSave:
- result = showSaveDialog();
+ result = showSaveDialog();
if (result.getCode() != Common::kUserCanceled) {
if (result.getCode() != Common::kNoError)
diff --git a/engines/prince/animation.cpp b/engines/prince/animation.cpp
index b4bde27f69..aabdd7a623 100644
--- a/engines/prince/animation.cpp
+++ b/engines/prince/animation.cpp
@@ -132,7 +132,7 @@ int16 Animation::getPhaseOffsetX(int phaseIndex) const {
if (phaseIndex < _phaseCount) {
return _phaseList[phaseIndex]._phaseOffsetX;
} else {
- error("getPhaseOffsetX() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ error("getPhaseOffsetX() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
}
}
@@ -140,7 +140,7 @@ int16 Animation::getPhaseOffsetY(int phaseIndex) const {
if (phaseIndex < _phaseCount) {
return _phaseList[phaseIndex]._phaseOffsetY;
} else {
- error("getPhaseOffsetY() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ error("getPhaseOffsetY() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
}
}
@@ -148,7 +148,7 @@ int16 Animation::getPhaseFrameIndex(int phaseIndex) const {
if (phaseIndex < _phaseCount) {
return _phaseList[phaseIndex]._phaseToFrameIndex;
} else {
- error("getPhaseFrameIndex() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ error("getPhaseFrameIndex() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
}
}
diff --git a/engines/prince/animation.h b/engines/prince/animation.h
index 733acb399c..3471ffa158 100644
--- a/engines/prince/animation.h
+++ b/engines/prince/animation.h
@@ -35,7 +35,7 @@ public:
Animation();
~Animation();
bool loadStream(Common::SeekableReadStream &stream);
-
+
int16 getLoopCount() const;
int32 getPhaseCount() const;
int32 getFrameCount() const;
diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp
index ae6a2b7546..a01f824df8 100644
--- a/engines/prince/archive.cpp
+++ b/engines/prince/archive.cpp
@@ -64,7 +64,7 @@ bool PtcArchive::open(const Common::String &filename) {
byte *fileTableEnd = fileTable + fileTableSize;
_stream->read(fileTable, fileTableSize);
decrypt(fileTable, fileTableSize);
-
+
for (byte *fileItem = fileTable; fileItem < fileTableEnd; fileItem += 32) {
FileEntry item;
Common::String name = (const char*)fileItem;
@@ -79,6 +79,28 @@ bool PtcArchive::open(const Common::String &filename) {
return true;
}
+bool PtcArchive::openTranslation(const Common::String &filename) {
+ _stream = SearchMan.createReadStreamForMember(filename);
+ if (!_stream)
+ return false;
+
+ Common::Array<Common::String> translationNames;
+ Common::String translationFileName;
+ const int kTranslationFiles = 5;
+ for (int i = 0; i < kTranslationFiles; i++) {
+ translationFileName = _stream->readLine();
+ translationNames.push_back(translationFileName);
+ }
+ FileEntry item;
+ for (int i = 0; i < kTranslationFiles; i++) {
+ item._offset = _stream->readUint32LE();
+ item._size = _stream->readUint32LE();
+ _items[translationNames[i]] = item;
+ }
+
+ return true;
+}
+
void PtcArchive::close() {
delete _stream;
_stream = nullptr;
diff --git a/engines/prince/archive.h b/engines/prince/archive.h
index e211036ed6..a640b77911 100644
--- a/engines/prince/archive.h
+++ b/engines/prince/archive.h
@@ -35,6 +35,7 @@ public:
~PtcArchive();
bool open(const Common::String &filename);
+ bool openTranslation(const Common::String &filename);
void close();
bool isOpen() const { return _stream != 0; }
diff --git a/engines/prince/cursor.h b/engines/prince/cursor.h
index 9387f344dc..fb07d01729 100644
--- a/engines/prince/cursor.h
+++ b/engines/prince/cursor.h
@@ -30,7 +30,7 @@
namespace Prince {
class Cursor {
-public:
+public:
Cursor();
~Cursor();
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
index 3f83009de8..3fe7993fdb 100644
--- a/engines/prince/detection.cpp
+++ b/engines/prince/detection.cpp
@@ -55,13 +55,15 @@ bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
- (f == kSupportsListSaves);
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup);
}
bool Prince::PrinceEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
+ (f == kSupportsSavingDuringRuntime) ||
+ (f == kSupportsRTL);
}
} // End of namespace Prince
diff --git a/engines/prince/detection.h b/engines/prince/detection.h
index 5cc0d32be4..7e5bdd6b7b 100644
--- a/engines/prince/detection.h
+++ b/engines/prince/detection.h
@@ -28,9 +28,15 @@
namespace Prince {
+enum PrinceGameType {
+ kPrinceDataUNK,
+ kPrinceDataDE,
+ kPrinceDataPL
+};
+
struct PrinceGameDescription {
ADGameDescription desc;
- int gameType;
+ PrinceGameType gameType;
};
static const PlainGameDescriptor princeGames[] = {
@@ -49,7 +55,7 @@ static const PrinceGameDescription gameDescriptions[] = {
ADGF_TESTING,
GUIO1(GUIO_NONE)
},
- 0
+ kPrinceDataDE
},
{
{
@@ -61,9 +67,33 @@ static const PrinceGameDescription gameDescriptions[] = {
ADGF_TESTING,
GUIO1(GUIO_NONE)
},
- 1
+ kPrinceDataPL
+ },
+ {
+ {
+ "prince",
+ "The Prince and the Coward",
+ AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_TESTING,
+ GUIO1(GUIO_NONE)
+ },
+ kPrinceDataDE
+ },
+ {
+ {
+ "prince",
+ "The Prince and the Coward",
+ AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_TESTING,
+ GUIO1(GUIO_NONE)
+ },
+ kPrinceDataPL
},
- { AD_TABLE_END_MARKER, 0 }
+ { AD_TABLE_END_MARKER, kPrinceDataUNK }
};
const static char *directoryGlobs[] = {
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp
index ad6a2ff85c..f556d81eab 100644
--- a/engines/prince/graphics.cpp
+++ b/engines/prince/graphics.cpp
@@ -194,7 +194,7 @@ void GraphicsMan::drawTransparentDrawNode(Graphics::Surface *screen, DrawNode *d
/**
* Similar to drawTransparentDrawNode but with additional anti-aliasing code for sprite drawing.
* Edge smoothing is based on 256 x 256 table of colors transition.
- * Algorithm is checking if currently drawing pixel is located next to the edge of sprite and if it makes jagged line.
+ * Algorithm is checking if currently drawing pixel is located next to the edge of sprite and if it makes jagged line.
* If it does then this pixel is set with color from transition table calculated of original background pixel color
* and sprite's edge pixel color.
*/
diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h
index b6f002b7da..1a1737f976 100644
--- a/engines/prince/graphics.h
+++ b/engines/prince/graphics.h
@@ -35,7 +35,7 @@ class GraphicsMan {
public:
GraphicsMan(PrinceEngine *vm);
~GraphicsMan();
-
+
void update(Graphics::Surface *screen);
void change();
diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp
index 06fba25ba9..b873e83360 100644
--- a/engines/prince/hero.cpp
+++ b/engines/prince/hero.cpp
@@ -54,7 +54,7 @@ Hero::~Hero() {
bool Hero::loadAnimSet(uint32 animSetNr) {
_animSetNr = animSetNr;
- if (animSetNr > sizeof(heroSetTable)) {
+ if (animSetNr >= ARRAYSIZE(heroSetTable)) {
return false;
}
@@ -129,7 +129,7 @@ int Hero::getScaledValue(int size) {
Graphics::Surface *Hero::zoomSprite(Graphics::Surface *heroFrame) {
Graphics::Surface *zoomedFrame = new Graphics::Surface();
zoomedFrame->create(_scaledFrameXSize, _scaledFrameYSize, Graphics::PixelFormat::createFormatCLUT8());
-
+
int sprZoomX;
int sprZoomY = _vm->_scaleValue;
uint xSource = 0;
diff --git a/engines/prince/hero.h b/engines/prince/hero.h
index d5f7d8cc7a..703ef0650d 100644
--- a/engines/prince/hero.h
+++ b/engines/prince/hero.h
@@ -129,7 +129,7 @@ public:
void drawHeroShadow(Graphics::Surface *heroFrame);
void freeOldMove();
void freeHeroAnim();
-
+
uint16 _number;
uint16 _visible;
int16 _state;
@@ -170,7 +170,7 @@ public:
int _color; // subtitles color
uint32 _animSetNr; // number of animation set
Common::Array<Animation *> _moveSet; // MoveAnims MoveSet
-
+
uint32 _moveDelay;
uint32 _shadMinus;
diff --git a/engines/prince/mhwanh.cpp b/engines/prince/mhwanh.cpp
index ef94ef71f9..608ccc23d7 100644
--- a/engines/prince/mhwanh.cpp
+++ b/engines/prince/mhwanh.cpp
@@ -38,7 +38,7 @@ MhwanhDecoder::~MhwanhDecoder() {
void MhwanhDecoder::destroy() {
if (_surface != nullptr) {
_surface->free();
- delete _surface;
+ delete _surface;
_surface = nullptr;
}
if (_palette != nullptr) {
@@ -57,7 +57,7 @@ bool MhwanhDecoder::loadStream(Common::SeekableReadStream &stream) {
_palette[i * 3] = stream.readByte();
_palette[i * 3 + 1] = stream.readByte();
_palette[i * 3 + 2] = stream.readByte();
- }
+ }
_surface = new Graphics::Surface();
_surface->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
diff --git a/engines/prince/mob.h b/engines/prince/mob.h
index cc60e36f9b..0ea610dd8f 100644
--- a/engines/prince/mob.h
+++ b/engines/prince/mob.h
@@ -50,7 +50,7 @@ public:
void setData(AttrId dataId, uint16 value);
uint16 getData(AttrId dataId);
- bool _visible;
+ bool _visible;
uint16 _type;
uint16 _mask;
Common::Rect _rect;
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
index a9a96455b1..2dc5da68e7 100644
--- a/engines/prince/object.cpp
+++ b/engines/prince/object.cpp
@@ -79,7 +79,7 @@ bool Object::loadFromStream(Common::SeekableReadStream &stream) {
_flags = stream.readUint16LE();
_z = stream.readUint16LE();
-
+
stream.seek(pos + 16);
return true;
diff --git a/engines/prince/object.h b/engines/prince/object.h
index 68edd061a0..ff22a05805 100644
--- a/engines/prince/object.h
+++ b/engines/prince/object.h
@@ -62,7 +62,7 @@ public:
private:
void loadSurface(Common::SeekableReadStream &stream);
- Graphics::Surface *_surface;
+ Graphics::Surface *_surface;
};
} // End of namespace Prince
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
index 29c434e9c9..55f12a6560 100644
--- a/engines/prince/prince.cpp
+++ b/engines/prince/prince.cpp
@@ -61,6 +61,7 @@
#include "prince/animation.h"
#include "prince/option_text.h"
#include "prince/curve_values.h"
+#include "prince/detection.h"
namespace Prince {
@@ -95,7 +96,8 @@ PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc)
_tracePointFirstPointFlag(false), _coordsBuf2(nullptr), _coords2(nullptr), _coordsBuf3(nullptr), _coords3(nullptr),
_shanLen(0), _directionTable(nullptr), _currentMidi(0), _lightX(0), _lightY(0), _curveData(nullptr), _curvPos(0),
_creditsData(nullptr), _creditsDataSize(0), _currentTime(0), _zoomBitmap(nullptr), _shadowBitmap(nullptr), _transTable(nullptr),
- _flcFrameSurface(nullptr), _shadScaleValue(0), _shadLineLen(0), _scaleValue(0), _dialogImage(nullptr) {
+ _flcFrameSurface(nullptr), _shadScaleValue(0), _shadLineLen(0), _scaleValue(0), _dialogImage(nullptr), _mobTranslationData(nullptr),
+ _mobTranslationSize(0) {
// Debug/console setup
DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
@@ -204,6 +206,8 @@ PrinceEngine::~PrinceEngine() {
_dialogImage->free();
delete _dialogImage;
}
+
+ free(_mobTranslationData);
}
GUI::Debugger *PrinceEngine::getDebugger() {
@@ -213,11 +217,11 @@ GUI::Debugger *PrinceEngine::getDebugger() {
void PrinceEngine::init() {
const Common::FSNode gameDataDir(ConfMan.get("path"));
-
+
debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
PtcArchive *all = new PtcArchive();
- if (!all->open("all/databank.ptc"))
+ if (!all->open("all/databank.ptc"))
error("Can't open all/databank.ptc");
PtcArchive *voices = new PtcArchive();
@@ -228,11 +232,20 @@ void PrinceEngine::init() {
if (!sound->open("sound/databank.ptc"))
error("Can't open sound/databank.ptc");
+ PtcArchive *translation = new PtcArchive();
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ if (!translation->openTranslation("all/prince_translation.dat"))
+ error("Can't open prince_translation.dat");
+ }
+
SearchMan.addSubDirectoryMatching(gameDataDir, "all");
SearchMan.add("all", all);
SearchMan.add("voices", voices);
SearchMan.add("sound", sound);
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ SearchMan.add("translation", translation);
+ }
_graph = new GraphicsMan(this);
@@ -260,15 +273,24 @@ void PrinceEngine::init() {
_debugger = new Debugger(this, _flags);
_variaTxt = new VariaTxt();
- Resource::loadResource(_variaTxt, "variatxt.dat", true);
-
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ Resource::loadResource(_variaTxt, "variatxt.dat", true);
+ } else {
+ Resource::loadResource(_variaTxt, "variatxt_translate.dat", true);
+ }
+
_cursor1 = new Cursor();
Resource::loadResource(_cursor1, "mouse1.cur", true);
_cursor3 = new Cursor();
Resource::loadResource(_cursor3, "mouse2.cur", true);
- Common::SeekableReadStream *talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ Common::SeekableReadStream *talkTxtStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ } else {
+ talkTxtStream = SearchMan.createReadStreamForMember("talktxt_translate.dat");
+ }
if (!talkTxtStream) {
error("Can't load talkTxtStream");
return;
@@ -279,7 +301,12 @@ void PrinceEngine::init() {
delete talkTxtStream;
- Common::SeekableReadStream *invTxtStream = SearchMan.createReadStreamForMember("invtxt.dat");
+ Common::SeekableReadStream *invTxtStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ invTxtStream = SearchMan.createReadStreamForMember("invtxt.dat");
+ } else {
+ invTxtStream = SearchMan.createReadStreamForMember("invtxt_translate.dat");
+ }
if (!invTxtStream) {
error("Can't load invTxtStream");
return;
@@ -354,7 +381,12 @@ void PrinceEngine::init() {
_shadowLine = (byte *)malloc(kShadowLineArraySize);
- Common::SeekableReadStream *creditsDataStream = SearchMan.createReadStreamForMember("credits.dat");
+ Common::SeekableReadStream *creditsDataStream;
+ if (getLanguage() == Common::PL_POL || getLanguage() == Common::DE_DEU) {
+ creditsDataStream = SearchMan.createReadStreamForMember("credits.dat");
+ } else {
+ creditsDataStream = SearchMan.createReadStreamForMember("credits_translate.dat");
+ }
if (!creditsDataStream) {
error("Can't load creditsDataStream");
return;
@@ -363,11 +395,14 @@ void PrinceEngine::init() {
_creditsData = (byte *)malloc(_creditsDataSize);
creditsDataStream->read(_creditsData, _creditsDataSize);
delete creditsDataStream;
+
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ loadMobTranslationTexts();
+ }
}
void PrinceEngine::showLogo() {
MhwanhDecoder logo;
- _system->delayMillis(1000 / kFPS * 20);
if (Resource::loadResource(&logo, "logo.raw", true)) {
loadSample(0, "LOGO.WAV");
playSample(0, 0);
@@ -375,21 +410,58 @@ void PrinceEngine::showLogo() {
_graph->change();
_graph->update(_graph->_frontScreen);
setPalette(logo.getPalette());
- _system->delayMillis(1000 / kFPS * 70);
+
+ uint32 logoStart = _system->getMillis();
+ while (_system->getMillis() < logoStart + 5000) {
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ stopSample(0);
+ return;
+ }
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ stopSample(0);
+ return;
+ default:
+ break;
+ }
+ }
+
+ if (shouldQuit()) {
+ return;
+ }
+ }
}
}
Common::Error PrinceEngine::run() {
-
+ syncSoundSettings();
+ int startGameSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
init();
-
- showLogo();
-
+ if (startGameSlot == -1) {
+ showLogo();
+ } else {
+ loadLocation(59); // load intro location - easiest way to set everything up
+ loadGame(startGameSlot);
+ }
mainLoop();
-
return Common::kNoError;
}
+void PrinceEngine::pauseEngineIntern(bool pause) {
+ Engine::pauseEngineIntern(pause);
+ if (pause) {
+ _midiPlayer->pause();
+ }
+ else {
+ _midiPlayer->resume();
+ }
+}
+
bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
int32 pos = stream.pos();
@@ -469,13 +541,17 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
loadMobPriority("mobpri");
_mobList.clear();
- if (getLanguage() == Common::DE_DEU) {
+ if (getGameType() == kPrinceDataDE) {
const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
debug("name: %s", mobLstName.c_str());
Resource::loadResource(_mobList, mobLstName.c_str(), false);
- } else {
+ } else if (getGameType() == kPrinceDataPL) {
Resource::loadResource(_mobList, "mob.lst", false);
}
+ if (getLanguage() != Common::PL_POL && getLanguage() != Common::DE_DEU) {
+ // update Mob texts for translated version
+ setMobTranslationTexts();
+ }
_animList.clear();
Resource::loadResource(_animList, "anim.lst", false);
@@ -678,7 +754,11 @@ void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
return;
}
_audioStream[sampleId]->rewind();
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ if (sampleId < 28) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ } else {
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ }
}
}
@@ -705,7 +785,7 @@ void PrinceEngine::freeAllSamples() {
}
bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
- // FIXME: This is just a workaround streamName is a path
+ // FIXME: This is just a workaround streamName is a path
// SOUND\\SCIERKA1.WAV for now only last path component is used
Common::String normalizedPath = lastPathComponent(streamName, '\\');
@@ -730,8 +810,8 @@ bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamNam
bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
- if (slot > kMaxTexts) {
- error("Text slot bigger than MAXTEXTS %d", kMaxTexts);
+ if (slot >= kMaxTexts) {
+ error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
return false;
}
@@ -756,7 +836,7 @@ bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::Strin
}
id = sampleStream->readUint32LE();
- debugEngine("SetVoice slot %d time %04x", slot, id);
+ debugEngine("SetVoice slot %d time %04x", slot, id);
id <<= 3;
id /= 22050;
id += 2;
@@ -768,7 +848,7 @@ bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::Strin
_secondHero->_talkTime = id;
}
- debugEngine("SetVoice slot %d time %04x", slot, id);
+ debugEngine("SetVoice slot %d time %04x", slot, id);
sampleStream->seek(SEEK_SET);
_audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
delete sampleStream;
@@ -947,6 +1027,45 @@ bool PrinceEngine::loadMobPriority(const char *resourceName) {
return true;
}
+void PrinceEngine::loadMobTranslationTexts() {
+ Common::SeekableReadStream *mobTranslationStream = SearchMan.createReadStreamForMember("mob_translate.dat");
+ if (!mobTranslationStream) {
+ error("Can't load mob_translate.dat");
+ }
+ _mobTranslationSize = mobTranslationStream->size();
+ _mobTranslationData = (byte *)malloc(_mobTranslationSize);
+ mobTranslationStream->read(_mobTranslationData, _mobTranslationSize);
+ delete mobTranslationStream;
+}
+
+void PrinceEngine::setMobTranslationTexts() {
+ int locationOffset = READ_UINT16(_mobTranslationData + (_locationNr - 1) * 2);
+ if (locationOffset) {
+ byte *locationText = _mobTranslationData + locationOffset;
+ for (uint i = 0; i < _mobList.size(); i++) {
+ byte c;
+ locationText++;
+ _mobList[i]._name.clear();
+ while ((c = *locationText)) {
+ _mobList[i]._name += c;
+ locationText++;
+ }
+ locationText++;
+ _mobList[i]._examText.clear();
+ c = *locationText;
+ locationText++;
+ if (c) {
+ _mobList[i]._examText += c;
+ do {
+ c = *locationText;
+ _mobList[i]._examText += c;
+ locationText++;
+ } while (c != 255);
+ }
+ }
+ }
+}
+
void PrinceEngine::keyHandler(Common::Event event) {
uint16 nChar = event.kbd.keycode;
switch (nChar) {
@@ -1506,7 +1625,7 @@ void PrinceEngine::setBackAnim(Anim &backAnim) {
}
void PrinceEngine::showBackAnims() {
- for (uint i = 0; i < kMaxBackAnims; i++) {
+ for (int i = 0; i < kMaxBackAnims; i++) {
BAS &seq = _backAnimList[i]._seq;
int activeSubAnim = seq._currRelative;
if (!_backAnimList[i].backAnims.empty()) {
@@ -1893,7 +2012,7 @@ void PrinceEngine::blackPalette() {
free(blackPalette1);
return;
}
- pause();
+ pausePrinceEngine();
}
free(paletteBackup);
free(blackPalette1);
@@ -1901,41 +2020,34 @@ void PrinceEngine::blackPalette() {
void PrinceEngine::setPalette(const byte *palette) {
if (palette != nullptr) {
- byte *blackPalette = (byte *)malloc(256 * 3);
+ byte *blackPalette_ = (byte *)malloc(256 * 3);
int fadeStep = 0;
for (int i = 0; i <= kFadeStep; i++) {
for (int j = 0; j < 256; j++) {
- blackPalette[3 * j] = palette[3 * j] * fadeStep / 4;
- blackPalette[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
- blackPalette[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
+ blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
+ blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
+ blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
}
fadeStep++;
- _graph->setPalette(blackPalette);
+ _graph->setPalette(blackPalette_);
_system->updateScreen();
Common::Event event;
Common::EventManager *eventMan = _system->getEventManager();
eventMan->pollEvent(event);
if (shouldQuit()) {
_graph->setPalette(palette);
- free(blackPalette);
+ free(blackPalette_);
return;
}
- pause();
+ pausePrinceEngine();
}
_graph->setPalette(palette);
- free(blackPalette);
+ free(blackPalette_);
}
}
-void PrinceEngine::pause() {
- int delay = 1000 / kFPS - int32(_system->getMillis() - _currentTime);
- delay = delay < 0 ? 0 : delay;
- _system->delayMillis(delay);
- _currentTime = _system->getMillis();
-}
-
-void PrinceEngine::pause2() {
- int delay = 1000 / (kFPS * 2) - int32(_system->getMillis() - _currentTime);
+void PrinceEngine::pausePrinceEngine(int fps) {
+ int delay = 1000 / fps - int32(_system->getMillis() - _currentTime);
delay = delay < 0 ? 0 : delay;
_system->delayMillis(delay);
_currentTime = _system->getMillis();
@@ -2048,7 +2160,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
while (_mst_shadow2 > 256) {
rememberScreenInv();
@@ -2062,7 +2174,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
} else {
//CURSEBLINK:
@@ -2080,7 +2192,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
while (_mst_shadow2 > 256) {
rememberScreenInv();
@@ -2094,7 +2206,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
}
}
@@ -2110,7 +2222,7 @@ void PrinceEngine::addInvObj() {
if (shouldQuit()) {
return;
}
- pause();
+ pausePrinceEngine();
}
}
@@ -2305,6 +2417,7 @@ void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFl
}
void PrinceEngine::leftMouseButton() {
+ _flags->setFlagValue(Flags::ESCAPED2, 1); // skip intro animation
_flags->setFlagValue(Flags::LMOUSE, 1);
if (_flags->getFlagValue(Flags::POWERENABLED)) {
_flags->setFlagValue(Flags::MBFLAG, 1);
@@ -2738,7 +2851,7 @@ void PrinceEngine::displayInventory() {
getDebugger()->onFrame();
_graph->update(_graph->_screenForInventory);
- pause();
+ pausePrinceEngine();
}
if (_currentPointerNumber == 2) {
@@ -2863,7 +2976,7 @@ void PrinceEngine::dialogRun() {
getDebugger()->onFrame();
_graph->update(_graph->_frontScreen);
- pause();
+ pausePrinceEngine();
}
_dialogImage->free();
delete _dialogImage;
@@ -3122,7 +3235,7 @@ void PrinceEngine::scrollCredits() {
}
_graph->change();
_graph->update(_graph->_frontScreen);
- pause2();
+ pausePrinceEngine(kFPS * 2);
}
char letter2;
byte *scan2 = scrollAdress;
@@ -4106,7 +4219,7 @@ int PrinceEngine::checkRightUpDir() {
}
bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
- for (int i = 0; i < kPathBitmapLen; i++) {
+ for (uint i = 0; i < kPathBitmapLen; i++) {
_roomPathBitmapTemp[i] = 0;
}
if (x1 != x2 || y1 != y2) {
@@ -4321,7 +4434,7 @@ int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDi
tempCoordsBuf += 4;
if (tempCoordsBuf == _coords) {
- direction = tempX;
+ direction = tempX;
break;
}
@@ -4726,7 +4839,7 @@ void PrinceEngine::mainLoop() {
openInventoryCheck();
- pause();
+ pausePrinceEngine();
}
}
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
index 0e5bf97dde..6dce044a41 100644
--- a/engines/prince/prince.h
+++ b/engines/prince/prince.h
@@ -242,7 +242,7 @@ struct DebugChannel {
enum Type {
kScript,
- kEngine
+ kEngine
};
};
@@ -256,6 +256,7 @@ public:
virtual ~PrinceEngine();
virtual bool hasFeature(EngineFeature f) const;
+ virtual void pauseEngineIntern(bool pause);
virtual bool canSaveGameStateCurrently();
virtual bool canLoadGameStateCurrently();
virtual Common::Error saveGameState(int slot, const Common::String &desc);
@@ -285,6 +286,9 @@ public:
uint32 _talkTxtSize;
byte *_talkTxt;
+ uint32 _mobTranslationSize;
+ byte *_mobTranslationData;
+
bool loadLocation(uint16 locationNr);
bool loadAnim(uint16 animNr, bool loop);
bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name);
@@ -294,6 +298,9 @@ public:
bool loadTrans(byte *transTable, const char *resourceName);
bool loadMobPriority(const char *resourceName);
+ void loadMobTranslationTexts();
+ void setMobTranslationTexts();
+
bool loadMusic(int musNumber);
void stopMusic();
@@ -365,7 +372,7 @@ public:
static const int16 kZoomBitmapHeight = kMaxPicHeight / kZoomStep;
static const int16 kNormalWidth = 640;
static const int16 kNormalHeight = 480;
- static const int32 kTransTableSize = 256 * 256;
+ static const uint32 kTransTableSize = 256 * 256;
static const int kMaxNormAnims = 64;
static const int kMaxBackAnims = 64;
@@ -401,7 +408,7 @@ public:
int _currentPointerNumber;
static const int16 kMaxInv = 90; // max amount of inventory items in whole game
- static const int16 kMaxItems = 30; // size of inventory
+ static const uint16 kMaxItems = 30; // size of inventory
uint32 _invTxtSize;
byte *_invTxt;
@@ -530,7 +537,7 @@ public:
// Pathfinding
static const int16 kPathGridStep = 2;
- static const int32 kPathBitmapLen = (kMaxPicHeight / kPathGridStep * kMaxPicWidth / kPathGridStep) / 8;
+ static const uint32 kPathBitmapLen = (kMaxPicHeight / kPathGridStep * kMaxPicWidth / kPathGridStep) / 8;
static const int32 kTracePts = 8000;
static const int32 kPBW = kMaxPicWidth / 16; // PathBitmapWidth
static const int kMinDistance = 2500;
@@ -633,8 +640,7 @@ private:
static bool compareDrawNodes(DrawNode d1, DrawNode d2);
void runDrawNodes();
void makeShadowTable(int brightness);
- void pause();
- void pause2();
+ void pausePrinceEngine(int fps = kFPS);
uint32 getTextWidth(const char *s);
void debugEngine(const char *s, ...);
@@ -658,7 +664,7 @@ private:
Common::Array<Mob> _invMobList;
bool _flicLooped;
-
+
void mainLoop();
};
diff --git a/engines/prince/pscr.h b/engines/prince/pscr.h
index d59fa37d81..fdcdb524a9 100644
--- a/engines/prince/pscr.h
+++ b/engines/prince/pscr.h
@@ -40,7 +40,7 @@ public:
Graphics::Surface *getSurface() const { return _surface; }
private:
void loadSurface(Common::SeekableReadStream &stream);
- Graphics::Surface *_surface;
+ Graphics::Surface *_surface;
};
} // End of namespace Prince
diff --git a/engines/prince/resource.h b/engines/prince/resource.h
index b1fbd9c4f0..f42eb87842 100644
--- a/engines/prince/resource.h
+++ b/engines/prince/resource.h
@@ -41,13 +41,13 @@ namespace Resource {
bool loadResource(T *resource, const char *resourceName, bool required) {
Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
if (!stream) {
- if (required)
+ if (required)
error("Can't load %s", resourceName);
return false;
}
return loadFromStream(*resource, *stream);
- }
+ }
template <typename T>
bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
@@ -82,7 +82,7 @@ namespace Resource {
}
// FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initiailzed object
- while (true) {
+ while (true) {
T* t = new T();
if (!t->loadFromStream(*stream)) {
delete t;
diff --git a/engines/prince/saveload.cpp b/engines/prince/saveload.cpp
index 39a4002b40..46e598be70 100644
--- a/engines/prince/saveload.cpp
+++ b/engines/prince/saveload.cpp
@@ -172,14 +172,34 @@ void PrinceMetaEngine::removeSaveState(const char *target, int slot) const {
g_system->getSavefileManager()->removeSavefile(fileName);
}
-// TODO
bool PrinceEngine::canSaveGameStateCurrently() {
- return true;
+ if (_mouseFlag && _mouseFlag != 3) {
+ if (_mainHero->_visible) {
+ // 29 - Basement
+ if (_locationNr != 29) {
+ // No dialog box and not in inventory
+ if (!_dialogFlag && !_showInventoryFlag) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
-// TODO
bool PrinceEngine::canLoadGameStateCurrently() {
- return true;
+ if (_mouseFlag && _mouseFlag != 3) {
+ if (_mainHero->_visible) {
+ // 29 - Basement
+ if (_locationNr != 29) {
+ // No dialog box and not in inventory
+ if (!_dialogFlag && !_showInventoryFlag) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
Common::Error PrinceEngine::saveGameState(int slot, const Common::String &desc) {
@@ -480,7 +500,7 @@ bool PrinceEngine::loadGame(int slotNumber) {
saveFile->read(dataBuffer, size);
readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
delete saveFile;
-
+
// Check to see if it's a ScummVM savegame or not
char buffer[kSavegameStrSize + 1];
readStream->read(buffer, kSavegameStrSize + 1);
@@ -505,9 +525,6 @@ bool PrinceEngine::loadGame(int slotNumber) {
syncGame(readStream, nullptr);
delete readStream;
- // TODO
- //syncSpeechSettings();
-
return true;
}
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
index 0e9dd27877..4ed3cee6f3 100644
--- a/engines/prince/script.cpp
+++ b/engines/prince/script.cpp
@@ -43,7 +43,7 @@ Room::Room() {}
bool Room::loadRoom(byte *roomData) {
int roomSize = 64;
Common::MemoryReadStream roomStream(roomData, roomSize);
-
+
_mobs = roomStream.readSint32LE();
_backAnim = roomStream.readSint32LE();
_obj = roomStream.readSint32LE();
@@ -131,7 +131,7 @@ bool Script::loadStream(Common::SeekableReadStream &stream) {
_scriptInfo.invObjGive = scriptDataStream.readSint32LE();
_scriptInfo.stdGiveItem = scriptDataStream.readSint32LE();
_scriptInfo.goTester = scriptDataStream.readSint32LE();
-
+
return true;
}
@@ -391,10 +391,10 @@ bool Script::loadAllMasks(Common::Array<Mask> &maskList, int offset) {
debug("Can't load %s", msStreamName.c_str());
delete msStream;
} else {
- uint32 dataSize = msStream->size();
+ int32 dataSize = msStream->size();
if (dataSize != -1) {
tempMask._data = (byte *)malloc(dataSize);
- if (msStream->read(tempMask._data, dataSize) != dataSize) {
+ if (msStream->read(tempMask._data, dataSize) != (uint32)dataSize) {
free(tempMask._data);
delete msStream;
return false;
@@ -427,7 +427,7 @@ int32 InterpreterFlags::getFlagValue(Flags::Id flagId) {
return _flags[(uint32)flagId - kFlagMask];
}
-Interpreter::Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags) :
+Interpreter::Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags) :
_vm(vm), _script(script), _flags(flags),
_stacktop(0), _opcodeNF(false), _opcodeEnd(false),
_waitFlag(0), _result(true) {
@@ -477,10 +477,10 @@ uint32 Interpreter::step(uint32 opcodePC) {
// Get the current opcode
_lastOpcode = readScript16();
- if (_lastOpcode > kNumOpcodes)
+ if (_lastOpcode >= kNumOpcodes)
error(
- "Trying to execute unknown opcode @0x%04X: %02d",
- _currentInstruction,
+ "Trying to execute unknown opcode @0x%04X: %02d",
+ _currentInstruction,
_lastOpcode);
// Execute the current opcode
@@ -570,7 +570,7 @@ int32 Interpreter::readScriptFlagValue() {
return value;
}
-Flags::Id Interpreter::readScriptFlagId() {
+Flags::Id Interpreter::readScriptFlagId() {
return (Flags::Id)readScript16();
}
@@ -722,6 +722,17 @@ void Interpreter::O_PUTBACKANIM() {
_vm->_script->installSingleBackAnim(_vm->_backAnimList, slot, room->_backAnim);
}
delete room;
+
+ // WALKAROUND: fix for turning on 'walking bird' background animation too soon,
+ // after completing 'throw a rock' mini-game in Silmaniona location.
+ // Second bird shouldn't appear when normal animation is still in use
+ // in script lines 13814 and 13848
+ if (_currentInstruction == kSecondBirdAnimationScriptFix) {
+ if (_vm->_normAnimList[1]._state == 0) {
+ _vm->_backAnimList[0].backAnims[0]._state = 1;
+ }
+ }
+
debugInterpreter("O_PUTBACKANIM roomId %d, slot %d, animId %d", roomId, slot, animId);
}
@@ -1629,7 +1640,7 @@ void Interpreter::O_BACKANIMRANGE() {
}
void Interpreter::O_CLEARPATH() {
- for (int i = 0; i < _vm->kPathBitmapLen; i++) {
+ for (uint i = 0; i < _vm->kPathBitmapLen; i++) {
_vm->_roomPathBitmap[i] = 255;
}
debugInterpreter("O_CLEARPATH");
@@ -1689,7 +1700,7 @@ void Interpreter::O_POPSTRING() {
void Interpreter::O_SETFGCODE() {
int32 offset = readScript32();
- _fgOpcodePC = _currentInstruction + offset - 4;
+ _fgOpcodePC = _currentInstruction + offset - 4;
debugInterpreter("O_SETFGCODE next %08x, offset %08x", _fgOpcodePC, offset);
}
diff --git a/engines/prince/script.h b/engines/prince/script.h
index 4799e84944..fe79cf5f96 100644
--- a/engines/prince/script.h
+++ b/engines/prince/script.h
@@ -241,7 +241,8 @@ private:
typedef void (Interpreter::*OpcodeFunc)();
static OpcodeFunc _opcodes[];
- static const int kGiveLetterScriptFix = 79002;
+ static const uint kGiveLetterScriptFix = 79002;
+ static const uint kSecondBirdAnimationScriptFix = 45658;
// Keep opcode handlers names as they are in original code
// making it easier to switch back and forth
diff --git a/engines/queen/logic.cpp b/engines/queen/logic.cpp
index d48bb8a498..664a9a15f9 100644
--- a/engines/queen/logic.cpp
+++ b/engines/queen/logic.cpp
@@ -2115,9 +2115,15 @@ void LogicInterview::setupSpecialMoveTable() {
}
void LogicGame::useJournal() {
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
+
_vm->command()->clear(false);
_journal->use();
_vm->walk()->stopJoe();
+
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
}
bool LogicGame::changeToSpecialRoom() {
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index 1b9d72babc..e86a53d448 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -189,7 +189,7 @@ void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) {
}
}
- if (_vm->input()->talkQuit())
+ if (_vm->input()->talkQuit() || _vm->shouldQuit())
break;
retval = _dialogueTree[level][selectedSentence].dialogueNodeValue1;
@@ -1250,15 +1250,12 @@ int16 Talk::selectSentence() {
}
_vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
if (sentenceCount > 0) {
int oldZone = 0;
- while (0 == selectedSentence) {
-
- if (_vm->input()->talkQuit())
- break;
-
+ while (0 == selectedSentence && !_vm->input()->talkQuit() && !_vm->shouldQuit()) {
_vm->update();
Common::Point mouse = _vm->input()->getMousePos();
@@ -1328,6 +1325,9 @@ int16 Talk::selectSentence() {
}
}
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
+
debug(6, "Selected sentence %i", selectedSentence);
arrowBobUp->active = false;
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index b8a5436d76..8dc27c74be 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -468,7 +468,6 @@ public:
int actorIdToIndex(uint16 id) { return (id == ID_PROTAG) ? 0 : objectIdToIndex(id); }
uint16 actorIndexToId(int index) { return (index == 0) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); }
ActorData *getActor(uint16 actorId);
- ActorData *getFirstActor() { return &_actors.front(); }
// clarification: Obj - means game object, such Hat, Spoon etc, Object - means Actor,Obj,HitZone,StepZone
diff --git a/engines/saga/introproc_ite.cpp b/engines/saga/introproc_ite.cpp
index 0c1a2ce233..0b129dbcc0 100644
--- a/engines/saga/introproc_ite.cpp
+++ b/engines/saga/introproc_ite.cpp
@@ -374,7 +374,7 @@ int Scene::ITEIntroCaveCommonProc(int param, int caveScene) {
lang = 2;
int n_dialogues = 0;
-
+
switch (caveScene) {
case 1:
n_dialogues = ARRAYSIZE(introDialogueCave1[lang]);
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index 90ba62070b..e659e09ce8 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -215,8 +215,7 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
#ifdef ENABLE_IHNM
if (getGameId() == GID_IHNM) {
out->writeSint32LE(_scene->currentChapterNumber());
- // Protagonist
- out->writeSint32LE(_scene->currentProtag());
+ out->writeSint32LE(0); // obsolete, was used for the protagonist
out->writeSint32LE(_scene->getCurrentMusicTrack());
out->writeSint32LE(_scene->getCurrentMusicRepeat());
}
@@ -316,7 +315,7 @@ void SagaEngine::load(const char *fileName) {
if (getGameId() == GID_IHNM) {
int currentChapter = _scene->currentChapterNumber();
_scene->setChapterNumber(in->readSint32LE());
- _scene->setProtag(in->readSint32LE());
+ in->skip(4); // obsolete, was used for setting the protagonist
if (_scene->currentChapterNumber() != currentChapter)
_scene->changeScene(-2, 0, kTransitionFade, _scene->currentChapterNumber());
_scene->setCurrentMusicTrack(in->readSint32LE());
@@ -366,30 +365,6 @@ void SagaEngine::load(const char *fileName) {
int volume = _music->getVolume();
_music->setVolume(0);
-#ifdef ENABLE_IHNM
- // Protagonist swapping
- if (getGameId() == GID_IHNM) {
- if (_scene->currentProtag() != 0 && _scene->currentChapterNumber() != 6) {
- ActorData *actor1 = _actor->getFirstActor();
- ActorData *actor2;
- // The original gets actor2 from the current protagonist ID, but this is sometimes wrong
- // If the current protagonist ID is not correct, use the stored protagonist
- if (!_actor->validActorId(_scene->currentProtag())) {
- actor2 = _actor->_protagonist;
- } else {
- actor2 = _actor->getActor(_scene->currentProtag());
- }
-
- SWAP(actor1->_location, actor2->_location);
-
- actor2->_flags &= ~kProtagonist;
- actor1->_flags |= kProtagonist;
- _actor->_protagonist = _actor->_centerActor = actor1;
- _scene->setProtag(actor1->_id);
- }
- }
-#endif
-
_scene->clearSceneQueue();
_scene->changeScene(sceneNumber, ACTOR_NO_ENTRANCE, kTransitionNoFade);
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index 6a9571d282..410713c5d5 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -286,8 +286,6 @@ class Scene {
#endif
return _sceneLUT[sceneNumber];
}
- int currentProtag() const { return _currentProtag; }
- void setProtag(int pr) { _currentProtag = pr; }
int currentSceneNumber() const { return _sceneNumber; }
int currentChapterNumber() const { return _chapterNumber; }
void setChapterNumber(int ch) { _chapterNumber = ch; }
@@ -341,7 +339,6 @@ class Scene {
Common::Array<uint16> _sceneLUT;
SceneQueueList _sceneQueue;
bool _sceneLoaded;
- int _currentProtag;
int _sceneNumber;
int _chapterNumber;
int _outsetSceneNumber;
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index cb963e23ac..2175d8f40a 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -748,14 +748,10 @@ void Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
actor1->_flags &= ~kProtagonist;
actor2->_flags |= kProtagonist;
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor2;
- if (_vm->getGameId() == GID_IHNM)
- _vm->_scene->setProtag(actorId2);
} else if (actor2->_flags & kProtagonist) {
actor2->_flags &= ~kProtagonist;
actor1->_flags |= kProtagonist;
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor1;
- if (_vm->getGameId() == GID_IHNM)
- _vm->_scene->setProtag(actorId1);
}
}
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 565e9752c3..e233c4cba4 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -485,6 +485,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
#endif
debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
+ debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette->isUsing16bitColorMatch() ? "yes" : "no");
debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
@@ -663,7 +664,7 @@ bool Console::cmdDiskDump(int argc, const char **argv) {
int resNumFrom = 0;
int resNumTo = 0;
int resNumCur = 0;
-
+
if (argc != 3) {
debugPrintf("Dumps the specified resource to disk as a patch file\n");
debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]);
@@ -671,7 +672,7 @@ bool Console::cmdDiskDump(int argc, const char **argv) {
cmdResourceTypes(argc, argv);
return true;
}
-
+
if (strcmp(argv[2], "*") == 0) {
resNumFrom = 0;
resNumTo = 65535;
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index dddf845222..a65bcb7df5 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -145,7 +145,7 @@ public:
*/
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
-
+
void init();
uint getSelectorNamesSize() const;
@@ -161,7 +161,7 @@ public:
* @return The appropriate selector ID, or -1 on error
*/
int findSelector(const char *selectorName) const;
-
+
bool selectorNamesAvailable();
// Script dissection/dumping functions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index c2089bcd4d..ee2249bd9d 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -354,13 +354,16 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
}
textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();
+
+ uint16 languageSplitter = 0;
+ Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, sep);
#ifdef ENABLE_SCI32
if (g_sci->_gfxText32)
- g_sci->_gfxText32->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText32->kernelTextSize(splitText.c_str(), font_nr, maxwidth, &textWidth, &textHeight);
else
#endif
- g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight);
// One of the game texts in LB2 German contains loads of spaces in
// its end. We trim the text here, otherwise the graphics code will
@@ -376,7 +379,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
// Copy over the trimmed string...
s->_segMan->strcpy(argv[1], text.c_str());
// ...and recalculate bounding box dimensions
- g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight);
}
}
@@ -818,16 +821,29 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
if (!textReference.isNull())
text = s->_segMan->getString(textReference);
+ uint16 languageSplitter = 0;
+ Common::String splitText;
+
+ switch (type) {
+ case SCI_CONTROLS_TYPE_BUTTON:
+ case SCI_CONTROLS_TYPE_TEXTEDIT:
+ splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, NULL);
+ break;
+ case SCI_CONTROLS_TYPE_TEXT:
+ splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter);
+ break;
+ }
+
switch (type) {
case SCI_CONTROLS_TYPE_BUTTON:
debugC(kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d", PRINT_REG(controlObject), x, y);
- g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, style, hilite);
+ g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, splitText.c_str(), languageSplitter, fontId, style, hilite);
return;
case SCI_CONTROLS_TYPE_TEXT:
alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode));
debugC(kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment);
- g_sci->_gfxControls16->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite);
+ g_sci->_gfxControls16->kernelDrawText(rect, controlObject, splitText.c_str(), languageSplitter, fontId, alignment, style, hilite);
s->r_acc = g_sci->_gfxText16->allocAndFillReferenceRectArray();
return;
@@ -841,7 +857,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos);
}
debugC(kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y);
- g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite);
+ g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, splitText.c_str(), languageSplitter, fontId, mode, style, cursorPos, maxChars, hilite);
return;
case SCI_CONTROLS_TYPE_ICON:
@@ -1165,8 +1181,11 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) {
argc--; argc--; argv++; argv++;
text = g_sci->getKernel()->lookupText(textp, index);
}
+
+ uint16 languageSplitter = 0;
+ Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter);
- return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv);
+ return g_sci->_gfxPaint16->kernelDisplay(splitText.c_str(), languageSplitter, argc, argv);
}
reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) {
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 56dad583e4..eef758a0d9 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -42,10 +42,12 @@ reg_t kStrCat(EngineState *s, int argc, reg_t *argv) {
Common::String s1 = s->_segMan->getString(argv[0]);
Common::String s2 = s->_segMan->getString(argv[1]);
- // The Japanese version of PQ2 splits the two strings here
- // (check bug #3396887).
- if (g_sci->getGameId() == GID_PQ2 &&
- g_sci->getLanguage() == Common::JA_JPN) {
+ // Japanese PC-9801 interpreter splits strings here
+ // see bug #5834
+ // Verified for Police Quest 2 + Quest For Glory 1
+ // However Space Quest 4 PC-9801 doesn't
+ if ((g_sci->getLanguage() == Common::JA_JPN)
+ && (getSciVersion() <= SCI_VERSION_01)) {
s1 = g_sci->strSplit(s1.c_str(), NULL);
s2 = g_sci->strSplit(s2.c_str(), NULL);
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 8bbbd713a6..3d76848a76 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -1917,6 +1917,43 @@ static const SciScriptPatcherEntry pq1vgaSignatures[] = {
};
// ===========================================================================
+// At the healer's house there is a bird's nest up on the tree.
+// The player can throw rocks at it until it falls to the ground.
+// The hero will then grab the item, that is in the nest.
+//
+// When running is active, the hero will not reach the actual destination
+// and because of that, the game will get stuck.
+//
+// We just change the coordinate of the destination slightly, so that walking,
+// sneaking and running work.
+//
+// This bug was fixed by Sierra at least in the Japanese PC-9801 version.
+// Applies to at least: English floppy (1.000, 1.012)
+// Responsible method: pickItUp::changeState (script 54)
+// Fixes bug: #6407
+static const uint16 qfg1egaSignatureThrowRockAtNest[] = {
+ 0x4a, 0x04, // send 04 (nest::x)
+ 0x36, // push
+ SIG_MAGICDWORD,
+ 0x35, 0x0f, // ldi 0f (15d)
+ 0x02, // add
+ 0x36, // push
+ SIG_END
+};
+
+static const uint16 qfg1egaPatchThrowRockAtNest[] = {
+ PATCH_ADDTOOFFSET(+3),
+ 0x35, 0x12, // ldi 12 (18d)
+ PATCH_END
+};
+
+// script, description, signature patch
+static const SciScriptPatcherEntry qfg1egaSignatures[] = {
+ { true, 54, "throw rock at nest while running", 1, qfg1egaSignatureThrowRockAtNest, qfg1egaPatchThrowRockAtNest },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
// script 215 of qfg1vga pointBox::doit actually processes button-presses
// during fighting with monsters. It strangely also calls kGetEvent. Because
// the main User::doit also calls kGetEvent it's pure luck, where the event
@@ -3036,6 +3073,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3
case GID_PQ1:
signatureTable = pq1vgaSignatures;
break;
+ case GID_QFG1:
+ signatureTable = qfg1egaSignatures;
+ break;
case GID_QFG1VGA:
signatureTable = qfg1vgaSignatures;
break;
diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h
index 0b35792949..7023ef327e 100644
--- a/engines/sci/engine/script_patches.h
+++ b/engines/sci/engine/script_patches.h
@@ -98,7 +98,7 @@ private:
void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription);
int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11);
void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11);
-
+
Selector *_selectorIdTable;
SciScriptPatcherRuntimeEntry *_runtimeTable;
};
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 7701822f6d..c07dc925e0 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -203,59 +203,94 @@ static kLanguage charToLanguage(const char c) {
}
}
-Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2) const {
- kLanguage secondLang = K_LANG_NONE;
-
- const char *seeker = str.c_str();
- while (*seeker) {
- if ((*seeker == '%') || (*seeker == '#')) {
- secondLang = charToLanguage(*(seeker + 1));
-
- if (secondLang != K_LANG_NONE)
+Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage requestedLanguage, kLanguage *secondaryLanguage, uint16 *languageSplitter) const {
+ kLanguage foundLanguage = K_LANG_NONE;
+ const byte *textPtr = (byte *)str.c_str();
+ byte curChar = 0;
+ byte curChar2 = 0;
+
+ while (1) {
+ curChar = *textPtr;
+ if (!curChar)
+ break;
+
+ if ((curChar == '%') || (curChar == '#')) {
+ curChar2 = *(textPtr + 1);
+ foundLanguage = charToLanguage(curChar2);
+
+ if (foundLanguage != K_LANG_NONE) {
+ // Return language splitter
+ if (languageSplitter)
+ *languageSplitter = curChar | ( curChar2 << 8 );
+ // Return the secondary language found in the string
+ if (secondaryLanguage)
+ *secondaryLanguage = foundLanguage;
break;
+ }
}
-
- ++seeker;
+ textPtr++;
}
- // Return the secondary language found in the string
- if (lang2)
- *lang2 = secondLang;
-
- if (secondLang == lang) {
- if (*(++seeker) == 'J') {
+ if (foundLanguage == requestedLanguage) {
+ if (curChar2 == 'J') {
// Japanese including Kanji, displayed with system font
// Convert half-width characters to full-width equivalents
Common::String fullWidth;
- byte c;
+ uint16 mappedChar;
+
+ textPtr += 2; // skip over language splitter
+
+ while (1) {
+ curChar = *textPtr;
+
+ switch (curChar) {
+ case 0: // Terminator NUL
+ return fullWidth;
+ case '\\':
+ // "\n", "\N", "\r" and "\R" were overwritten with SPACE + 0x0D in PC-9801 SSCI
+ // inside GetLongest() (text16). We do it here, because it's much cleaner and
+ // we have to process the text here anyway.
+ // Occurs for example in Police Quest 2 intro
+ curChar2 = *(textPtr + 1);
+ switch (curChar2) {
+ case 'n':
+ case 'N':
+ case 'r':
+ case 'R':
+ fullWidth += ' ';
+ fullWidth += 0x0D; // CR
+ textPtr += 2;
+ continue;
+ }
+ }
+
+ textPtr++;
- while ((c = *(++seeker))) {
- uint16 mappedChar = s_halfWidthSJISMap[c];
+ mappedChar = s_halfWidthSJISMap[curChar];
if (mappedChar) {
fullWidth += mappedChar >> 8;
fullWidth += mappedChar & 0xFF;
} else {
// Copy double-byte character
- char c2 = *(++seeker);
- if (!c2) {
- error("SJIS character %02X is missing second byte", c);
+ curChar2 = *(textPtr++);
+ if (!curChar) {
+ error("SJIS character %02X is missing second byte", curChar);
break;
}
- fullWidth += c;
- fullWidth += c2;
+ fullWidth += curChar;
+ fullWidth += curChar2;
}
}
- return fullWidth;
} else {
- return Common::String(seeker + 1);
+ return Common::String((const char *)(textPtr + 2));
}
}
- if (*seeker)
- return Common::String(str.c_str(), seeker - str.c_str());
- else
- return str;
+ if (curChar)
+ return Common::String(str.c_str(), (const char *)textPtr - str.c_str());
+
+ return str;
}
kLanguage SciEngine::getSciLanguage() {
@@ -314,25 +349,25 @@ void SciEngine::setSciLanguage() {
setSciLanguage(getSciLanguage());
}
-Common::String SciEngine::strSplit(const char *str, const char *sep) {
- kLanguage lang = getSciLanguage();
- kLanguage subLang = K_LANG_NONE;
+Common::String SciEngine::strSplitLanguage(const char *str, uint16 *languageSplitter, const char *sep) {
+ kLanguage activeLanguage = getSciLanguage();
+ kLanguage subtitleLanguage = K_LANG_NONE;
if (SELECTOR(subtitleLang) != -1)
- subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang));
+ subtitleLanguage = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang));
- kLanguage secondLang;
- Common::String retval = getSciLanguageString(str, lang, &secondLang);
+ kLanguage foundLanguage;
+ Common::String retval = getSciLanguageString(str, activeLanguage, &foundLanguage, languageSplitter);
// Don't add subtitle when separator is not set, subtitle language is not set, or
// string contains only one language
- if ((sep == NULL) || (subLang == K_LANG_NONE) || (secondLang == K_LANG_NONE))
+ if ((sep == NULL) || (subtitleLanguage == K_LANG_NONE) || (foundLanguage == K_LANG_NONE))
return retval;
// Add subtitle, unless the subtitle language doesn't match the languages in the string
- if ((subLang == K_LANG_ENGLISH) || (subLang == secondLang)) {
+ if ((subtitleLanguage == K_LANG_ENGLISH) || (subtitleLanguage == foundLanguage)) {
retval += sep;
- retval += getSciLanguageString(str, subLang);
+ retval += getSciLanguageString(str, subtitleLanguage);
}
return retval;
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index ea4dc2fe71..c5730b5345 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -91,7 +91,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others
{ GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge
{ GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794
- { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when saving the game (may also occur in other situations) - bug #6601
+ { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614
+ { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control
{ GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts
{ GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665
{ GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662
diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp
index f2b2ccdfe6..e2e250cf9d 100644
--- a/engines/sci/graphics/controls16.cpp
+++ b/engines/sci/graphics/controls16.cpp
@@ -280,7 +280,7 @@ int GfxControls16::getPicNotValid() {
return _screen->_picNotValid;
}
-void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) {
+void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 style, bool hilite) {
int16 sci0EarlyPen = 0, sci0EarlyBack = 0;
if (!hilite) {
if (getSciVersion() == SCI_VERSION_0_EARLY) {
@@ -295,7 +295,7 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t
_paint16->frameRect(rect);
rect.grow(-2);
_ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED));
- _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
+ _text16->Box(text, languageSplitter, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
_ports->textGreyedOutput(false);
rect.grow(1);
if (style & SCI_CONTROLS_STYLE_SELECTED)
@@ -318,12 +318,12 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t
}
}
-void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) {
+void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, TextAlignment alignment, int16 style, bool hilite) {
if (!hilite) {
rect.grow(1);
_paint16->eraseRect(rect);
rect.grow(-1);
- _text16->Box(text, false, rect, alignment, fontId);
+ _text16->Box(text, languageSplitter, false, rect, alignment, fontId);
if (style & SCI_CONTROLS_STYLE_SELECTED) {
_paint16->frameRect(rect);
}
@@ -335,7 +335,7 @@ void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *tex
}
}
-void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) {
+void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) {
Common::Rect textRect = rect;
uint16 oldFontId = _text16->GetFontId();
@@ -343,7 +343,7 @@ void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char
_texteditCursorVisible = false;
texteditCursorErase();
_paint16->eraseRect(rect);
- _text16->Box(text, false, textRect, SCI_TEXT16_ALIGNMENT_LEFT, fontId);
+ _text16->Box(text, languageSplitter, false, textRect, SCI_TEXT16_ALIGNMENT_LEFT, fontId);
_paint16->frameRect(rect);
if (style & SCI_CONTROLS_STYLE_SELECTED) {
_text16->SetFont(fontId);
diff --git a/engines/sci/graphics/controls16.h b/engines/sci/graphics/controls16.h
index 6a70c71aae..39ffa243fb 100644
--- a/engines/sci/graphics/controls16.h
+++ b/engines/sci/graphics/controls16.h
@@ -55,9 +55,9 @@ public:
GfxControls16(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen);
~GfxControls16();
- void kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite);
- void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 alignment, int16 style, bool hilite);
- void kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite);
+ void kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 style, bool hilite);
+ 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 kernelTexteditChange(reg_t controlObject, reg_t eventObject);
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 048ec1e9b9..1a58de073c 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -47,7 +47,7 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc
_isVisible = true;
// center mouse cursor
- setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2));
+ setPosition(Common::Point(_screen->getScriptWidth() / 2, _screen->getScriptHeight() / 2));
_moveZoneActive = false;
_zoomZoneActive = false;
@@ -151,14 +151,14 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) {
colorMapping[0] = 0; // Black is hardcoded
colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded
colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR;
- colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey
+ colorMapping[3] = _palette->matchColor(170, 170, 170) & SCI_PALETTE_MATCH_COLORMASK; // Grey
// TODO: Figure out if the grey color is hardcoded
// HACK for the magnifier cursor in LB1, fixes its color (bug #3487092)
if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1)
colorMapping[3] = _screen->getColorWhite();
// HACK for Longbow cursors, fixes the shade of grey they're using (bug #3489101)
if (g_sci->getGameId() == GID_LONGBOW)
- colorMapping[3] = _palette->matchColor(223, 223, 223); // Light Grey
+ colorMapping[3] = _palette->matchColor(223, 223, 223) & SCI_PALETTE_MATCH_COLORMASK; // Light Grey
// Seek to actual data
resourceData += 4;
@@ -481,7 +481,7 @@ void GfxCursor::kernelSetPos(Common::Point pos) {
void GfxCursor::kernelMoveCursor(Common::Point pos) {
_coordAdjuster->moveCursor(pos);
- if (pos.x > _screen->getWidth() || pos.y > _screen->getHeight()) {
+ if (pos.x > _screen->getScriptWidth() || pos.y > _screen->getScriptHeight()) {
warning("attempt to place cursor at invalid coordinates (%d, %d)", pos.y, pos.x);
return;
}
diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp
index e4684ff134..2268ec0459 100644
--- a/engines/sci/graphics/font.cpp
+++ b/engines/sci/graphics/font.cpp
@@ -48,8 +48,8 @@ GfxFontFromResource::GfxFontFromResource(ResourceManager *resMan, GfxScreen *scr
// filling info for every char
for (int16 i = 0; i < _numChars; i++) {
_chars[i].offset = READ_SCI32ENDIAN_UINT16(_resourceData + 6 + i * 2);
- _chars[i].w = _resourceData[_chars[i].offset];
- _chars[i].h = _resourceData[_chars[i].offset + 1];
+ _chars[i].width = _resourceData[_chars[i].offset];
+ _chars[i].height = _resourceData[_chars[i].offset + 1];
}
}
@@ -66,10 +66,10 @@ byte GfxFontFromResource::getHeight() {
return _fontHeight;
}
byte GfxFontFromResource::getCharWidth(uint16 chr) {
- return chr < _numChars ? _chars[chr].w : 0;
+ return chr < _numChars ? _chars[chr].width : 0;
}
byte GfxFontFromResource::getCharHeight(uint16 chr) {
- return chr < _numChars ? _chars[chr].h : 0;
+ return chr < _numChars ? _chars[chr].height : 0;
}
byte *GfxFontFromResource::getCharData(uint16 chr) {
return chr < _numChars ? _resourceData + _chars[chr].offset + 2 : 0;
diff --git a/engines/sci/graphics/font.h b/engines/sci/graphics/font.h
index 58b2ba4813..451261f315 100644
--- a/engines/sci/graphics/font.h
+++ b/engines/sci/graphics/font.h
@@ -71,9 +71,11 @@ private:
byte *_resourceData;
struct Charinfo {
- byte w, h;
+ byte width;
+ byte height;
int16 offset;
};
+
byte _fontHeight;
uint16 _numChars;
Charinfo *_chars;
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index fafc734895..ccc362dc37 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -524,6 +524,10 @@ void GfxFrameout::showVideo() {
RobotDecoder *videoDecoder = g_sci->_robotDecoder;
uint16 x = videoDecoder->getPos().x;
uint16 y = videoDecoder->getPos().y;
+ uint16 screenWidth = _screen->getWidth();
+ uint16 screenHeight = _screen->getHeight();
+ uint16 outputWidth;
+ uint16 outputHeight;
if (videoDecoder->hasDirtyPalette())
g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
@@ -532,7 +536,11 @@ void GfxFrameout::showVideo() {
if (videoDecoder->needsUpdate()) {
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
if (frame) {
- g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
+ // We need to clip here
+ // At least Phantasmagoria shows a 640x390 video on a 630x450 screen during the intro
+ outputWidth = frame->w > screenWidth ? screenWidth : frame->w;
+ outputHeight = frame->h > screenHeight ? screenHeight : frame->h;
+ g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, outputWidth, outputHeight);
if (videoDecoder->hasDirtyPalette())
g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index b835eb92ca..f80703e14d 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -476,7 +476,7 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) {
#define SCI_DISPLAY_DUMMY3 117
#define SCI_DISPLAY_DONTSHOWBITS 121
-reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
+reg_t GfxPaint16::kernelDisplay(const char *text, uint16 languageSplitter, int argc, reg_t *argv) {
reg_t displayArg;
TextAlignment alignment = SCI_TEXT16_ALIGNMENT_LEFT;
int16 colorPen = -1, colorBack = -1, width = -1, bRedraw = 1;
@@ -572,7 +572,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
}
// now drawing the text
- _text16->Size(rect, text, -1, width);
+ _text16->Size(rect, text, languageSplitter, -1, width);
rect.moveTo(_ports->getPort()->curLeft, _ports->getPort()->curTop);
// Note: This code has been found in SCI1 middle and newer games. It was
// previously only for SCI1 late and newer, but the LSL1 interpreter contains
@@ -588,7 +588,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
result = bitsSave(rect, GFX_SCREEN_MASK_VISUAL);
if (colorBack != -1)
fillRect(rect, GFX_SCREEN_MASK_VISUAL, colorBack, 0, 0);
- _text16->Box(text, false, rect, alignment, -1);
+ _text16->Box(text, languageSplitter, false, rect, alignment, -1);
if (_screen->_picNotValid == 0 && bRedraw)
bitsShow(rect);
// restoring port and cursor pos
diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h
index 882f311a5b..955cfdec8f 100644
--- a/engines/sci/graphics/paint16.h
+++ b/engines/sci/graphics/paint16.h
@@ -80,7 +80,7 @@ public:
void kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode);
void kernelGraphRedrawBox(Common::Rect rect);
- reg_t kernelDisplay(const char *text, int argc, reg_t *argv);
+ reg_t kernelDisplay(const char *text, uint16 languageSplitter, int argc, reg_t *argv);
reg_t kernelPortraitLoad(const Common::String &resourceName);
void kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq);
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index 7d106b5b02..a210a469f1 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -46,7 +46,7 @@ void GfxPaint32::fillRect(Common::Rect rect, byte color) {
Common::Rect clipRect = rect;
clipRect.clip(_screen->getWidth(), _screen->getHeight());
-
+
for (y = clipRect.top; y < clipRect.bottom; y++) {
for (x = clipRect.left; x < clipRect.right; x++) {
_screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0, 0);
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index a3624c7959..59abef5550 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -65,14 +65,21 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen)
// the real merging done in earlier games. If we use the copying over, we
// will get issues because some views have marked all colors as being used
// and those will overwrite the current palette in that case
- if (getSciVersion() < SCI_VERSION_1_1)
+ if (getSciVersion() < SCI_VERSION_1_1) {
_useMerging = true;
- else if (getSciVersion() == SCI_VERSION_1_1)
+ _use16bitColorMatch = true;
+ } else if (getSciVersion() == SCI_VERSION_1_1) {
// there are some games that use inbetween SCI1.1 interpreter, so we have
// to detect if the current game is merging or copying
_useMerging = _resMan->detectPaletteMergingSci11();
- else // SCI32
+ _use16bitColorMatch = _useMerging;
+ // Note: Laura Bow 2 floppy uses the new palette format and is detected
+ // as 8 bit color matching because of that.
+ } else {
+ // SCI32
_useMerging = false;
+ _use16bitColorMatch = false; // not verified that SCI32 uses 8-bit color matching
+ }
palVaryInit();
@@ -120,6 +127,10 @@ bool GfxPalette::isMerging() {
return _useMerging;
}
+bool GfxPalette::isUsing16bitColorMatch() {
+ return _use16bitColorMatch;
+}
+
// meant to get called only once during init of engine
void GfxPalette::setDefault() {
if (_resMan->getViewType() == kViewEga)
@@ -464,8 +475,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
// check if exact color could be matched
res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b);
- if (res & 0x8000) { // exact match was found
- newPalette->mapping[i] = res & 0xFF;
+ if (res & SCI_PALETTE_MATCH_PERFECT) { // exact match was found
+ newPalette->mapping[i] = res & SCI_PALETTE_MATCH_COLORMASK;
continue;
}
@@ -486,8 +497,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
// if still no luck - set an approximate color
if (j == 256) {
- newPalette->mapping[i] = res & 0xFF;
- _sysPalette.colors[res & 0xFF].used |= 0x10;
+ newPalette->mapping[i] = res & SCI_PALETTE_MATCH_COLORMASK;
+ _sysPalette.colors[res & SCI_PALETTE_MATCH_COLORMASK].used |= 0x10;
}
}
@@ -509,29 +520,47 @@ void GfxPalette::drewPicture(GuiResourceId pictureId) {
}
}
-uint16 GfxPalette::matchColor(byte r, byte g, byte b) {
- byte found = 0xFF;
- int diff = 0x2FFFF, cdiff;
- int16 dr,dg,db;
-
- for (int i = 1; i < 255; i++) {
- if ((!_sysPalette.colors[i].used))
- continue;
- dr = _sysPalette.colors[i].r - r;
- dg = _sysPalette.colors[i].g - g;
- db = _sysPalette.colors[i].b - b;
-// minimum squares match
- cdiff = (dr*dr) + (dg*dg) + (db*db);
-// minimum sum match (Sierra's)
-// cdiff = ABS(dr) + ABS(dg) + ABS(db);
- if (cdiff < diff) {
- if (cdiff == 0)
- return i | 0x8000; // setting this flag to indicate exact match
- found = i;
- diff = cdiff;
+uint16 GfxPalette::matchColor(byte matchRed, byte matchGreen, byte matchBlue) {
+ int16 colorNr;
+ int16 differenceRed, differenceGreen, differenceBlue;
+ int16 differenceTotal = 0;
+ int16 bestDifference = 0x7FFF;
+ uint16 bestColorNr = 255;
+
+ if (_use16bitColorMatch) {
+ // used by SCI0 to SCI1, also by the first few SCI1.1 games
+ for (colorNr = 0; colorNr < 256; colorNr++) {
+ if ((!_sysPalette.colors[colorNr].used))
+ continue;
+ differenceRed = ABS(_sysPalette.colors[colorNr].r - matchRed);
+ differenceGreen = ABS(_sysPalette.colors[colorNr].g - matchGreen);
+ differenceBlue = ABS(_sysPalette.colors[colorNr].b - matchBlue);
+ differenceTotal = differenceRed + differenceGreen + differenceBlue;
+ if (differenceTotal <= bestDifference) {
+ bestDifference = differenceTotal;
+ bestColorNr = colorNr;
+ }
+ }
+ } else {
+ // SCI1.1, starting with QfG3 introduced a bug in the matching code
+ // we have to implement it as well, otherwise some colors will be "wrong" in comparison to the original interpreter
+ // See Space Quest 5 bug #6455
+ for (colorNr = 0; colorNr < 256; colorNr++) {
+ if ((!_sysPalette.colors[colorNr].used))
+ continue;
+ differenceRed = (uint8)ABS<int8>(_sysPalette.colors[colorNr].r - matchRed);
+ differenceGreen = (uint8)ABS<int8>(_sysPalette.colors[colorNr].g - matchGreen);
+ differenceBlue = (uint8)ABS<int8>(_sysPalette.colors[colorNr].b - matchBlue);
+ differenceTotal = differenceRed + differenceGreen + differenceBlue;
+ if (differenceTotal <= bestDifference) {
+ bestDifference = differenceTotal;
+ bestColorNr = colorNr;
+ }
}
}
- return found;
+ if (differenceTotal == 0) // original interpreter does not do this, instead it does 2 calls for merges in the worst case
+ return bestColorNr | SCI_PALETTE_MATCH_PERFECT; // we set this flag, so that we can optimize during palette merge
+ return bestColorNr;
}
void GfxPalette::getSys(Palette *pal) {
@@ -621,7 +650,7 @@ void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 int
}
int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) {
- return matchColor(r, g, b) & 0xFF;
+ return matchColor(r, g, b) & SCI_PALETTE_MATCH_COLORMASK;
}
// Returns true, if palette got changed
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 347695deb8..500a45eccf 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -31,6 +31,10 @@ namespace Sci {
class ResourceManager;
class GfxScreen;
+// Special flag implemented by us for optimization in palette merge
+#define SCI_PALETTE_MATCH_PERFECT 0x8000
+#define SCI_PALETTE_MATCH_COLORMASK 0xFF
+
enum ColorRemappingType {
kRemappingNone = 0,
kRemappingByRange = 1,
@@ -46,6 +50,7 @@ public:
~GfxPalette();
bool isMerging();
+ bool isUsing16bitColorMatch();
void setDefault();
void createFromData(byte *data, int bytesLeft, Palette *paletteOut);
@@ -124,6 +129,7 @@ private:
bool _sysPaletteChanged;
bool _useMerging;
+ bool _use16bitColorMatch;
Common::Array<PalSchedule> _schedules;
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 434a490109..d7ef84dc1e 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -88,10 +88,13 @@ void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int1
}
void GfxPicture::reset() {
+ int16 startY = _ports->getPort()->top;
+ int16 startX = 0;
int16 x, y;
- for (y = _ports->getPort()->top; y < _screen->getHeight(); y++) {
- for (x = 0; x < _screen->getWidth(); x++) {
- _screen->putPixel(x, y, GFX_SCREEN_MASK_ALL, 255, 0, 0);
+ _screen->vectorAdjustCoordinate(&startX, &startY);
+ for (y = startY; y < _screen->getHeight(); y++) {
+ for (x = startX; x < _screen->getWidth(); x++) {
+ _screen->vectorPutPixel(x, y, GFX_SCREEN_MASK_ALL, 255, 0, 0);
}
}
}
@@ -246,7 +249,7 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
int16 y, lastY, x, leftX, rightX;
int pixelCount;
uint16 width, height;
-
+
// if the picture is not an overlay and we are also not in EGA mode, use priority 0
if (!isEGA && !_addToFlag)
priority = 0;
@@ -362,7 +365,7 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
ptr = celBitmap;
ptr += skipCelBitmapPixels;
ptr += skipCelBitmapLines * width;
-
+
if ((!isEGA) || (priority < 16)) {
// VGA + EGA, EGA only checks priority, when given priority is below 16
if (!_mirroredFlag) {
@@ -482,6 +485,8 @@ enum {
PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4
};
+//#define DEBUG_PICTURE_DRAW 1
+
#ifdef DEBUG_PICTURE_DRAW
const char *picOpcodeNames[] = {
"Set color",
@@ -589,6 +594,9 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
while (curPos < dataSize) {
#ifdef DEBUG_PICTURE_DRAW
debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos);
+ _screen->copyToScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(400);
#endif
switch (pic_op = data[curPos++]) {
case PIC_OP_SET_COLOR:
@@ -934,17 +942,17 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
Common::Point p, p1;
byte screenMask = _screen->getDrawingMask(color, priority, control);
byte matchedMask, matchMask;
- int16 w, e, a_set, b_set;
bool isEGA = (_resMan->getViewType() == kViewEga);
p.x = x + curPort->left;
p.y = y + curPort->top;
- stack.push(p);
- byte searchColor = _screen->getVisual(p.x, p.y);
- byte searchPriority = _screen->getPriority(p.x, p.y);
- byte searchControl = _screen->getControl(p.x, p.y);
+ _screen->vectorAdjustCoordinate(&p.x, &p.y);
+
+ byte searchColor = _screen->vectorGetVisual(p.x, p.y);
+ byte searchPriority = _screen->vectorGetPriority(p.x, p.y);
+ byte searchControl = _screen->vectorGetControl(p.x, p.y);
if (isEGA) {
// In EGA games a pixel in the framebuffer is only 4 bits. We store
@@ -991,22 +999,31 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
}
// hard borders for filling
- int l = curPort->rect.left + curPort->left;
- int t = curPort->rect.top + curPort->top;
- int r = curPort->rect.right + curPort->left - 1;
- int b = curPort->rect.bottom + curPort->top - 1;
+ int16 borderLeft = curPort->rect.left + curPort->left;
+ int16 borderTop = curPort->rect.top + curPort->top;
+ int16 borderRight = curPort->rect.right + curPort->left - 1;
+ int16 borderBottom = curPort->rect.bottom + curPort->top - 1;
+ int16 curToLeft, curToRight, a_set, b_set;
+
+ // Translate coordinates, if required (needed for Macintosh 480x300)
+ _screen->vectorAdjustCoordinate(&borderLeft, &borderTop);
+ _screen->vectorAdjustCoordinate(&borderRight, &borderBottom);
+ //return;
+
+ stack.push(p);
+
while (stack.size()) {
p = stack.pop();
- if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled
+ if ((matchedMask = _screen->vectorIsFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)) == 0) // already filled
continue;
- _screen->putPixel(p.x, p.y, screenMask, color, priority, control);
- w = p.x;
- e = p.x;
+ _screen->vectorPutPixel(p.x, p.y, screenMask, color, priority, control);
+ curToLeft = p.x;
+ curToRight = p.x;
// moving west and east pointers as long as there is a matching color to fill
- while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
- _screen->putPixel(--w, p.y, screenMask, color, priority, control);
- while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
- _screen->putPixel(++e, p.y, screenMask, color, priority, control);
+ while (curToLeft > borderLeft && (matchedMask = _screen->vectorIsFillMatch(curToLeft - 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
+ _screen->vectorPutPixel(--curToLeft, p.y, screenMask, color, priority, control);
+ while (curToRight < borderRight && (matchedMask = _screen->vectorIsFillMatch(curToRight + 1, p.y, matchMask, searchColor, searchPriority, searchControl, isEGA)))
+ _screen->vectorPutPixel(++curToRight, p.y, screenMask, color, priority, control);
#if 0
// debug code for floodfill
_screen->copyToScreen();
@@ -1015,10 +1032,10 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
#endif
// checking lines above and below for possible flood targets
a_set = b_set = 0;
- while (w <= e) {
- if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above
+ while (curToLeft <= curToRight) {
+ if (p.y > borderTop && (matchedMask = _screen->vectorIsFillMatch(curToLeft, p.y - 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line above
if (a_set == 0) {
- p1.x = w;
+ p1.x = curToLeft;
p1.y = p.y - 1;
stack.push(p1);
a_set = 1;
@@ -1026,16 +1043,16 @@ void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, by
} else
a_set = 0;
- if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below
+ if (p.y < borderBottom && (matchedMask = _screen->vectorIsFillMatch(curToLeft, p.y + 1, matchMask, searchColor, searchPriority, searchControl, isEGA))) { // one line below
if (b_set == 0) {
- p1.x = w;
+ p1.x = curToLeft;
p1.y = p.y + 1;
stack.push(p1);
b_set = 1;
}
} else
b_set = 0;
- w++;
+ curToLeft++;
}
}
}
@@ -1173,7 +1190,7 @@ void GfxPicture::vectorPatternBox(Common::Rect box, byte color, byte prio, byte
for (y = box.top; y < box.bottom; y++) {
for (x = box.left; x < box.right; x++) {
- _screen->putPixel(x, y, flag, color, prio, control);
+ _screen->vectorPutPixel(x, y, flag, color, prio, control);
}
}
}
@@ -1186,7 +1203,7 @@ void GfxPicture::vectorPatternTexturedBox(Common::Rect box, byte color, byte pri
for (y = box.top; y < box.bottom; y++) {
for (x = box.left; x < box.right; x++) {
if (*textureData) {
- _screen->putPixel(x, y, flag, color, prio, control);
+ _screen->vectorPutPixel(x, y, flag, color, prio, control);
}
textureData++;
}
@@ -1203,7 +1220,7 @@ void GfxPicture::vectorPatternCircle(Common::Rect box, byte size, byte color, by
for (y = box.top; y < box.bottom; y++) {
for (x = box.left; x < box.right; x++) {
if (bitmap & 1) {
- _screen->putPixel(x, y, flag, color, prio, control);
+ _screen->vectorPutPixel(x, y, flag, color, prio, control);
}
bitNo++;
if (bitNo == 8) {
@@ -1222,12 +1239,12 @@ void GfxPicture::vectorPatternTexturedCircle(Common::Rect box, byte size, byte c
byte bitNo = 0;
const bool *textureData = &vectorPatternTextures[vectorPatternTextureOffset[texture]];
int y, x;
-
+
for (y = box.top; y < box.bottom; y++) {
for (x = box.left; x < box.right; x++) {
if (bitmap & 1) {
if (*textureData) {
- _screen->putPixel(x, y, flag, color, prio, control);
+ _screen->vectorPutPixel(x, y, flag, color, prio, control);
}
textureData++;
}
@@ -1252,7 +1269,10 @@ void GfxPicture::vectorPattern(int16 x, int16 y, byte color, byte priority, byte
rect.top = y; rect.left = x;
rect.setHeight((size*2)+1); rect.setWidth((size*2)+2);
_ports->offsetRect(rect);
- rect.clip(_screen->getWidth(), _screen->getHeight());
+ rect.clip(_screen->getScriptWidth(), _screen->getScriptHeight());
+
+ _screen->vectorAdjustCoordinate(&rect.left, &rect.top);
+ _screen->vectorAdjustCoordinate(&rect.right, &rect.bottom);
if (code & SCI_PATTERN_CODE_RECTANGLE) {
// Rectangle
diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp
index 488450485d..668de616fb 100644
--- a/engines/sci/graphics/portrait.cpp
+++ b/engines/sci/graphics/portrait.cpp
@@ -134,34 +134,34 @@ void Portrait::init() {
// raw lip-sync ID table follows
uint32 lipSyncIDTableSize;
-
+
lipSyncIDTableSize = READ_LE_UINT32(data);
data += 4;
assert( lipSyncIDTableSize == (_lipSyncIDCount * 4) );
_lipSyncIDTable = data;
data += lipSyncIDTableSize;
-
+
// raw lip-sync frame table follows
uint32 lipSyncDataTableSize;
uint32 lipSyncDataTableLastOffset;
byte lipSyncData;
uint16 lipSyncDataNr;
uint16 lipSyncCurOffset;
-
+
lipSyncDataTableSize = READ_LE_UINT32(data);
data += 4;
assert( lipSyncDataTableSize == 0x220 ); // always this size, just a safety-check
-
+
_lipSyncData = data;
lipSyncDataTableLastOffset = lipSyncDataTableSize - 1;
_lipSyncDataOffsetTable = new uint16[ _lipSyncIDCount ];
-
+
lipSyncDataNr = 0;
lipSyncCurOffset = 0;
while ( (lipSyncCurOffset < lipSyncDataTableSize) && (lipSyncDataNr < _lipSyncIDCount) ) {
// We are currently at the start of ID-frame data
_lipSyncDataOffsetTable[lipSyncDataNr] = lipSyncCurOffset;
-
+
// Look for end of ID-frame data
lipSyncData = *data++; lipSyncCurOffset++;
while ( (lipSyncData != 0xFF) && (lipSyncCurOffset < lipSyncDataTableLastOffset) ) {
@@ -195,7 +195,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
Resource *syncResource = _resMan->findResource(syncResourceId, true);
uint syncOffset = 0;
#endif
-
+
#ifdef DEBUG_PORTRAIT
// prints out the current lip sync ASCII data
char debugPrint[4000];
@@ -246,7 +246,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
warning("kPortrait: no rave resource %d %X", resourceId, audioNumber);
return;
}
-
+
// Do animation depending on rave resource till audio is done playing
int16 raveTicks;
uint16 raveID;
@@ -264,7 +264,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
raveTicks = raveGetTicks(raveResource, &raveOffset);
if (raveTicks < 0)
break;
-
+
// get lipSyncID
raveID = raveGetID(raveResource, &raveOffset);
if (raveID) {
@@ -272,7 +272,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
} else {
raveLipSyncData = NULL;
}
-
+
timerPosition += raveTicks;
// Wait till syncTime passed, then show specific animation bitmap
@@ -287,7 +287,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
curPosition = _audio->getAudioPosition();
} while ((curPosition != -1) && (curPosition < timerPosition) && (!userAbort));
}
-
+
if (raveLipSyncData) {
// lip sync data is
// Tick:Byte, Bitmap-Nr:BYTE
@@ -308,7 +308,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
} while ((curPosition != -1) && (curPosition < timerPositionWithin) && (!userAbort));
raveLipSyncBitmapNr = *raveLipSyncData++;
-
+
// bitmap nr within sync data is base 1, we need base 0
raveLipSyncBitmapNr--;
@@ -319,7 +319,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
} else {
warning("kPortrait: rave lip sync data tried to draw non-existent bitmap %d", raveLipSyncBitmapNr);
}
-
+
raveLipSyncTicks = *raveLipSyncData++;
}
}
@@ -372,7 +372,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint
}
}
#endif
-
+
// Reset the portrait bitmap to "closed mouth" state (rave.dll seems to do the same)
drawBitmap(0);
bitsShow();
@@ -393,10 +393,10 @@ int16 Portrait::raveGetTicks(Resource *resource, uint *offset) {
byte *curData = resource->data + curOffset;
byte curByte;
uint16 curValue = 0;
-
+
if (curOffset >= resource->size)
return -1;
-
+
while (curOffset < resource->size) {
curByte = *curData++; curOffset++;
if ( curByte == ' ' )
@@ -418,7 +418,7 @@ uint16 Portrait::raveGetID(Resource *resource, uint *offset) {
byte *curData = resource->data + curOffset;
byte curByte = 0;
uint16 curValue = 0;
-
+
while (curOffset < resource->size) {
curByte = *curData++; curOffset++;
if ( curByte == ' ' )
@@ -429,7 +429,7 @@ uint16 Portrait::raveGetID(Resource *resource, uint *offset) {
curValue |= curByte;
}
}
-
+
*offset = curOffset;
return curValue;
}
@@ -440,17 +440,17 @@ byte *Portrait::raveGetLipSyncData(uint16 raveID) {
byte *lipSyncIDPtr = _lipSyncIDTable;
byte lipSyncIDByte1, lipSyncIDByte2;
uint16 lipSyncID;
-
+
lipSyncIDPtr++; // skip over first byte
while (lipSyncIDNr < _lipSyncIDCount) {
lipSyncIDByte1 = *lipSyncIDPtr++;
lipSyncIDByte2 = *lipSyncIDPtr++;
lipSyncID = ( lipSyncIDByte1 << 8 ) | lipSyncIDByte2;
-
+
if ( lipSyncID == raveID ) {
return _lipSyncData + _lipSyncDataOffsetTable[lipSyncIDNr];
}
-
+
lipSyncIDNr++;
lipSyncIDPtr += 2; // ID is every 4 bytes
}
diff --git a/engines/sci/graphics/portrait.h b/engines/sci/graphics/portrait.h
index 877b253bcf..e0888daa86 100644
--- a/engines/sci/graphics/portrait.h
+++ b/engines/sci/graphics/portrait.h
@@ -72,7 +72,7 @@ private:
Common::String _resourceName;
byte *_fileData;
-
+
uint32 _lipSyncIDCount;
byte *_lipSyncIDTable;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 56c63a7b12..bcc991081e 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -63,10 +63,10 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
openPort(_menuPort);
setPort(_menuPort);
_text16->SetFont(0);
- _menuPort->rect = Common::Rect(0, 0, _screen->getWidth(), _screen->getHeight());
- _menuBarRect = Common::Rect(0, 0, _screen->getWidth(), 9);
- _menuRect = Common::Rect(0, 0, _screen->getWidth(), 10);
- _menuLine = Common::Rect(0, 9, _screen->getWidth(), 10);
+ _menuPort->rect = Common::Rect(0, 0, _screen->getScriptWidth(), _screen->getScriptHeight());
+ _menuBarRect = Common::Rect(0, 0, _screen->getScriptWidth(), 9);
+ _menuRect = Common::Rect(0, 0, _screen->getScriptWidth(), 10);
+ _menuLine = Common::Rect(0, 9, _screen->getScriptWidth(), 10);
_wmgrPort = new Port(1);
_windowsById.resize(2);
@@ -122,13 +122,13 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
} else {
_wmgrPort->rect.bottom = _screen->getHeight();
}
- _wmgrPort->rect.right = _screen->getWidth();
+ _wmgrPort->rect.right = _screen->getScriptWidth();
_wmgrPort->rect.moveTo(0, 0);
_wmgrPort->curTop = 0;
_wmgrPort->curLeft = 0;
_windowList.push_front(_wmgrPort);
- _picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
+ _picWind = addWindow(Common::Rect(0, offTop, _screen->getScriptWidth(), _screen->getScriptHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
// For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead
// Because of the menu/status bar
if (_usesOldGfxFunctions)
@@ -321,13 +321,13 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
// their interpreter even in the newer VGA games.
r.left = r.left & 0xFFFE;
- if (r.width() > _screen->getWidth()) {
+ if (r.width() > _screen->getScriptWidth()) {
// We get invalid dimensions at least at the end of sq3 (script bug!).
// Same happens very often in lsl5, sierra sci didnt fix it but it looked awful.
// Also happens frequently in the demo of GK1.
warning("Fixing too large window, left: %d, right: %d", dims.left, dims.right);
r.left = 0;
- r.right = _screen->getWidth() - 1;
+ r.right = _screen->getScriptWidth() - 1;
if ((style != _styleUser) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME))
r.right--;
}
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index c5c94d7991..8b0e76332f 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -37,7 +37,15 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
// Scale the screen, if needed
_upscaledHires = GFX_SCREEN_UPSCALED_DISABLED;
-
+
+ // we default to scripts running at 320x200
+ _scriptWidth = 320;
+ _scriptHeight = 200;
+ _width = 0;
+ _height = 0;
+ _displayWidth = 0;
+ _displayHeight = 0;
+
// King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able
// to provide that under DOS as well, but as gk1/floppy does support
// upscaled hires scriptswise, but doesn't actually have the hires content
@@ -50,10 +58,33 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_upscaledHires = GFX_SCREEN_UPSCALED_640x480;
#endif
}
+
+ // Japanese versions of games use hi-res font on upscaled version of the game.
+ if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
+ _upscaledHires = GFX_SCREEN_UPSCALED_640x400;
+ // Macintosh SCI0 games used 480x300, while the scripts were running at 320x200
if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
- if (getSciVersion() <= SCI_VERSION_01)
+ if (getSciVersion() <= SCI_VERSION_01) {
_upscaledHires = GFX_SCREEN_UPSCALED_480x300;
+ _width = 480;
+ _height = 300; // regular visual, priority and control map are 480x300 (this is different than other upscaled SCI games)
+ }
+
+ // Some Mac SCI1/1.1 games only take up 190 rows and do not
+ // have the menu bar.
+ // TODO: Verify that LSL1 and LSL5 use height 190
+ switch (g_sci->getGameId()) {
+ case GID_FREDDYPHARKAS:
+ case GID_KQ5:
+ case GID_KQ6:
+ case GID_LSL1:
+ case GID_LSL5:
+ case GID_SQ1:
+ _width = 190;
+ default:
+ break;
+ }
}
#ifdef ENABLE_SCI32
@@ -65,76 +96,77 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
#endif
if (_resMan->detectHires()) {
- _width = 640;
- _pitch = 640;
- _height = 480;
- } else {
- _width = 320;
- _pitch = 320;
- _height = getLowResScreenHeight();
+ _scriptWidth = 640;
+ _scriptHeight = 480;
}
#ifdef ENABLE_SCI32
- // Phantasmagoria 1 sets a window area of 630x450
+ // Phantasmagoria 1 effectively outputs 630x450
+ // Coordinate translation has to use this resolution as well
if (g_sci->getGameId() == GID_PHANTASMAGORIA) {
_width = 630;
_height = 450;
}
#endif
- // Japanese versions of games use hi-res font on upscaled version of the game.
- if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
- _upscaledHires = GFX_SCREEN_UPSCALED_640x400;
+ // if not yet set, set those to script-width/height
+ if (!_width)
+ _width = _scriptWidth;
+ if (!_height)
+ _height = _scriptHeight;
- _pixels = _pitch * _height;
+ _pixels = _width * _height;
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_480x300:
// Space Quest 3, Hoyle 1+2 on MAC use this one
- // TODO: Sierra's upscaling worked differently. We need to figure out the exact algo
_displayWidth = 480;
_displayHeight = 300;
- for (int i = 0; i <= _height; i++)
+ for (int i = 0; i <= _scriptHeight; i++)
_upscaledHeightMapping[i] = (i * 3) >> 1;
- for (int i = 0; i <= _width; i++)
+ for (int i = 0; i <= _scriptWidth; i++)
_upscaledWidthMapping[i] = (i * 3) >> 1;
break;
case GFX_SCREEN_UPSCALED_640x400:
// Police Quest 2 and Quest For Glory on PC9801 (Japanese)
_displayWidth = 640;
_displayHeight = 400;
- for (int i = 0; i <= _height; i++)
+ for (int i = 0; i <= _scriptHeight; i++)
_upscaledHeightMapping[i] = i * 2;
- for (int i = 0; i <= _width; i++)
+ for (int i = 0; i <= _scriptWidth; i++)
_upscaledWidthMapping[i] = i * 2;
break;
case GFX_SCREEN_UPSCALED_640x440:
// used by King's Quest 6 on Windows
_displayWidth = 640;
_displayHeight = 440;
- for (int i = 0; i <= _height; i++)
+ for (int i = 0; i <= _scriptHeight; i++)
_upscaledHeightMapping[i] = (i * 11) / 5;
- for (int i = 0; i <= _width; i++)
+ for (int i = 0; i <= _scriptWidth; i++)
_upscaledWidthMapping[i] = i * 2;
break;
case GFX_SCREEN_UPSCALED_640x480:
// Gabriel Knight 1 (VESA, Mac)
_displayWidth = 640;
_displayHeight = 480;
- for (int i = 0; i <= _height; i++)
+ for (int i = 0; i <= _scriptHeight; i++)
_upscaledHeightMapping[i] = (i * 12) / 5;
- for (int i = 0; i <= _width; i++)
+ for (int i = 0; i <= _scriptWidth; i++)
_upscaledWidthMapping[i] = i * 2;
break;
default:
- _displayWidth = _pitch;
- _displayHeight = _height;
+ if (!_displayWidth)
+ _displayWidth = _width;
+ if (!_displayHeight)
+ _displayHeight = _height;
memset(&_upscaledHeightMapping, 0, sizeof(_upscaledHeightMapping) );
memset(&_upscaledWidthMapping, 0, sizeof(_upscaledWidthMapping) );
break;
}
_displayPixels = _displayWidth * _displayHeight;
+
+ // Allocate visual, priority, control and display screen
_visualScreen = (byte *)calloc(_pixels, 1);
_priorityScreen = (byte *)calloc(_pixels, 1);
_controlScreen = (byte *)calloc(_pixels, 1);
@@ -179,6 +211,34 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
error("Unknown SCI1.1 Mac game");
} else
initGraphics(_displayWidth, _displayHeight, _displayWidth > 320);
+
+ // Initialize code pointers
+ _vectorAdjustCoordinatePtr = &GfxScreen::vectorAdjustCoordinateNOP;
+ _vectorAdjustLineCoordinatesPtr = &GfxScreen::vectorAdjustLineCoordinatesNOP;
+ _vectorIsFillMatchPtr = &GfxScreen::vectorIsFillMatchNormal;
+ _vectorPutPixelPtr = &GfxScreen::putPixelNormal;
+ _vectorPutLinePixelPtr = &GfxScreen::putPixel;
+ _vectorGetPixelPtr = &GfxScreen::getPixelNormal;
+ _putPixelPtr = &GfxScreen::putPixelNormal;
+ _getPixelPtr = &GfxScreen::getPixelNormal;
+
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300:
+ _vectorAdjustCoordinatePtr = &GfxScreen::vectorAdjustCoordinate480x300Mac;
+ _vectorAdjustLineCoordinatesPtr = &GfxScreen::vectorAdjustLineCoordinates480x300Mac;
+ // vectorPutPixel -> we already adjust coordinates for vector code, that's why we can set pixels directly
+ // vectorGetPixel -> see vectorPutPixel
+ _vectorPutLinePixelPtr = &GfxScreen::vectorPutLinePixel480x300Mac;
+ _putPixelPtr = &GfxScreen::putPixelAllUpscaled;
+ _getPixelPtr = &GfxScreen::getPixelUpscaled;
+ break;
+ case GFX_SCREEN_UPSCALED_640x400:
+ case GFX_SCREEN_UPSCALED_640x440:
+ case GFX_SCREEN_UPSCALED_640x480:
+ _vectorPutPixelPtr = &GfxScreen::putPixelDisplayUpscaled;
+ _putPixelPtr = &GfxScreen::putPixelDisplayUpscaled;
+ break;
+ }
}
GfxScreen::~GfxScreen() {
@@ -232,7 +292,7 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect, int16 x, int16 y) {
} else {
int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top];
int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
-
+
g_system->copyRectToScreen(_activeScreen + _upscaledHeightMapping[rect.top] * _displayWidth + _upscaledWidthMapping[rect.left], _displayWidth, _upscaledWidthMapping[x], _upscaledHeightMapping[y], rectWidth, rectHeight);
}
}
@@ -248,43 +308,162 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) {
return flag;
}
-void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, byte control) {
- int offset = y * _pitch + x;
+void GfxScreen::vectorAdjustCoordinateNOP(int16 *x, int16 *y) {
+}
- if (drawMask & GFX_SCREEN_MASK_VISUAL) {
- _visualScreen[offset] = color;
- if (!_upscaledHires) {
- _displayScreen[offset] = color;
+void GfxScreen::vectorAdjustCoordinate480x300Mac(int16 *x, int16 *y) {
+ *x = _upscaledWidthMapping[*x];
+ *y = _upscaledHeightMapping[*y];
+}
+
+void GfxScreen::vectorAdjustLineCoordinatesNOP(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) {
+}
+
+void GfxScreen::vectorAdjustLineCoordinates480x300Mac(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) {
+ int16 displayLeft = _upscaledWidthMapping[*left];
+ int16 displayRight = _upscaledWidthMapping[*right];
+ int16 displayTop = _upscaledHeightMapping[*top];
+ int16 displayBottom = _upscaledHeightMapping[*bottom];
+
+ if (displayLeft < displayRight) {
+ // one more pixel to the left, one more pixel to the right
+ if (displayLeft > 0)
+ vectorPutLinePixel(displayLeft - 1, displayTop, drawMask, color, priority, control);
+ vectorPutLinePixel(displayRight + 1, displayBottom, drawMask, color, priority, control);
+ } else if (displayLeft > displayRight) {
+ if (displayRight > 0)
+ vectorPutLinePixel(displayRight - 1, displayBottom, drawMask, color, priority, control);
+ vectorPutLinePixel(displayLeft + 1, displayTop, drawMask, color, priority, control);
+ }
+ *left = displayLeft;
+ *top = displayTop;
+ *right = displayRight;
+ *bottom = displayBottom;
+}
+
+byte GfxScreen::vectorIsFillMatchNormal(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA) {
+ int offset = y * _width + x;
+ byte match = 0;
+
+ if (screenMask & GFX_SCREEN_MASK_VISUAL) {
+ if (!isEGA) {
+ if (*(_visualScreen + offset) == checkForColor)
+ match |= GFX_SCREEN_MASK_VISUAL;
} else {
- putScaledPixelOnDisplay(x, y, color);
+ // In EGA games a pixel in the framebuffer is only 4 bits. We store
+ // a full byte per pixel to allow undithering, but when comparing
+ // pixels for flood-fill purposes, we should only compare the
+ // visible color of a pixel.
+
+ byte EGAcolor = *(_visualScreen + offset);
+ if ((x ^ y) & 1)
+ EGAcolor = (EGAcolor ^ (EGAcolor >> 4)) & 0x0F;
+ else
+ EGAcolor = EGAcolor & 0x0F;
+ if (EGAcolor == checkForColor)
+ match |= GFX_SCREEN_MASK_VISUAL;
}
}
+ if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == checkForPriority)
+ match |= GFX_SCREEN_MASK_PRIORITY;
+ if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == checkForControl)
+ match |= GFX_SCREEN_MASK_CONTROL;
+ return match;
+}
+
+// Special 480x300 Mac putPixel for vector line drawing, also draws an additional pixel below the actual one
+void GfxScreen::vectorPutLinePixel480x300Mac(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ int offset = y * _width + x;
+
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ _visualScreen[offset] = color;
+ _visualScreen[offset + _width] = color;
+ _displayScreen[offset] = color;
+ // also set pixel below actual pixel
+ _displayScreen[offset + _displayWidth] = color;
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
+ _priorityScreen[offset] = priority;
+ _priorityScreen[offset + _width] = priority;
+ }
+ if (drawMask & GFX_SCREEN_MASK_CONTROL) {
+ _controlScreen[offset] = control;
+ _controlScreen[offset + _width] = control;
+ }
+}
+
+// Directly sets a pixel on various screens, display is not upscaled
+void GfxScreen::putPixelNormal(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ int offset = y * _width + x;
+
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ _visualScreen[offset] = color;
+ _displayScreen[offset] = color;
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY)
+ _priorityScreen[offset] = priority;
+ if (drawMask & GFX_SCREEN_MASK_CONTROL)
+ _controlScreen[offset] = control;
+}
+
+// Directly sets a pixel on various screens, display IS upscaled
+void GfxScreen::putPixelDisplayUpscaled(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ int offset = y * _width + x;
+
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ _visualScreen[offset] = color;
+ putScaledPixelOnScreen(_displayScreen, x, y, color);
+ }
if (drawMask & GFX_SCREEN_MASK_PRIORITY)
_priorityScreen[offset] = priority;
if (drawMask & GFX_SCREEN_MASK_CONTROL)
_controlScreen[offset] = control;
}
+// Directly sets a pixel on various screens, ALL screens ARE upscaled
+void GfxScreen::putPixelAllUpscaled(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ putScaledPixelOnScreen(_visualScreen, x, y, color);
+ putScaledPixelOnScreen(_displayScreen, x, y, color);
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY)
+ putScaledPixelOnScreen(_priorityScreen, x, y, priority);
+ if (drawMask & GFX_SCREEN_MASK_CONTROL)
+ putScaledPixelOnScreen(_controlScreen, x, y, control);
+}
+
/**
* This is used to put font pixels onto the screen - we adjust differently, so that we won't
* do triple pixel lines in any case on upscaled hires. That way the font will not get distorted
* Sierra SCI didn't do this
*/
-void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) {
- int actualY = startingY + y;
+void GfxScreen::putFontPixel(int16 startingY, int16 x, int16 y, byte color) {
+ int16 actualY = startingY + y;
if (_fontIsUpscaled) {
// Do not scale ourselves, but put it on the display directly
putPixelOnDisplay(x, actualY, color);
} else {
- int offset = actualY * _pitch + x;
+ int offset = actualY * _width + x;
_visualScreen[offset] = color;
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_DISABLED:
_displayScreen[offset] = color;
break;
+ case GFX_SCREEN_UPSCALED_640x400:
+ case GFX_SCREEN_UPSCALED_640x440:
+ case GFX_SCREEN_UPSCALED_640x480: {
+ // to 1-> 4 pixels upscaling for all of those, so that fonts won't look weird
+ int displayOffset = (_upscaledHeightMapping[startingY] + y * 2) * _displayWidth + x * 2;
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ displayOffset += _displayWidth;
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ break;
+ }
default:
- putScaledPixelOnDisplay(x, actualY, color);
+ putScaledPixelOnScreen(_displayScreen, x, actualY, color);
break;
}
}
@@ -295,12 +474,15 @@ void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) {
* only used on upscaled-Hires games where hires content needs to get drawn ONTO
* the upscaled display screen (like japanese fonts, hires portraits, etc.).
*/
-void GfxScreen::putPixelOnDisplay(int x, int y, byte color) {
+void GfxScreen::putPixelOnDisplay(int16 x, int16 y, byte color) {
int offset = y * _displayWidth + x;
_displayScreen[offset] = color;
}
-void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) {
+//void GfxScreen::putScaledPixelOnDisplay(int16 x, int16 y, byte color) {
+//}
+
+void GfxScreen::putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte data) {
int displayOffset = _upscaledHeightMapping[y] * _displayWidth + _upscaledWidthMapping[x];
int heightOffsetBreak = (_upscaledHeightMapping[y + 1] - _upscaledHeightMapping[y]) * _displayWidth;
int heightOffset = 0;
@@ -308,7 +490,7 @@ void GfxScreen::putScaledPixelOnDisplay(int x, int y, byte color) {
do {
int widthOffset = 0;
do {
- _displayScreen[displayOffset + heightOffset + widthOffset] = color;
+ screen[displayOffset + heightOffset + widthOffset] = data;
widthOffset++;
} while (widthOffset != widthOffsetBreak);
heightOffset += _displayWidth;
@@ -329,16 +511,18 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
int16 top = CLIP<int16>(startPoint.y, 0, maxHeight);
int16 right = CLIP<int16>(endPoint.x, 0, maxWidth);
int16 bottom = CLIP<int16>(endPoint.y, 0, maxHeight);
-
+
//set_drawing_flag
byte drawMask = getDrawingMask(color, priority, control);
+ vectorAdjustLineCoordinates(&left, &top, &right, &bottom, drawMask, color, priority, control);
+
// horizontal line
if (top == bottom) {
if (right < left)
SWAP(right, left);
for (int i = left; i <= right; i++)
- putPixel(i, top, drawMask, color, priority, control);
+ vectorPutLinePixel(i, top, drawMask, color, priority, control);
return;
}
// vertical line
@@ -346,20 +530,20 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
if (top > bottom)
SWAP(top, bottom);
for (int i = top; i <= bottom; i++)
- putPixel(left, i, drawMask, color, priority, control);
+ vectorPutLinePixel(left, i, drawMask, color, priority, control);
return;
}
// sloped line - draw with Bresenham algorithm
- int dy = bottom - top;
- int dx = right - left;
- int stepy = dy < 0 ? -1 : 1;
- int stepx = dx < 0 ? -1 : 1;
+ int16 dy = bottom - top;
+ int16 dx = right - left;
+ int16 stepy = dy < 0 ? -1 : 1;
+ int16 stepx = dx < 0 ? -1 : 1;
dy = ABS(dy) << 1;
dx = ABS(dx) << 1;
// setting the 1st and last pixel
- putPixel(left, top, drawMask, color, priority, control);
- putPixel(right, bottom, drawMask, color, priority, control);
+ vectorPutLinePixel(left, top, drawMask, color, priority, control);
+ vectorPutLinePixel(right, bottom, drawMask, color, priority, control);
// drawing the line
if (dx > dy) { // going horizontal
int fraction = dy - (dx >> 1);
@@ -370,7 +554,7 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
}
left += stepx;
fraction += dy;
- putPixel(left, top, drawMask, color, priority, control);
+ vectorPutLinePixel(left, top, drawMask, color, priority, control);
}
} else { // going vertical
int fraction = dx - (dy >> 1);
@@ -381,7 +565,7 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
}
top += stepy;
fraction += dx;
- putPixel(left, top, drawMask, color, priority, control);
+ vectorPutLinePixel(left, top, drawMask, color, priority, control);
}
}
}
@@ -394,46 +578,14 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u
commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0, -1, -1);
}
-byte GfxScreen::getVisual(int x, int y) {
- return _visualScreen[y * _pitch + x];
-}
-
-byte GfxScreen::getPriority(int x, int y) {
- return _priorityScreen[y * _pitch + x];
-}
-
-byte GfxScreen::getControl(int x, int y) {
- return _controlScreen[y * _pitch + x];
+byte GfxScreen::getPixelNormal(byte *screen, int16 x, int16 y) {
+ return screen[y * _width + x];
}
-byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) {
- int offset = y * _pitch + x;
- byte match = 0;
-
- if (screenMask & GFX_SCREEN_MASK_VISUAL) {
- if (!isEGA) {
- if (*(_visualScreen + offset) == t_color)
- match |= GFX_SCREEN_MASK_VISUAL;
- } else {
- // In EGA games a pixel in the framebuffer is only 4 bits. We store
- // a full byte per pixel to allow undithering, but when comparing
- // pixels for flood-fill purposes, we should only compare the
- // visible color of a pixel.
-
- byte c = *(_visualScreen + offset);
- if ((x ^ y) & 1)
- c = (c ^ (c >> 4)) & 0x0F;
- else
- c = c & 0x0F;
- if (c == t_color)
- match |= GFX_SCREEN_MASK_VISUAL;
- }
- }
- if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && *(_priorityScreen + offset) == t_pri)
- match |= GFX_SCREEN_MASK_PRIORITY;
- if ((screenMask & GFX_SCREEN_MASK_CONTROL) && *(_controlScreen + offset) == t_con)
- match |= GFX_SCREEN_MASK_CONTROL;
- return match;
+byte GfxScreen::getPixelUpscaled(byte *screen, int16 x, int16 y) {
+ int16 mappedX = _upscaledWidthMapping[x];
+ int16 mappedY = _upscaledHeightMapping[y];
+ return screen[mappedY * _width + mappedX];
}
int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) {
@@ -469,14 +621,14 @@ void GfxScreen::bitsSave(Common::Rect rect, byte mask, byte *memoryPtr) {
memcpy(memoryPtr, (void *)&mask, sizeof(mask)); memoryPtr += sizeof(mask);
if (mask & GFX_SCREEN_MASK_VISUAL) {
- bitsSaveScreen(rect, _visualScreen, _pitch, memoryPtr);
+ bitsSaveScreen(rect, _visualScreen, _width, memoryPtr);
bitsSaveDisplayScreen(rect, memoryPtr);
}
if (mask & GFX_SCREEN_MASK_PRIORITY) {
- bitsSaveScreen(rect, _priorityScreen, _pitch, memoryPtr);
+ bitsSaveScreen(rect, _priorityScreen, _width, memoryPtr);
}
if (mask & GFX_SCREEN_MASK_CONTROL) {
- bitsSaveScreen(rect, _controlScreen, _pitch, memoryPtr);
+ bitsSaveScreen(rect, _controlScreen, _width, memoryPtr);
}
if (mask & GFX_SCREEN_MASK_DISPLAY) {
if (!_upscaledHires)
@@ -530,14 +682,14 @@ void GfxScreen::bitsRestore(byte *memoryPtr) {
memcpy((void *)&mask, memoryPtr, sizeof(mask)); memoryPtr += sizeof(mask);
if (mask & GFX_SCREEN_MASK_VISUAL) {
- bitsRestoreScreen(rect, memoryPtr, _visualScreen, _pitch);
+ bitsRestoreScreen(rect, memoryPtr, _visualScreen, _width);
bitsRestoreDisplayScreen(rect, memoryPtr);
}
if (mask & GFX_SCREEN_MASK_PRIORITY) {
- bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _pitch);
+ bitsRestoreScreen(rect, memoryPtr, _priorityScreen, _width);
}
if (mask & GFX_SCREEN_MASK_CONTROL) {
- bitsRestoreScreen(rect, memoryPtr, _controlScreen, _pitch);
+ bitsRestoreScreen(rect, memoryPtr, _controlScreen, _width);
}
if (mask & GFX_SCREEN_MASK_DISPLAY) {
if (!_upscaledHires)
@@ -612,21 +764,22 @@ void GfxScreen::dither(bool addToFlag) {
byte color, ditheredColor;
byte *visualPtr = _visualScreen;
byte *displayPtr = _displayScreen;
-
+
if (!_unditheringEnabled) {
// Do dithering on visual and display-screen
for (y = 0; y < _height; y++) {
- for (x = 0; x < _pitch; x++) {
+ for (x = 0; x < _width; x++) {
color = *visualPtr;
if (color & 0xF0) {
color ^= color << 4;
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_DISABLED:
+ case GFX_SCREEN_UPSCALED_480x300:
*displayPtr = color;
break;
default:
- putScaledPixelOnDisplay(x, y, color);
+ putScaledPixelOnScreen(_displayScreen, x, y, color);
break;
}
*visualPtr = color;
@@ -639,7 +792,7 @@ void GfxScreen::dither(bool addToFlag) {
memset(&_ditheredPicColors, 0, sizeof(_ditheredPicColors));
// Do dithering on visual screen and put decoded but undithered byte onto display-screen
for (y = 0; y < _height; y++) {
- for (x = 0; x < _pitch; x++) {
+ for (x = 0; x < _width; x++) {
color = *visualPtr;
if (color & 0xF0) {
color ^= color << 4;
@@ -654,10 +807,11 @@ void GfxScreen::dither(bool addToFlag) {
}
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_DISABLED:
+ case GFX_SCREEN_UPSCALED_480x300:
*displayPtr = ditheredColor;
break;
default:
- putScaledPixelOnDisplay(x, y, ditheredColor);
+ putScaledPixelOnScreen(_displayScreen, x, y, ditheredColor);
break;
}
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
@@ -685,8 +839,8 @@ int16 *GfxScreen::unditherGetDitheredBgColors() {
}
void GfxScreen::debugShowMap(int mapNo) {
- // We cannot really support changing maps when in upscaledHires mode
- if (_upscaledHires)
+ // We cannot really support changing maps when display screen has a different resolution than visual screen
+ if ((_width != _displayWidth) || (_height != _displayHeight))
return;
switch (mapNo) {
@@ -779,8 +933,8 @@ void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativ
switch (_upscaledHires) {
case GFX_SCREEN_UPSCALED_480x300:
- x = (x << 1) / 3;
- y = (y << 1) / 3;
+ x = (x * 4) / 6;
+ y = (y * 4) / 6;
break;
case GFX_SCREEN_UPSCALED_640x400:
x /= 2;
@@ -816,26 +970,4 @@ int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) {
return oldPicNotValid;
}
-uint16 GfxScreen::getLowResScreenHeight() {
- // Some Mac SCI1/1.1 games only take up 190 rows and do not
- // have the menu bar.
- // TODO: Verify that LSL1 and LSL5 use height 190
- if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
- switch (g_sci->getGameId()) {
- case GID_FREDDYPHARKAS:
- case GID_KQ5:
- case GID_KQ6:
- case GID_LSL1:
- case GID_LSL5:
- case GID_SQ1:
- return 190;
- default:
- break;
- }
- }
-
- // Everything else is 200
- return 200;
-}
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index e266a4ed16..766e32614a 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -69,6 +69,8 @@ public:
uint16 getWidth() { return _width; }
uint16 getHeight() { return _height; }
+ uint16 getScriptWidth() { return _scriptWidth; }
+ uint16 getScriptHeight() { return _scriptHeight; }
uint16 getDisplayWidth() { return _displayWidth; }
uint16 getDisplayHeight() { return _displayHeight; }
byte getColorWhite() { return _colorWhite; }
@@ -81,11 +83,51 @@ public:
void copyDisplayRectToScreen(const Common::Rect &rect);
void copyRectToScreen(const Common::Rect &rect, int16 x, int16 y);
+ // calls to code pointers
+ void inline vectorAdjustCoordinate (int16 *x, int16 *y) {
+ (this->*_vectorAdjustCoordinatePtr)(x, y);
+ }
+ void inline vectorAdjustLineCoordinates (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) {
+ (this->*_vectorAdjustLineCoordinatesPtr)(left, top, right, bottom, drawMask, color, priority, control);
+ }
+ byte inline vectorIsFillMatch (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA) {
+ return (this->*_vectorIsFillMatchPtr)(x, y, screenMask, t_color, t_pri, t_con, isEGA);
+ }
+ void inline vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ (this->*_vectorPutPixelPtr)(x, y, drawMask, color, priority, control);
+ }
+ void inline vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ (this->*_vectorPutLinePixelPtr)(x, y, drawMask, color, priority, control);
+ }
+ byte inline vectorGetVisual(int16 x, int16 y) {
+ return (this->*_vectorGetPixelPtr)(_visualScreen, x, y);
+ }
+ byte inline vectorGetPriority(int16 x, int16 y) {
+ return (this->*_vectorGetPixelPtr)(_priorityScreen, x, y);
+ }
+ byte inline vectorGetControl(int16 x, int16 y) {
+ return (this->*_vectorGetPixelPtr)(_controlScreen, x, y);
+ }
+
+
+ void inline putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ (this->*_putPixelPtr)(x, y, drawMask, color, priority, control);
+ }
+
+ byte inline getVisual(int16 x, int16 y) {
+ return (this->*_getPixelPtr)(_visualScreen, x, y);
+ }
+ byte inline getPriority(int16 x, int16 y) {
+ return (this->*_getPixelPtr)(_priorityScreen, x, y);
+ }
+ byte inline getControl(int16 x, int16 y) {
+ return (this->*_getPixelPtr)(_controlScreen, x, y);
+ }
+
byte getDrawingMask(byte color, byte prio, byte control);
- void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control);
- void putFontPixel(int startingY, int x, int y, byte color);
- void putPixelOnDisplay(int x, int y, byte color);
- void putScaledPixelOnDisplay(int x, int y, byte color);
+ //void putPixel(int16 x, int16 y, byte drawMask, byte color, byte prio, byte control);
+ void putFontPixel(int16 startingY, int16 x, int16 y, byte color);
+ void putPixelOnDisplay(int16 x, int16 y, byte color);
void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control);
void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
@@ -101,10 +143,6 @@ public:
void enableUndithering(bool flag);
void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
- byte getVisual(int x, int y);
- byte getPriority(int x, int y);
- byte getControl(int x, int y);
- byte isFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
int bitsGetDataSize(Common::Rect rect, byte mask);
void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
@@ -135,9 +173,10 @@ public:
private:
uint16 _width;
- uint16 _pitch;
uint16 _height;
uint _pixels;
+ uint16 _scriptWidth;
+ uint16 _scriptHeight;
uint16 _displayWidth;
uint16 _displayHeight;
uint _displayPixels;
@@ -190,8 +229,8 @@ private:
* This here holds a translation for vertical+horizontal coordinates between native
* (visual) and actual (display) screen.
*/
- int _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
- int _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1];
+ int16 _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
+ int16 _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1];
/**
* This defines whether or not the font we're drawing is already scaled
@@ -199,7 +238,38 @@ private:
*/
bool _fontIsUpscaled;
- uint16 getLowResScreenHeight();
+ // dynamic code
+ void (GfxScreen::*_vectorAdjustCoordinatePtr) (int16 *x, int16 *y);
+ void vectorAdjustCoordinateNOP (int16 *x, int16 *y);
+ void vectorAdjustCoordinate480x300Mac (int16 *x, int16 *y);
+
+ void (GfxScreen::*_vectorAdjustLineCoordinatesPtr) (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
+ void vectorAdjustLineCoordinatesNOP (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
+ void vectorAdjustLineCoordinates480x300Mac (int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
+
+ byte (GfxScreen::*_vectorIsFillMatchPtr) (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
+ byte vectorIsFillMatchNormal (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
+ byte vectorIsFillMatch480x300Mac (int16 x, int16 y, byte screenMask, byte t_color, byte t_pri, byte t_con, bool isEGA);
+
+ void (GfxScreen::*_vectorPutPixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void vectorPutPixel480x300Mac (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+
+ void (GfxScreen::*_vectorPutLinePixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void vectorPutLinePixel480x300Mac (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+
+ byte (GfxScreen::*_vectorGetPixelPtr) (byte *screen, int16 x, int16 y);
+
+ void (GfxScreen::*_putPixelPtr) (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void putPixelNormal (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void putPixelDisplayUpscaled (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void putPixelAllUpscaled (int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+
+ byte (GfxScreen::*_getPixelPtr) (byte *screen, int16 x, int16 y);
+ byte getPixelNormal (byte *screen, int16 x, int16 y);
+ byte getPixelUpscaled (byte *screen, int16 x, int16 y);
+
+ // pixel helper
+ void putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte color);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 245d6996cb..f463dff4b1 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -143,18 +143,30 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1
return textCodeSize;
}
-static const uint16 text16_punctuationSjis[] = {
- 0x9F82, 0xA182, 0xA382, 0xA582, 0xA782, 0xC182, 0xA782, 0xC182, 0xE182, 0xE382, 0xE582, 0xEC82,
- 0x4083, 0x4283, 0x4483, 0x4683, 0x4883, 0x6283, 0x8383, 0x8583, 0x8783, 0x8E83, 0x9583, 0x9683,
- 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0
+// Has actually punctuation and characters in it, that may not be the first in a line
+static const uint16 text16_shiftJIS_punctuation[] = {
+ 0x9F82, 0xA182, 0xA382, 0xA582, 0xA782, 0xC182, 0xE182, 0xE382, 0xE582, 0xEC82, 0x4083, 0x4283,
+ 0x4483, 0x4683, 0x4883, 0x6283, 0x8383, 0x8583, 0x8783, 0x8E83, 0x9583, 0x9683, 0x5B81, 0x4181,
+ 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0
};
// return max # of chars to fit maxwidth with full words, does not include
// breaking space
-int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) {
+// Also adjusts text pointer to the new position for the caller
+//
+// Special cases in games:
+// Laura Bow 2 - Credits in the game menu - all the text lines start with spaces (bug #5159)
+// Act 6 Coroner questionaire - the text of all control buttons has trailing spaces
+// "Detective Ryan Hanrahan O'Riley" contains even more spaces (bug #5334)
+// Conquests of Camelot - talking with Cobb - one text box of the dialogue contains a longer word,
+// that will be broken into 2 lines (bug #5159)
+int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId orgFontId) {
uint16 curChar = 0;
- int16 maxChars = 0, curCharCount = 0;
- uint16 width = 0;
+ const char *textStartPtr = textPtr;
+ const char *lastSpacePtr = NULL;
+ int16 lastSpaceCharCount = 0;
+ int16 curCharCount = 0, resultCharCount = 0;
+ uint16 curWidth = 0, tempWidth = 0;
GuiResourceId previousFontId = GetFontId();
int16 previousPenColor = _ports->_curPort->penClr;
@@ -162,35 +174,38 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
if (!_font)
return 0;
- while (width <= maxWidth) {
- curChar = (*(const byte *)text++);
+ while (1) {
+ curChar = (*(const byte *)textPtr);
if (_font->isDoubleByte(curChar)) {
- curChar |= (*(const byte *)text++) << 8;
- curCharCount++;
+ curChar |= (*(const byte *)(textPtr + 1)) << 8;
}
switch (curChar) {
case 0x7C:
if (getSciVersion() >= SCI_VERSION_1_1) {
- curCharCount++;
- curCharCount += CodeProcessing(text, orgFontId, previousPenColor, false);
+ curCharCount++; textPtr++;
+ curCharCount += CodeProcessing(textPtr, orgFontId, previousPenColor, false);
continue;
}
break;
// We need to add 0xD, 0xA and 0xD 0xA to curCharCount and then exit
- // which means, we split text like
- // 'Mature, experienced software analyst available.' 0xD 0xA
- // 'Bug installation a proven speciality. "No version too clean."' (normal game text, this is from lsl2)
- // and 0xA '-------' 0xA (which is the official sierra subtitle separator)
+ // which means, we split text like for example
+ // - 'Mature, experienced software analyst available.' 0xD 0xA
+ // 'Bug installation a proven speciality. "No version too clean."' (normal game text, this is from lsl2)
+ // - 0xA '-------' 0xA (which is the official sierra subtitle separator) (found in multilingual versions)
// Sierra did it the same way.
case 0xD:
// Check, if 0xA is following, if so include it as well
- if ((*(const unsigned char *)text) == 0xA)
- curCharCount++;
+ if ((*(const byte *)(textPtr + 1)) == 0xA) {
+ curCharCount++; textPtr++;
+ }
// it's meant to pass through here
case 0xA:
case 0x9781: // this one is used by SQ4/japanese as line break as well
- curCharCount++;
+ curCharCount++; textPtr++;
+ if (curChar > 0xFF) {
+ curCharCount++; textPtr++;
+ }
// and it's also meant to pass through here
case 0:
SetFont(previousFontId);
@@ -198,55 +213,86 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF
return curCharCount;
case ' ':
- maxChars = curCharCount; // return count up to (but not including) breaking space
+ lastSpaceCharCount = curCharCount; // return count up to (but not including) breaking space
+ lastSpacePtr = textPtr + 1; // remember position right after the current space
break;
}
- // Sometimes this can go off the screen, like for example bug #3040161.
- // However, we only perform this for non-Japanese games, as these require
- // special handling, done after this loop.
- if (width + _font->getCharWidth(curChar) > maxWidth && g_sci->getLanguage() != Common::JA_JPN)
+ tempWidth += _font->getCharWidth(curChar);
+
+ // Width is too large? -> break out
+ if (tempWidth > maxWidth)
break;
- width += _font->getCharWidth(curChar);
- curCharCount++;
+
+ // still fits, remember width
+ curWidth = tempWidth;
+
+ // go to next character
+ curCharCount++; textPtr++;
+ if (curChar > 0xFF) {
+ // Double-Byte
+ curCharCount++; textPtr++;
+ }
}
- // Text without spaces, probably Kanji/Japanese
- if (maxChars == 0) {
- maxChars = curCharCount;
+ if (lastSpaceCharCount) {
+ // Break and at least one space was found before that
+ resultCharCount = lastSpaceCharCount;
- uint16 nextChar;
+ // additionally skip over all spaces, that are following that space, but don't count them for displaying purposes
+ textPtr = lastSpacePtr;
+ while (*textPtr == ' ')
+ textPtr++;
- // We remove the last char only, if maxWidth was actually equal width
- // before adding the last char. Otherwise we won't get the same cutting
- // as in sierra pc98 sci.
- if (maxWidth == (width - _font->getCharWidth(curChar))) {
- maxChars--;
- if (curChar > 0xFF)
- maxChars--;
- nextChar = curChar;
- } else {
- nextChar = (*(const byte *)text++);
- if (_font->isDoubleByte(nextChar))
- nextChar |= (*(const byte *)text++) << 8;
- }
- // sierra checked the following character against a punctuation kanji table
- if (nextChar > 0xFF) {
- // if the character is punctuation, we go back one character
- uint nonBreakingNr = 0;
- while (text16_punctuationSjis[nonBreakingNr]) {
- if (text16_punctuationSjis[nonBreakingNr] == nextChar) {
- maxChars--;
- if (curChar > 0xFF)
- maxChars--; // go back 2 chars, when last char was double byte
+ } else {
+ // Break without spaces found, we split the very first word - may also be Kanji/Japanese
+ if (curChar > 0xFF) {
+ // current charracter is Japanese
+
+ // PC-9801 SCI actually added the last character, which shouldn't fit anymore, still onto the
+ // screen in case maxWidth wasn't fully reached with the last character
+ if (( maxWidth - 1 ) > curWidth) {
+ curCharCount += 2; textPtr += 2;
+
+ curChar = (*(const byte *)textPtr);
+ if (_font->isDoubleByte(curChar)) {
+ curChar |= (*(const byte *)(textPtr + 1)) << 8;
+ }
+ }
+
+ // But it also checked, if the current character is not inside a punctuation table and it even
+ // went backwards in case it found multiple ones inside that table.
+ uint nonBreakingPos = 0;
+
+ while (1) {
+ // Look up if character shouldn't be the first on a new line
+ nonBreakingPos = 0;
+ while (text16_shiftJIS_punctuation[nonBreakingPos]) {
+ if (text16_shiftJIS_punctuation[nonBreakingPos] == curChar)
+ break;
+ nonBreakingPos++;
+ }
+ if (!text16_shiftJIS_punctuation[nonBreakingPos]) {
+ // character is fine
break;
}
- nonBreakingNr++;
+ // Character is not acceptable, seek backward in the text
+ curCharCount -= 2; textPtr -= 2;
+ if (textPtr < textStartPtr)
+ error("Seeking back went too far, data corruption?");
+
+ curChar = (*(const byte *)textPtr);
+ if (!_font->isDoubleByte(curChar))
+ error("Non double byte while seeking back");
+ curChar |= (*(const byte *)(textPtr + 1)) << 8;
}
}
+
+ // We split the word in that case
+ resultCharCount = curCharCount;
}
SetFont(previousFontId);
_ports->penColor(previousPenColor);
- return maxChars;
+ return resultCharCount;
}
void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont) {
@@ -303,7 +349,7 @@ void GfxText16::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPe
Draw(str, 0, (int16)strlen(str), orgFontId, orgPenColor);
}
-int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth) {
+int16 GfxText16::Size(Common::Rect &rect, const char *text, uint16 languageSplitter, GuiResourceId fontId, int16 maxWidth) {
GuiResourceId previousFontId = GetFontId();
int16 previousPenColor = _ports->_curPort->penClr;
int16 charCount;
@@ -315,12 +361,12 @@ int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
else
fontId = previousFontId;
- if (g_sci->getLanguage() == Common::JA_JPN)
- SwitchToFont900OnSjis(text);
-
rect.top = rect.left = 0;
if (maxWidth < 0) { // force output as single line
+ if (g_sci->getLanguage() == Common::JA_JPN)
+ SwitchToFont900OnSjis(text, languageSplitter);
+
StringWidth(text, fontId, textWidth, textHeight);
rect.bottom = textHeight;
rect.right = textWidth;
@@ -328,17 +374,20 @@ int16 GfxText16::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
// rect.right=found widest line with RTextWidth and GetLongest
// rect.bottom=num. lines * GetPointSize
rect.right = (maxWidth ? maxWidth : 192);
- const char *curPos = text;
- while (*curPos) {
- charCount = GetLongest(curPos, rect.right, fontId);
+ const char *curTextPos = text; // in work position for GetLongest()
+ const char *curTextLine = text; // starting point of current line
+ while (*curTextPos) {
+ // We need to check for Shift-JIS every line
+ if (g_sci->getLanguage() == Common::JA_JPN)
+ SwitchToFont900OnSjis(curTextPos, languageSplitter);
+
+ charCount = GetLongest(curTextPos, rect.right, fontId);
if (charCount == 0)
break;
- Width(curPos, 0, charCount, fontId, textWidth, textHeight, false);
+ Width(curTextLine, 0, charCount, fontId, textWidth, textHeight, false);
maxTextWidth = MAX(textWidth, maxTextWidth);
totalHeight += textHeight;
- curPos += charCount;
- while (*curPos == ' ')
- curPos++; // skip over breaking spaces
+ curTextLine = curTextPos;
}
rect.bottom = totalHeight;
rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth);
@@ -405,34 +454,38 @@ void GfxText16::Show(const char *text, int16 from, int16 len, GuiResourceId orgF
}
// Draws a text in rect.
-void GfxText16::Box(const char *text, bool show, const Common::Rect &rect, TextAlignment alignment, GuiResourceId fontId) {
+void GfxText16::Box(const char *text, uint16 languageSplitter, bool show, const Common::Rect &rect, TextAlignment alignment, GuiResourceId fontId) {
int16 textWidth, maxTextWidth, textHeight, charCount;
int16 offset = 0;
int16 hline = 0;
GuiResourceId previousFontId = GetFontId();
int16 previousPenColor = _ports->_curPort->penClr;
bool doubleByteMode = false;
+ const char *curTextPos = text;
+ const char *curTextLine = text;
if (fontId != -1)
SetFont(fontId);
else
fontId = previousFontId;
- if (g_sci->getLanguage() == Common::JA_JPN) {
- if (SwitchToFont900OnSjis(text))
- doubleByteMode = true;
- }
-
// Reset reference code rects
_codeRefRects.clear();
_codeRefTempRect.left = _codeRefTempRect.top = -1;
maxTextWidth = 0;
- while (*text) {
- charCount = GetLongest(text, rect.width(), fontId);
+ while (*curTextPos) {
+ // We need to check for Shift-JIS every line
+ // Police Quest 2 PC-9801 often draws English + Japanese text during the same call
+ if (g_sci->getLanguage() == Common::JA_JPN) {
+ if (SwitchToFont900OnSjis(curTextPos, languageSplitter))
+ doubleByteMode = true;
+ }
+
+ charCount = GetLongest(curTextPos, rect.width(), fontId);
if (charCount == 0)
break;
- Width(text, 0, charCount, fontId, textWidth, textHeight, true);
+ Width(curTextLine, 0, charCount, fontId, textWidth, textHeight, true);
maxTextWidth = MAX<int16>(maxTextWidth, textWidth);
switch (alignment) {
case SCI_TEXT16_ALIGNMENT_RIGHT:
@@ -451,15 +504,13 @@ void GfxText16::Box(const char *text, bool show, const Common::Rect &rect, TextA
_ports->moveTo(rect.left + offset, rect.top + hline);
if (show) {
- Show(text, 0, charCount, fontId, previousPenColor);
+ Show(curTextLine, 0, charCount, fontId, previousPenColor);
} else {
- Draw(text, 0, charCount, fontId, previousPenColor);
+ Draw(curTextLine, 0, charCount, fontId, previousPenColor);
}
hline += textHeight;
- text += charCount;
- while (*text == ' ')
- text++; // skip over breaking spaces
+ curTextLine = curTextPos;
}
SetFont(previousFontId);
_ports->penColor(previousPenColor);
@@ -521,11 +572,13 @@ void GfxText16::DrawStatus(const char *text) {
// Sierra did this in their PC98 interpreter only, they identify a text as being
// sjis and then switch to font 900
-bool GfxText16::SwitchToFont900OnSjis(const char *text) {
+bool GfxText16::SwitchToFont900OnSjis(const char *text, uint16 languageSplitter) {
byte firstChar = (*(const byte *)text++);
- if (((firstChar >= 0x81) && (firstChar <= 0x9F)) || ((firstChar >= 0xE0) && (firstChar <= 0xEF))) {
- SetFont(900);
- return true;
+ if (languageSplitter != 0x6a23) { // #j prefix as language splitter
+ if (((firstChar >= 0x81) && (firstChar <= 0x9F)) || ((firstChar >= 0xE0) && (firstChar <= 0xEF))) {
+ SetFont(900);
+ return true;
+ }
}
return false;
}
@@ -554,9 +607,9 @@ reg_t GfxText16::allocAndFillReferenceRectArray() {
return NULL_REG;
}
-void GfxText16::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
+void GfxText16::kernelTextSize(const char *text, uint16 languageSplitter, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
Common::Rect rect(0, 0, 0, 0);
- Size(rect, text, font, maxWidth);
+ Size(rect, text, languageSplitter, font, maxWidth);
*textWidth = rect.width();
*textHeight = rect.height();
}
diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h
index ab0cb13a64..2724d97347 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -51,15 +51,20 @@ public:
void ClearChar(int16 chr);
- int16 GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId);
+ 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);
- int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth);
+ 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);
- void Box(const char *text, bool show, const Common::Rect &rect, TextAlignment alignment, GuiResourceId fontId);
+ void Box(const char *text, uint16 languageSplitter, bool show, const Common::Rect &rect, TextAlignment alignment, GuiResourceId fontId);
+
+ void Box(const char *text, bool show, const Common::Rect &rect, TextAlignment alignment, GuiResourceId fontId) {
+ Box(text, 0, show, rect, alignment, fontId);
+ }
+
void DrawString(const char *text);
void DrawStatus(const char *text);
@@ -67,13 +72,13 @@ public:
reg_t allocAndFillReferenceRectArray();
- void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+ void kernelTextSize(const char *text, uint16 textLanguage, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
void kernelTextFonts(int argc, reg_t *argv);
void kernelTextColors(int argc, reg_t *argv);
private:
void init();
- bool SwitchToFont900OnSjis(const char *text);
+ bool SwitchToFont900OnSjis(const char *text, uint16 languageSplitter);
GfxCache *_cache;
GfxPorts *_ports;
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index 5e7dbc6c15..ccc7a4389a 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -339,10 +339,10 @@ void GfxTransitions::pixelation(bool blackoutFlag) {
do {
mask = (mask & 1) ? (mask >> 1) ^ 0xB400 : mask >> 1;
- if (mask >= _screen->getWidth() * _screen->getHeight())
+ if (mask >= _screen->getScriptWidth() * _screen->getScriptHeight())
continue;
- pixelRect.left = mask % _screen->getWidth(); pixelRect.right = pixelRect.left + 1;
- pixelRect.top = mask / _screen->getWidth(); pixelRect.bottom = pixelRect.top + 1;
+ pixelRect.left = mask % _screen->getScriptWidth(); pixelRect.right = pixelRect.left + 1;
+ pixelRect.top = mask / _screen->getScriptWidth(); pixelRect.bottom = pixelRect.top + 1;
pixelRect.clip(_picRect);
if (!pixelRect.isEmpty())
copyRectToScreen(pixelRect, blackoutFlag);
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index a88546e68c..da61ecf4c3 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -367,7 +367,7 @@ void GfxView::initData(GuiResourceId resourceId) {
default:
error("ViewType was not detected, can't continue");
}
-
+
// Inject our own views
// Currently only used for Dual mode (speech + text) for games, that do not have a "dual" icon already
// Which is Laura Bow 2 + King's Quest 6
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 6b6058c819..33392e3b42 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -76,8 +76,8 @@ MODULE_OBJS := \
sound/drivers/midi.o \
sound/drivers/pcjr.o \
video/seq_decoder.o
-
-
+
+
ifdef ENABLE_SCI32
MODULE_OBJS += \
engine/kgraphics32.o \
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index d155792853..10740a8b7b 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -2350,6 +2350,9 @@ bool ResourceManager::detectPaletteMergingSci11() {
// Old palette format used in palette resource? -> it's merging
if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0))
return true;
+ // Hardcoded: Laura Bow 2 floppy uses new palette resource, but still palette merging + 16 bit color matching
+ if ((g_sci->getGameId() == GID_LAURABOW2) && (!g_sci->isCD()) && (!g_sci->isDemo()))
+ return true;
return false;
}
return false;
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 66778f0914..c775f502c5 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -110,7 +110,7 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
unalloc();
return false;
}
-
+
_headerSize = file->readByte();
if (type == kResourceTypeAudio) {
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index fc723f18cf..60a1271b89 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -219,7 +219,7 @@ Common::Error SciEngine::run() {
// Add the after market GM patches for the specified game, if they exist
_resMan->addNewGMPatch(_gameId);
_gameObjectAddress = _resMan->findGameObject();
-
+
_scriptPatcher = new ScriptPatcher();
SegManager *segMan = new SegManager(_resMan, _scriptPatcher);
@@ -896,7 +896,7 @@ void SciEngine::syncSoundSettings() {
bool SciEngine::speechAndSubtitlesEnabled() {
bool subtitlesOn = ConfMan.getBool("subtitles");
bool speechOn = !ConfMan.getBool("speech_mute");
-
+
if (isCD() && subtitlesOn && speechOn)
return true;
return false;
@@ -936,7 +936,7 @@ void SciEngine::updateScummVMAudioOptions() {
// depending on the in-game settings
if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
uint16 ingameSetting = _gamestate->variables[VAR_GLOBAL][90].getOffset();
-
+
switch (ingameSetting) {
case 1:
// subtitles
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 2377386c72..4928fd1b4e 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -314,13 +314,16 @@ public:
* if NULL is passed no subtitle will be added to the returned string
* @return processed string
*/
- Common::String strSplit(const char *str, const char *sep = "\r----------\r");
+ Common::String strSplitLanguage(const char *str, uint16 *splitLanguage, const char *sep = "\r----------\r");
+ Common::String strSplit(const char *str, const char *sep = "\r----------\r") {
+ return strSplitLanguage(str, NULL, sep);
+ }
kLanguage getSciLanguage();
void setSciLanguage(kLanguage lang);
void setSciLanguage();
- Common::String getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2 = NULL) const;
+ Common::String getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2 = NULL, uint16 *languageSplitter = NULL) const;
// Check if vocabulary needs to get switched (in multilingual parser games)
void checkVocabularySwitch();
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 362cca699d..7a6eaf62b4 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -142,7 +142,7 @@ void SciMusic::init() {
_driverLastChannel = _pMidiDrv->getLastChannel();
if (getSciVersion() <= SCI_VERSION_0_LATE)
_globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0
-
+
_currentlyPlayingSample = NULL;
}
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index 6149bb799e..4e44074630 100644
--- a/engines/sci/sound/music.h
+++ b/engines/sci/sound/music.h
@@ -264,7 +264,7 @@ private:
int _driverFirstChannel;
int _driverLastChannel;
-
+
MusicEntry *_currentlyPlayingSample;
};
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 116a953b0b..0d7ea39ec2 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -33,6 +33,7 @@
#include "scumm/resource.h"
#include "scumm/saveload.h"
#include "scumm/scumm_v7.h"
+#include "scumm/scumm_v0.h"
#include "scumm/he/sound_he.h"
#include "scumm/he/sprite_he.h"
#include "scumm/usage_bits.h"
@@ -42,12 +43,66 @@ namespace Scumm {
byte Actor::kInvalidBox = 0;
-static const byte v0ActorTalkArray[0x19] = {
- 0x00, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x00, 0x46, 0x06,
- 0x06, 0x06, 0x06, 0xFF, 0xFF,
- 0x06, 0xC0, 0x06, 0x06, 0x00,
- 0xC0, 0xC0, 0x00, 0x06, 0x06
+static const byte v0ActorDemoTalk[25] = {
+ 0x00,
+ 0x06, // Syd
+ 0x06, // Razor
+ 0x06, // Dave
+ 0x06, // Michael
+ 0x06, // Bernard
+ 0x06, // Wendy
+ 0x00, // Jeff
+ 0x46, // Radiation Suit
+ 0x06, // Dr Fred
+ 0x06, // Nurse Edna
+ 0x06, // Weird Ed
+ 0x06, // Dead Cousin Ted
+ 0xE2, // Purple Tentacle
+ 0xE2, // Green Tentacle
+ 0x06, // Meteor police
+ 0xC0, // Meteor
+ 0x06, // Mark Eteer
+ 0x06, // Talkshow Host
+ 0x00, // Plant
+ 0xC0, // Meteor Radiation
+ 0xC0, // Edsel (small, outro)
+ 0x00, // Meteor (small, intro)
+ 0x06, // Sandy (Lab)
+ 0x06, // Sandy (Cut-Scene)
+};
+
+static const byte v0ActorTalk[25] = {
+ 0x00,
+ 0x06, // Syd
+ 0x06, // Razor
+ 0x06, // Dave
+ 0x06, // Michael
+ 0x06, // Bernard
+ 0x06, // Wendy
+ 0x00, // Jeff
+ 0x46, // Radiation Suit
+ 0x06, // Dr Fred
+ 0x06, // Nurse Edna
+ 0x06, // Weird Ed
+ 0x06, // Dead Cousin Ted
+ 0xFF, // Purple Tentacle
+ 0xFF, // Green Tentacle
+ 0x06, // Meteor police
+ 0xC0, // Meteor
+ 0x06, // Mark Eteer
+ 0x06, // Talkshow Host
+ 0x00, // Plant
+ 0xC0, // Meteor Radiation
+ 0xC0, // Edsel (small, outro)
+ 0x00, // Meteor (small, intro)
+ 0x06, // Sandy (Lab)
+ 0x06, // Sandy (Cut-Scene)
+};
+
+static const byte v0WalkboxSlantedModifier[0x16] = {
+ 0x00,0x01,0x02,0x03,0x03,0x04,0x05,0x06,
+ 0x06,0x07,0x08,0x09,0x09,0x0A,0x0B,
+ 0x0C,0x0C,0x0D,0x0E,0x0F,0x10,0x10
};
Actor::Actor(ScummEngine *scumm, int id) :
@@ -182,6 +237,20 @@ void Actor_v0::initActor(int mode) {
_costCommand = 0xFF;
_miscflags = 0;
_speaking = 0;
+
+ _walkCountModulo = 0;
+ _newWalkBoxEntered = false;
+ _walkDirX = 0;
+ _walkDirY = 0;
+ _walkYCountGreaterThanXCount = 0;
+ _walkXCount = 0;
+ _walkXCountInc = 0;
+ _walkYCount = 0;
+ _walkYCountInc = 0;
+ _walkMaxXYCountInc = 0;
+
+ _tmp_WalkBox = 0;
+ _tmp_NewWalkBoxEntered = 0;
_animFrameRepeat = 0;
for (int i = 0; i < 8; ++i) {
@@ -189,6 +258,12 @@ void Actor_v0::initActor(int mode) {
_limbFrameRepeat[i] = 0;
_limb_flipped[i] = false;
}
+
+ if (_vm->_game.features & GF_DEMO) {
+ _sound[0] = v0ActorDemoTalk[_number];
+ } else {
+ _sound[0] = v0ActorTalk[_number];
+ }
}
void Actor::setBox(int box) {
@@ -249,9 +324,12 @@ void Actor::stopActorMoving() {
if (_walkScript)
_vm->stopScript(_walkScript);
- _moving = 0;
- if (_vm->_game.version == 0)
+ if (_vm->_game.version == 0) {
+ _moving = 2;
setDirection(_facing);
+ } else {
+ _moving = 0;
+ }
}
void Actor::setActorWalkSpeed(uint newSpeedX, uint newSpeedY) {
@@ -339,9 +417,6 @@ int Actor::actorWalkStep() {
int distX, distY;
int nextFacing;
- if (_vm->_game.version == 0)
- ((Actor_v0 *)this)->_animFrameRepeat = -1;
-
_needRedraw = true;
nextFacing = updateActorDirection(true);
@@ -350,10 +425,6 @@ int Actor::actorWalkStep() {
startWalkAnim(1, nextFacing);
}
_moving |= MF_IN_LEG;
-
- // V0: Don't move during the turn
- if (_vm->_game.version == 0)
- return 0;
}
if (_walkbox != _walkdata.curbox && _vm->checkXYInBoxBounds(_walkdata.curbox, _pos.x, _pos.y)) {
@@ -368,13 +439,28 @@ int Actor::actorWalkStep() {
return 0;
}
- tmpX = (_pos.x << 16) + _walkdata.xfrac + (_walkdata.deltaXFactor >> 8) * _scalex;
- _walkdata.xfrac = (uint16)tmpX;
- _pos.x = (tmpX >> 16);
+ if (_vm->_game.version <= 2) {
+ if (_walkdata.deltaXFactor != 0) {
+ if (_walkdata.deltaXFactor > 0)
+ _pos.x += 1;
+ else
+ _pos.x -= 1;
+ }
+ if (_walkdata.deltaYFactor != 0) {
+ if (_walkdata.deltaYFactor > 0)
+ _pos.y += 1;
+ else
+ _pos.y -= 1;
+ }
+ } else {
+ tmpX = (_pos.x << 16) + _walkdata.xfrac + (_walkdata.deltaXFactor >> 8) * _scalex;
+ _walkdata.xfrac = (uint16)tmpX;
+ _pos.x = (tmpX >> 16);
- tmpY = (_pos.y << 16) + _walkdata.yfrac + (_walkdata.deltaYFactor >> 8) * _scaley;
- _walkdata.yfrac = (uint16)tmpY;
- _pos.y = (tmpY >> 16);
+ tmpY = (_pos.y << 16) + _walkdata.yfrac + (_walkdata.deltaYFactor >> 8) * _scaley;
+ _walkdata.yfrac = (uint16)tmpY;
+ _pos.y = (tmpY >> 16);
+ }
if (ABS(_pos.x - _walkdata.cur.x) > distX) {
_pos.x = _walkdata.next.x;
@@ -384,17 +470,118 @@ int Actor::actorWalkStep() {
_pos.y = _walkdata.next.y;
}
- if (_vm->_game.version >= 4 && _vm->_game.version <= 6 && _pos == _walkdata.next) {
+ if ((_vm->_game.version <= 2 || (_vm->_game.version >= 4 && _vm->_game.version <= 6)) && _pos == _walkdata.next) {
_moving &= ~MF_IN_LEG;
return 0;
}
- if (_vm->_game.version == 0)
- ((Actor_v0 *)this)->animateActor(newDirToOldDir(_facing));
-
return 1;
}
+bool Actor_v0::calcWalkDistances() {
+ _walkDirX = 0;
+ _walkDirY = 0;
+ _walkYCountGreaterThanXCount = 0;
+ uint16 A = 0;
+
+ if (_CurrentWalkTo.x >= _tmp_Dest.x) {
+ A = _CurrentWalkTo.x - _tmp_Dest.x;
+ _walkDirX = 1;
+ } else {
+ A = _tmp_Dest.x - _CurrentWalkTo.x;
+ }
+
+ _walkXCountInc = A;
+
+ if (_CurrentWalkTo.y >= _tmp_Dest.y) {
+ A = _CurrentWalkTo.y - _tmp_Dest.y;
+ _walkDirY = 1;
+ } else {
+ A = _tmp_Dest.y - _CurrentWalkTo.y;
+ }
+
+ _walkYCountInc = A;
+ if (!_walkXCountInc && !_walkYCountInc)
+ return true;
+
+ if (_walkXCountInc <= _walkYCountInc)
+ _walkYCountGreaterThanXCount = 1;
+
+ // 2FCC
+ A = _walkXCountInc;
+ if (A <= _walkYCountInc)
+ A = _walkYCountInc;
+
+ _walkMaxXYCountInc = A;
+ _walkXCount = _walkXCountInc;
+ _walkYCount = _walkYCountInc;
+ _walkCountModulo = _walkMaxXYCountInc;
+
+ return false;
+}
+
+byte Actor_v0::actorWalkX() {
+ byte A = _walkXCount;
+ A += _walkXCountInc;
+ if (A >= _walkCountModulo) {
+ if (!_walkDirX) {
+ _tmp_Dest.x--;
+ } else {
+ _tmp_Dest.x++;
+ }
+
+ A -= _walkCountModulo;
+ }
+ // 2EAC
+ _walkXCount = A;
+ setTmpFromActor();
+ if (updateWalkbox() == kInvalidBox) {
+ // 2EB9
+ setActorFromTmp();
+
+ return 3;
+ }
+ // 2EBF
+ if (_tmp_Dest.x == _CurrentWalkTo.x)
+ return 1;
+
+ return 0;
+}
+
+byte Actor_v0::actorWalkY() {
+ byte A = _walkYCount;
+ A += _walkYCountInc;
+ if (A >= _walkCountModulo) {
+ if (!_walkDirY) {
+ _tmp_Dest.y--;
+ } else {
+ _tmp_Dest.y++;
+ }
+
+ A -= _walkCountModulo;
+ }
+ // 2EEB
+ _walkYCount = A;
+ setTmpFromActor();
+ if (updateWalkbox() == kInvalidBox) {
+ // 2EF8
+ setActorFromTmp();
+ return 4;
+ }
+ // 2EFE
+ if (_walkYCountInc != 0) {
+ if (_walkYCountInc == 0xFF) {
+ setActorFromTmp();
+ return 4;
+ }
+ }
+ // 2F0D
+ if (_CurrentWalkTo.y == _tmp_Dest.y)
+ return 1;
+
+ return 0;
+}
+
void Actor::startWalkActor(int destX, int destY, int dir) {
AdjustBoxResult abr;
@@ -447,9 +634,16 @@ void Actor::startWalkActor(int destX, int destY, int dir) {
_walkdata.dest.y = abr.y;
_walkdata.destbox = abr.box;
_walkdata.destdir = dir;
- _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG;
- _walkdata.point3.x = 32000;
+
+ if (_vm->_game.version == 0) {
+ ((Actor_v0*)this)->_newWalkBoxEntered = true;
+ } else if (_vm->_game.version <= 2) {
+ _moving = (_moving & ~(MF_LAST_LEG | MF_IN_LEG)) | MF_NEW_LEG;
+ } else {
+ _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG;
+ }
+ _walkdata.point3.x = 32000;
_walkdata.curbox = _walkbox;
}
@@ -567,88 +761,206 @@ void Actor::walkActor() {
calcMovementFactor(_walkdata.dest);
}
-bool Actor_v2::checkWalkboxesHaveDirectPath(Common::Point &foundPath) {
- // only MM v0 supports walking in direct line between walkboxes.
- // MM v1 already does not support it anymore.
- return false;
-}
+void Actor_v0::walkActor() {
+ actorSetWalkTo();
-bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
- const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result)
-{
- const Common::Point v1 = line1End - line1Start; // line1(n1) = line1Start + n1 * v1
- const Common::Point v2 = line2End - line2Start; // line2(n2) = line2Start + n2 * v2
+ _needRedraw = true;
+ if (_NewWalkTo != _CurrentWalkTo) {
+ _CurrentWalkTo = _NewWalkTo;
- double det = v2.x * v1.y - v1.x * v2.y;
- if (det == 0)
- return false;
+L2A33:;
+ _moving &= 0xF0;
+ _tmp_Dest = _pos;
- double n1 = ((double)v2.x * (line2Start.y - line1Start.y) -
- (double)v2.y * (line2Start.x - line1Start.x)) / det;
- double n2 = ((double)v1.x * (line2Start.y - line1Start.y) -
- (double)v1.y * (line2Start.x - line1Start.x)) / det;
+ byte tmp = calcWalkDistances();
+ _moving &= 0xF0;
+ _moving |= tmp;
- // both coefficients have to be in [0, 1], otherwise the intersection is
- // not inside of at least one of the two line segments
- if (n1 < 0.0 || n1 > 1.0 || n2 < 0.0 || n2 > 1.0)
- return false;
+ if (!_walkYCountGreaterThanXCount) {
+ if (_walkDirX) {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*1, V12_Y_MULTIPLIER*0, false);
+ } else {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*-1, V12_Y_MULTIPLIER*0, false);
+ }
+ } else {
+ if (_walkDirY) {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*1, false);
+ } else {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*-1, false);
+ }
+ }
- result.x = line1Start.x + (int)(n1 * v1.x);
- result.y = line1Start.y + (int)(n1 * v1.y);
- return true;
-}
+ directionUpdate();
+
+ if (_moving & 0x80)
+ return;
-/*
- * MM v0 allows the actor to walk in a direct line between boxes to the target
- * if actor and target share a horizontal or vertical corridor.
- * If such a corridor is found the actor is not forced to go horizontally or
- * vertically from one box to the next but can also walk diagonally.
- *
- * Note: the original v0 interpreter sets the target destination for diagonal
- * walking only once and then rechecks whenever the actor reaches a new box if the
- * walk destination is still suitable for the current box.
- * ScummVM does not perform such a check, so it is possible to leave the walkboxes
- * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water)
- * or the medical room (actor walks over examination table).
- * To solve this we intersect the new walk destination with the actor's walkbox borders,
- * so a recheck is done when the actor leaves his box. This is done by the
- * intersectLineSegments() routine calls.
- */
-bool Actor_v0::checkWalkboxesHaveDirectPath(Common::Point &foundPath) {
- BoxCoords boxCoords = _vm->getBoxCoordinates(_walkbox);
- BoxCoords curBoxCoords = _vm->getBoxCoordinates(_walkdata.curbox);
-
- // check if next walkbox is left or right to actor's box
- if (boxCoords.ll.x > curBoxCoords.lr.x || boxCoords.lr.x < curBoxCoords.ll.x) {
- // determine horizontal corridor gates
- int gateUpper = MAX(boxCoords.ul.y, curBoxCoords.ul.y);
- int gateLower = MIN(boxCoords.ll.y, curBoxCoords.ll.y);
-
- // check if actor and target are in the same horizontal corridor between the boxes
- if ((_pos.y >= gateUpper && _pos.y <= gateLower) &&
- (_walkdata.dest.y >= gateUpper && _walkdata.dest.y <= gateLower)) {
- if (boxCoords.ll.x > curBoxCoords.lr.x) // next box is left
- return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ll, boxCoords.ul, foundPath);
- else // next box is right
- return intersectLineSegments(_pos, _walkdata.dest, boxCoords.lr, boxCoords.ur, foundPath);
- }
- // check if next walkbox is above or below actor's box
- } else if (boxCoords.ul.y > curBoxCoords.ll.y || boxCoords.ll.y < curBoxCoords.ul.y) {
- // determine vertical corridor gates
- int gateLeft = MAX(boxCoords.ll.x, curBoxCoords.ll.x);
- int gateRight = MIN(boxCoords.lr.x, curBoxCoords.lr.x);
-
- // check if actor and target are in the same vertical corridor between the boxes
- if ((_pos.x >= gateLeft && _pos.x <= gateRight) &&
- (_walkdata.dest.x >= gateLeft && _walkdata.dest.x <= gateRight)) {
- if (boxCoords.ul.y > curBoxCoords.ll.y) // next box is above
- return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ul, boxCoords.ur, foundPath);
- else // next box is below
- return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ll, boxCoords.lr, foundPath);
+ animateActor(newDirToOldDir(_facing));
+
+ } else {
+ // 2A0A
+ if ((_moving & 0x7F) != 1) {
+
+ if (_NewWalkTo == _pos)
+ return;
}
}
- return false;
+ // 2A9A
+ if (_moving == 2)
+ return;
+
+ if ((_moving & 0x0F) == 1)
+ return stopActorMoving();
+
+ // 2AAD
+ if (_moving & 0x80) {
+ directionUpdate();
+
+ if (_moving & 0x80)
+ return;
+
+ animateActor(newDirToOldDir(_facing));
+ }
+
+ if ((_moving & 0x0F) == 3) {
+L2C36:;
+ setTmpFromActor();
+
+ if (!_walkDirX) {
+ _pos.x--;
+ } else {
+ _pos.x++;
+ }
+
+ // 2C51
+ if (updateWalkbox() != kInvalidBox) {
+
+ setActorFromTmp();
+ goto L2A33;
+ }
+
+ setActorFromTmp();
+
+ if (_CurrentWalkTo.y == _tmp_Dest.y) {
+ stopActorMoving();
+ return;
+ }
+
+ if (!_walkDirY) {
+ _tmp_Dest.y--;
+ } else {
+ _tmp_Dest.y++;
+ }
+
+ setTmpFromActor();
+
+ byte A = updateWalkbox();
+ if (A == 0xFF) {
+ setActorFromTmp();
+ stopActorMoving();
+ return;
+ }
+ // 2C98: Yes, an exact copy of what just occured.. the original does this, so im doing it...
+ // Just to keep me sane when going over it :)
+ if (A == 0xFF) {
+ setActorFromTmp();
+ stopActorMoving();
+ return;
+ }
+ return;
+ }
+
+ // 2ADA
+ if ((_moving & 0x0F) == 4) {
+L2CA3:;
+ setTmpFromActor();
+
+ if (!_walkDirY) {
+ _pos.y--;
+ } else {
+ _pos.y++;
+ }
+ if (updateWalkbox() == kInvalidBox) {
+ // 2CC7
+ setActorFromTmp();
+ if (_CurrentWalkTo.x == _tmp_Dest.x) {
+ stopActorMoving();
+ return;
+ }
+
+ if (!_walkDirX) {
+ _tmp_Dest.x--;
+ } else {
+ _tmp_Dest.x++;
+ }
+ setTmpFromActor();
+
+ if (updateWalkbox() == kInvalidBox) {
+ setActorFromTmp();
+ stopActorMoving();
+ }
+
+ return;
+ } else {
+ setActorFromTmp();
+ goto L2A33;
+ }
+ }
+
+ if ((_moving & 0x0F) == 0) {
+ // 2AE8
+ byte A = actorWalkX();
+
+ if (A == 1) {
+ A = actorWalkY();
+ if (A == 1) {
+ _moving &= 0xF0;
+ _moving |= A;
+ } else {
+ if (A == 4)
+ stopActorMoving();
+ }
+
+ return;
+
+ } else {
+ // 2B0C
+ if (A == 3) {
+ _moving &= 0xF0;
+ _moving |= A;
+
+ if (_walkDirY) {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*1, false);
+ } else {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*-1, false);
+ }
+
+ directionUpdate();
+ animateActor(newDirToOldDir(_facing));
+ goto L2C36;
+
+ } else {
+ // 2B39
+ A = actorWalkY();
+ if (A != 4)
+ return;
+
+ _moving &= 0xF0;
+ _moving |= A;
+
+ if (_walkDirX) {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*1, V12_Y_MULTIPLIER*0, false);
+ } else {
+ _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*-1, V12_Y_MULTIPLIER*0, false);
+ }
+
+ directionUpdate();
+ animateActor(newDirToOldDir(_facing));
+ goto L2CA3;
+ }
+ }
+ }
}
void Actor_v2::walkActor() {
@@ -697,10 +1009,8 @@ void Actor_v2::walkActor() {
_walkdata.curbox = next_box;
- if (!checkWalkboxesHaveDirectPath(foundPath)) {
- getClosestPtOnBox(_vm->getBoxCoordinates(_walkdata.curbox), _pos.x, _pos.y, tmp.x, tmp.y);
- getClosestPtOnBox(_vm->getBoxCoordinates(_walkbox), tmp.x, tmp.y, foundPath.x, foundPath.y);
- }
+ getClosestPtOnBox(_vm->getBoxCoordinates(_walkdata.curbox), _pos.x, _pos.y, tmp.x, tmp.y);
+ getClosestPtOnBox(_vm->getBoxCoordinates(_walkbox), tmp.x, tmp.y, foundPath.x, foundPath.y);
}
calcMovementFactor(foundPath);
}
@@ -972,7 +1282,7 @@ void Actor::setDirection(int direction) {
}
void Actor_v0::setDirection(int direction) {
- int dir = newDirToOldDir( direction );
+ int dir = newDirToOldDir(direction);
int res = 0;
switch (dir) {
@@ -985,18 +1295,16 @@ void Actor_v0::setDirection(int direction) {
break;
case 2:
- res = 6; // Face Away
+ res = 6; // Face Camera
break;
default:
- res = 7; // Face Camera
+ res = 7; // Face Away
break;
}
_animFrameRepeat = -1;
animateActor(res);
- if (_moving)
- animateCostume();
}
void Actor::faceToObject(int obj) {
@@ -1017,8 +1325,14 @@ void Actor::turnToDirection(int newdir) {
return;
if (_vm->_game.version <= 6) {
- _moving = MF_TURN;
_targetFacing = newdir;
+
+ if (_vm->_game.version == 0) {
+ setDirection(newdir);
+ return;
+ }
+ _moving = MF_TURN;
+
} else {
_moving &= ~MF_TURN;
if (newdir != _facing) {
@@ -1085,8 +1399,14 @@ void Actor::putActor(int dstX, int dstY, int newRoom) {
}
// V0 always sets the actor to face the camera upon entering a room
- if (_vm->_game.version == 0)
+ if (_vm->_game.version == 0) {
+ _walkdata.dest = _pos;
+
+ ((Actor_v0*)this)->_newWalkBoxEntered = true;
+ ((Actor_v0*)this)->_CurrentWalkTo = _pos;
+
setDirection(oldDirToNewDir(2));
+ }
}
static bool inBoxQuickReject(const BoxCoords &box, int x, int y, int threshold) {
@@ -1200,6 +1520,59 @@ static int checkXYInBoxBounds(int boxnum, int x, int y, int &destX, int &destY)
return dist;
}
+AdjustBoxResult Actor_v0::adjustPosInBorderWalkbox(AdjustBoxResult box) {
+ AdjustBoxResult Result = box;
+ BoxCoords BoxCoord = _vm->getBoxCoordinates(box.box);
+
+ byte boxMask = _vm->getMaskFromBox(box.box);
+ if (!(boxMask & 0x80))
+ return Result;
+
+ int16 A;
+ boxMask &= 0x7C;
+ if (boxMask == 0x0C)
+ A = 2;
+ else {
+ if (boxMask != 0x08)
+ return Result;
+
+ A = 1;
+ }
+
+ // 1BC6
+ byte Modifier = box.y - BoxCoord.ul.y;
+ assert(Modifier < 0x16);
+
+ if (A == 1) {
+ // 1BCF
+ A = BoxCoord.ur.x - v0WalkboxSlantedModifier[ Modifier ];
+ if (A < box.x)
+ return box;
+
+ if (A < 0xA0 || A == 0xA0)
+ A = 0;
+
+ Result.x = A;
+ } else {
+ // 1BED
+ A = BoxCoord.ul.x + v0WalkboxSlantedModifier[ Modifier ];
+
+ if (A < box.x || A == box.x)
+ Result.x = A;
+ }
+
+ return Result;
+}
+
+AdjustBoxResult Actor_v0::adjustXYToBeInBox(int dstX, int dstY) {
+ AdjustBoxResult Result = Actor_v2::adjustXYToBeInBox(dstX, dstY);
+
+ if (Result.box == kInvalidBox)
+ return Result;
+
+ return adjustPosInBorderWalkbox(Result);
+}
+
AdjustBoxResult Actor_v2::adjustXYToBeInBox(const int dstX, const int dstY) {
AdjustBoxResult abr;
@@ -1410,6 +1783,7 @@ void Actor::showActor() {
Actor_v0 *a = ((Actor_v0 *)this);
a->_costCommand = a->_costCommandNew = 0xFF;
+ _walkdata.dest = a->_CurrentWalkTo;
for (int i = 0; i < 8; ++i) {
a->_limbFrameRepeat[i] = 0;
@@ -1451,34 +1825,6 @@ void ScummEngine::showActors() {
}
}
-// bits 0..5: sound, bit 6: ???
-static const byte v0ActorSounds[24] = {
- 0x06, // Syd
- 0x06, // Razor
- 0x06, // Dave
- 0x06, // Michael
- 0x06, // Bernard
- 0x06, // Wendy
- 0x00, // Jeff
- 0x46, // Radiation Suit
- 0x06, // Dr Fred
- 0x06, // Nurse Edna
- 0x06, // Weird Ed
- 0x06, // Dead Cousin Ted
- 0xFF, // Purple Tentacle
- 0xFF, // Green Tentacle
- 0x06, // Meteor police
- 0xC0, // Meteor
- 0x06, // Mark Eteer
- 0x06, // Talkshow Host
- 0x00, // Plant
- 0xC0, // Meteor Radiation
- 0xC0, // Edsel (small, outro)
- 0x00, // Meteor (small, intro)
- 0x06, // Sandy (Lab)
- 0x06, // Sandy (Cut-Scene)
-};
-
/* Used in Scumm v5 only. Play sounds associated with actors */
void ScummEngine::playActorSounds() {
int i, j;
@@ -1488,7 +1834,7 @@ void ScummEngine::playActorSounds() {
if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom()) {
_currentScript = 0xFF;
if (_game.version == 0) {
- sound = v0ActorSounds[i - 1] & 0x3F;
+ sound = _actors[i]->_sound[0] & 0x3F;
} else {
sound = _actors[i]->_sound[0];
}
@@ -1642,13 +1988,13 @@ void ScummEngine::processActors() {
continue;
// Sound
- if (a0->_moving && _currentRoom != 1 && _currentRoom != 44) {
+ if (a0->_moving != 2 && _currentRoom != 1 && _currentRoom != 44) {
if (a0->_cost.soundPos == 0)
a0->_cost.soundCounter++;
// Is this the correct location?
// 0x073C
- if (v0ActorTalkArray[a0->_number] & 0x3F)
+ if (a0->_sound[0] & 0x3F)
a0->_cost.soundPos = (a0->_cost.soundPos + 1) % 3;
}
}
@@ -1659,8 +2005,17 @@ void ScummEngine::processActors() {
// would hence cause regressions. See also the other big
// comment further up in this method for some details.
if (a->_costume) {
- a->drawActorCostume();
- a->animateCostume();
+
+ // Unfortunately in V0, the 'animateCostume' call happens right after the call to 'walkActor' (which is before drawing the actor)...
+ // doing it the other way with V0, causes animation glitches (when beginnning to walk, as the costume hasnt been updated).
+ // Updating the costume directly after 'walkActor' and again, after drawing... causes frame skipping
+ if (_game.version == 0) {
+ a->animateCostume();
+ a->drawActorCostume();
+ } else {
+ a->drawActorCostume();
+ a->animateCostume();
+ }
}
}
}
@@ -1948,7 +2303,7 @@ void Actor::startAnimActor(int f) {
void Actor_v0::startAnimActor(int f) {
if (f == _talkStartFrame) {
- if (v0ActorTalkArray[_number] & 0x40)
+ if (_sound[0] & 0x40)
return;
_speaking = 1;
@@ -2054,7 +2409,7 @@ void Actor_v0::animateCostume() {
}
void Actor_v0::speakCheck() {
- if (v0ActorTalkArray[_number] & 0x80)
+ if (_sound[0] & 0x80)
return;
int cmd = newDirToOldDir(_facing);
@@ -2897,6 +3252,70 @@ void Actor_v0::animateActor(int anim) {
}
}
+byte Actor_v0::updateWalkbox() {
+ if (_vm->checkXYInBoxBounds(_walkbox, _pos.x, _pos.y))
+ return 0;
+
+ int numBoxes = _vm->getNumBoxes() - 1;
+ for (int i = 0; i <= numBoxes; i++) {
+ if (_vm->checkXYInBoxBounds(i, _pos.x, _pos.y) == true) {
+ if (_walkdata.curbox == i) {
+ setBox(i);
+ directionUpdate();
+
+ _newWalkBoxEntered = true;
+ return i;
+ }
+ }
+ }
+
+ return kInvalidBox;
+}
+
+void Actor_v0::directionUpdate() {
+
+ int nextFacing = updateActorDirection(true);
+ if (_facing != nextFacing) {
+ // 2A89
+ setDirection(nextFacing);
+
+ // Still need to turn?
+ if (_facing != _targetFacing) {
+ _moving |= 0x80;
+ return;
+ }
+ }
+
+ _moving &= ~0x80;
+}
+
+void Actor_v0::setTmpFromActor() {
+ _tmp_Pos = _pos;
+ _pos = _tmp_Dest;
+ _tmp_WalkBox = _walkbox;
+ _tmp_NewWalkBoxEntered = _newWalkBoxEntered;
+}
+
+void Actor_v0::setActorFromTmp() {
+ _pos = _tmp_Pos;
+ _tmp_Dest = _tmp_Pos;
+ _walkbox = _tmp_WalkBox;
+ _newWalkBoxEntered = _tmp_NewWalkBoxEntered;
+}
+
+void Actor_v0::actorSetWalkTo() {
+
+ if (_newWalkBoxEntered == false)
+ return;
+
+ _newWalkBoxEntered = false;
+
+ int nextBox = ((ScummEngine_v0*)_vm)->walkboxFindTarget(this, _walkdata.destbox, _walkdata.dest);
+ if (nextBox != kInvalidBox) {
+ _walkdata.curbox = nextBox;
+ }
+}
+
void Actor_v0::saveLoadWithSerializer(Serializer *ser) {
Actor::saveLoadWithSerializer(ser);
@@ -2910,6 +3329,20 @@ void Actor_v0::saveLoadWithSerializer(Serializer *ser) {
MKLINE(Actor_v0, _animFrameRepeat, sleByte, VER(89)),
MKARRAY(Actor_v0, _limbFrameRepeatNew[0], sleInt8, 8, VER(89)),
MKARRAY(Actor_v0, _limbFrameRepeat[0], sleInt8, 8, VER(90)),
+ MKLINE(Actor_v0, _CurrentWalkTo.x, sleInt16, VER(97)),
+ MKLINE(Actor_v0, _CurrentWalkTo.y, sleInt16, VER(97)),
+ MKLINE(Actor_v0, _NewWalkTo.x, sleInt16, VER(97)),
+ MKLINE(Actor_v0, _NewWalkTo.y, sleInt16, VER(97)),
+ MKLINE(Actor_v0, _walkCountModulo, sleInt8, VER(97)),
+ MKLINE(Actor_v0, _newWalkBoxEntered, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkDirX, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkDirY, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkYCountGreaterThanXCount, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkXCount, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkXCountInc, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkYCount, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkYCountInc, sleByte, VER(97)),
+ MKLINE(Actor_v0, _walkMaxXYCountInc, sleByte, VER(97)),
MKEND()
};
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index 46dc7d0295..c1a3f23318 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -333,7 +333,6 @@ public:
protected:
virtual bool isPlayer();
virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr);
- virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath);
};
enum ActorV0MiscFlags {
@@ -349,11 +348,32 @@ enum ActorV0MiscFlags {
class Actor_v0 : public Actor_v2 {
public:
+ Common::Point _CurrentWalkTo, _NewWalkTo;
+
byte _costCommandNew;
byte _costCommand;
byte _miscflags;
byte _speaking;
+ byte _walkCountModulo;
+ bool _newWalkBoxEntered;
+
+ byte _walkDirX;
+ byte _walkDirY;
+
+ byte _walkYCountGreaterThanXCount;
+ byte _walkXCount;
+ byte _walkXCountInc;
+ byte _walkYCount;
+ byte _walkYCountInc;
+
+ byte _walkMaxXYCountInc;
+
+ Common::Point _tmp_Pos;
+ Common::Point _tmp_Dest;
+ byte _tmp_WalkBox;
+ bool _tmp_NewWalkBoxEntered;
+
int8 _animFrameRepeat;
int8 _limbFrameRepeatNew[8];
int8 _limbFrameRepeat[8];
@@ -363,23 +383,32 @@ public:
public:
Actor_v0(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {}
- virtual void initActor(int mode);
- virtual void animateActor(int anim);
- virtual void animateCostume();
+ void initActor(int mode);
+ void animateActor(int anim);
+ void animateCostume();
void limbFrameCheck(int limb);
+ void directionUpdate();
void speakCheck();
- virtual void setDirection(int direction);
+ void setDirection(int direction);
void startAnimActor(int f);
+ bool calcWalkDistances();
+ void walkActor();
+ void actorSetWalkTo();
+ byte actorWalkX();
+ byte actorWalkY();
+ byte updateWalkbox();
+
+ AdjustBoxResult adjustXYToBeInBox(int dstX, int dstY);
+ AdjustBoxResult adjustPosInBorderWalkbox(AdjustBoxResult box);
+
+ void setTmpFromActor();
+ void setActorFromTmp();
+
// Used by the save/load system:
virtual void saveLoadWithSerializer(Serializer *ser);
-
-protected:
- bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
- const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result);
- virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath);
};
diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp
index 70c8f2e032..087d8425ac 100644
--- a/engines/scumm/boxes.cpp
+++ b/engines/scumm/boxes.cpp
@@ -1158,6 +1158,30 @@ bool ScummEngine::areBoxesNeighbors(int box1nr, int box2nr) {
return false;
}
+byte ScummEngine_v0::walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest) {
+ Actor_v0 *Actor = (Actor_v0*)a;
+
+ byte nextBox = getNextBox(a->_walkbox, destbox);
+
+ if (nextBox != 0xFF && nextBox == destbox && areBoxesNeighbors(a->_walkbox, nextBox)) {
+
+ Actor->_NewWalkTo = walkdest;
+ return nextBox;
+ }
+
+ if (nextBox != 0xFF && nextBox != a->_walkbox) {
+
+ getClosestPtOnBox(getBoxCoordinates(nextBox), a->getPos().x, a->getPos().y, Actor->_NewWalkTo.x, Actor->_NewWalkTo.y);
+
+ } else {
+ if (walkdest.x == -1)
+ Actor->_NewWalkTo = Actor->_CurrentWalkTo;
+ else
+ Actor->_NewWalkTo = walkdest;
+ }
+ return nextBox;
+}
+
bool ScummEngine_v0::areBoxesNeighbors(int box1nr, int box2nr) {
int i;
const int numOfBoxes = getNumBoxes();
diff --git a/engines/scumm/cdda.cpp b/engines/scumm/cdda.cpp
index adb414ecce..d797712a31 100644
--- a/engines/scumm/cdda.cpp
+++ b/engines/scumm/cdda.cpp
@@ -46,7 +46,7 @@ private:
public:
CDDAStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse);
virtual ~CDDAStream();
-
+
int readBuffer(int16 *buffer, const int numSamples);
bool isStereo() const { return true; }
int getRate() const { return 44100; }
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index a7922b232e..45647c9bed 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -244,7 +244,7 @@ static Common::String generateFilenameForDetection(const char *pattern, Filename
case kGenRoomNum:
result = Common::String::format(pattern, 0);
break;
-
+
case kGenDiskNumSteam:
case kGenRoomNumSteam: {
const SteamIndexFile *indexFile = lookUpSteamIndexFile(pattern, platform);
@@ -323,6 +323,8 @@ static BaseScummFile *openDiskImage(const Common::FSNode &node, const GameFilena
gs.gameid = gfp->gameid;
gs.id = (Common::String(gfp->gameid) == "maniac" ? GID_MANIAC : GID_ZAK);
gs.platform = gfp->platform;
+ if (strcmp(gfp->pattern, "maniacdemo.d64") == 0)
+ gs.features |= GF_DEMO;
// determine second disk file name
Common::String disk2(disk1);
@@ -502,6 +504,7 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF
// (since they have identical MD5):
if (dr.game.id == GID_MANIAC && !strcmp(gfp->pattern, "%02d.MAN")) {
dr.extra = "V1 Demo";
+ dr.game.features = GF_DEMO;
}
// HACK: Try to detect languages for translated games
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 791963e237..82a8b4452b 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -207,6 +207,7 @@ static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = {
static const GameSettings gameVariantsTable[] = {
{"maniac", "Apple II", 0, GID_MANIAC, 0, 0, MDT_APPLEIIGS, 0, Common::kPlatformApple2GS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"maniac", "C64", 0, GID_MANIAC, 0, 0, MDT_C64, 0, Common::kPlatformC64, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI) },
+ {"maniac", "C64 Demo", 0, GID_MANIAC, 0, 0, MDT_C64, GF_DEMO, Common::kPlatformC64, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI) },
{"maniac", "V1", "v1", GID_MANIAC, 1, 0, MDT_PCSPK | MDT_PCJR, 0, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"maniac", "V1 Demo", "v1", GID_MANIAC, 1, 0, MDT_PCSPK | MDT_PCJR, GF_DEMO, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"maniac", "NES", 0, GID_MANIAC, 1, 0, MDT_NONE, 0, Common::kPlatformNES, GUIO3(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOASPECT)},
@@ -448,6 +449,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "maniac", "%02d.MAN", kGenRoomNum, UNK_LANG, UNK, "V1 Demo" },
{ "maniac", "maniac1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "C64" }, // ... and maniac2.d64
{ "maniac", "maniac1.dsk", kGenUnchanged, UNK_LANG, Common::kPlatformApple2GS, "Apple II" }, // ... and maniac2.dsk
+ { "maniac", "maniacdemo.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "C64 Demo" },
{ "maniac", "Maniac Mansion (E).prg", kGenUnchanged, Common::EN_GRB, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (F).prg", kGenUnchanged, Common::FR_FRA, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (SW).prg", kGenUnchanged, Common::SE_SWE, Common::kPlatformNES, "NES" },
@@ -664,6 +666,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "dog", "Springparadijs", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "farm", "farm", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "farm", "farm", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "farm", "farmdemo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "farm", "Farm Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
@@ -680,12 +683,13 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "freddi", "Freddi Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi", "Freddi Fish", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi", "FreddiD", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "freddi", "FreddiE", kGenHEPC, UNK_LANG, UNK, 0 },
{ "freddi", "Freddi Fisk", kGenHEMac, Common::SE_SWE, Common::kPlatformMacintosh, 0 },
{ "freddi", "FRITZI", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "freddi", "Marine Malice", kGenHEMac, Common::FR_FRA, Common::kPlatformMacintosh, 0 },
{ "freddi", "MM-DEMO", kGenHEPC, UNK_LANG, UNK, 0 },
- { "freddi2", "freddi2", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "freddi2", "freddi2", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "freddi2", "FF2-demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi2", "ff2-demo", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "freddi2", "FFHSDemo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
@@ -747,7 +751,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "lost", "lost", kGenHEPC, UNK_LANG, UNK, 0 },
{ "lost", "Lost and Found", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "lost", "smaller", kGenHEPC, UNK_LANG, UNK, 0 },
- { "lost", "verloren", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "lost", "verloren", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 },
{ "lost", "Verloren", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "maze", "maze", kGenHEPC, UNK_LANG, UNK, 0 },
@@ -792,7 +796,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "pajama2", "PJ2 Demo", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "pajama2", "PS2DEMO", kGenHEPC, Common::HE_ISR, UNK, 0 },
- { "pajama3", "pajama3", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "pajama3", "pajama3", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "pajama3", "FPJ3Demo", kGenHEPC, Common::FR_FRA, UNK, 0 },
{ "pajama3", "GPJ3Demo", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "pajama3", "PajamaHTF", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
@@ -854,7 +858,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "putttime", "PuttTijd", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "putttime", "Putt Time", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "putttime", "PuttTTT", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "putttime", "PuttTTT", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "putttime", "PuttTTT", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "putttime", "TIJDDEMO", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 },
{ "putttime", "TijdDemo", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "putttime", "timedemo", kGenHEPC, UNK_LANG, UNK, 0 },
@@ -891,7 +895,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "socks", "socks", kGenHEPC, UNK_LANG, UNK, 0 },
{ "socks", "SockWorks", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "socks", "SokkenSoep", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "socks", "SokkenSoep", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 },
{ "socks", "SokkenSoep", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "spyfox", "spyfox", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
@@ -916,7 +920,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "spyfox", "JR-Demo", kGenHEMac, Common::FR_FRA, Common::kPlatformMacintosh, 0 },
{ "spyfox", "game", kGenHEIOS, Common::EN_ANY, Common::kPlatformIOS, 0 },
- { "spyfox2", "spyfox2", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "spyfox2", "spyfox2", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "spyfox2", "sf2-demo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "spyfox2", "sf2demo", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "spyfox2", "Sf2demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 52120949cc..c22525b6f2 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -180,9 +180,9 @@ static const ResString string_map_table_v345[] = {
// I18N: You may specify 'Yes' symbol at the end of the line, like this:
// "Moechten Sie wirklich neu starten? (J/N)J"
// Will react to J as 'Yes'
- {5, _s("Are you sure you want to restart? (Y/N)")},
+ {5, _s("Are you sure you want to restart? (Y/N)Y")},
// I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
- {6, _s("Are you sure you want to quit? (Y/N)")},
+ {6, _s("Are you sure you want to quit? (Y/N)Y")},
// Added in SCUMM4
{7, _s("Save")},
@@ -460,7 +460,7 @@ const Common::String InfoDialog::queryResString(int stringno) {
tmp += chr;
}
}
- return tmp;
+ return _(tmp);
}
#pragma mark -
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 475ffa3238..96b46aa21a 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -221,6 +221,15 @@ static const int maniacResourcesPerFile[55] = {
3, 10, 1, 0, 0
};
+static const int maniacDemoResourcesPerFile[55] = {
+ 0, 12, 0, 2, 1, 12, 1, 13, 6, 0,
+ 31, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 0, 1, 0, 0, 2, 0, 0, 1, 0, 0,
+ 2, 7, 1, 11, 0, 0, 5, 1, 0, 0,
+ 1, 0, 1, 3, 4, 3, 1, 0, 0, 1,
+ 2, 2, 0, 0, 0
+};
+
static const int zakResourcesPerFile[59] = {
0, 29, 12, 14, 13, 4, 4, 10, 7, 4,
14, 19, 5, 4, 7, 6, 11, 9, 4, 4,
@@ -253,9 +262,17 @@ ScummDiskImage::ScummDiskImage(const char *disk1, const char *disk2, GameSetting
_numGlobalObjects = 256;
_numRooms = 55;
_numCostumes = 25;
- _numScripts = 160;
- _numSounds = 70;
- _resourcesPerFile = maniacResourcesPerFile;
+
+ if (_game.features & GF_DEMO) {
+ _numScripts = 55;
+ _numSounds = 40;
+ _resourcesPerFile = maniacDemoResourcesPerFile;
+ } else {
+ _numScripts = 160;
+ _numSounds = 70;
+ _resourcesPerFile = maniacResourcesPerFile;
+ }
+
} else {
_numGlobalObjects = 775;
_numRooms = 59;
@@ -327,6 +344,9 @@ bool ScummDiskImage::open(const Common::String &filename) {
extractIndex(0); // Fill in resource arrays
+ if (_game.features & GF_DEMO)
+ return true;
+
openDisk(2);
if (_game.platform == Common::kPlatformApple2GS) {
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 824dfec144..86048af57c 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -452,8 +452,16 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE);
// F7 is used to skip cutscenes in the Commodote 64 version of Maniac Mansion
} else if (_game.id == GID_MANIAC &&_game.platform == Common::kPlatformC64) {
- if (lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0))
- lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE);
+ // Demo always F7 to be pressed to restart
+ if (_game.features & GF_DEMO) {
+ if (_roomResource != 0x2D && lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0)) {
+ restart();
+ return;
+ }
+ } else {
+ if (lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0))
+ lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE);
+ }
// 'B' is used to skip cutscenes in the NES version of Maniac Mansion
} else if (_game.id == GID_MANIAC &&_game.platform == Common::kPlatformNES) {
if (lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_SHIFT))
diff --git a/engines/scumm/resource_v2.cpp b/engines/scumm/resource_v2.cpp
index 7ccdfa4780..87dc132ff0 100644
--- a/engines/scumm/resource_v2.cpp
+++ b/engines/scumm/resource_v2.cpp
@@ -34,8 +34,14 @@ void ScummEngine_v2::readClassicIndexFile() {
_numGlobalObjects = 256;
_numRooms = 55;
_numCostumes = 25;
- _numScripts = 160;
- _numSounds = 70;
+ if (_game.features & GF_DEMO) {
+ _numScripts = 55;
+ _numSounds = 40;
+ } else {
+ _numScripts = 160;
+ _numSounds = 70;
+ }
+
} else if (_game.platform == Common::kPlatformNES) {
_numGlobalObjects = 775;
_numRooms = 55;
diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp
index 3828629997..4b59e22408 100644
--- a/engines/scumm/room.cpp
+++ b/engines/scumm/room.cpp
@@ -614,6 +614,15 @@ void ScummEngine_v3old::setupRoomSubBlocks() {
}
} else {
_roomWidth = READ_LE_UINT16(&(rmhd->old.width));
+
+ // WORKAROUND: Fix bad width value for room 64 (book of maps) in
+ // Indy3. A specific version of this game (DOS/EGA v1.0, according to
+ // scumm-md5.txt) has a wrong width of 1793 stored in the data files,
+ // which causes a strange situation in which the book view may scroll
+ // towards the right depending on Indy's position from the previous room.
+ // Fixes bug #6679.
+ if (_game.id == GID_INDY3 && _roomResource == 64 && _roomWidth == 1793)
+ _roomWidth = 320;
_roomHeight = READ_LE_UINT16(&(rmhd->old.height));
}
_numObjectsInRoom = roomptr[20];
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 7eadb042fb..0c0f6be73b 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -109,7 +109,12 @@ Common::Error ScummEngine::saveGameState(int slot, const Common::String &desc) {
}
bool ScummEngine::canSaveGameStateCurrently() {
- // FIXME: For now always allow loading in V0-V3 games
+ // Disallow saving in v0-v3 games when a 'prequel' to a cutscene is shown.
+ // This is a blank screen with text, and while this is shown, saving should
+ // be disabled, as no room is set.
+ if (_game.version <= 3 && _currentScript == 0xFF && _roomResource == 0 && _currentRoom == 0)
+ return false;
+
// TODO: Should we disallow saving in some more places,
// e.g. when a SAN movie is playing? Not sure whether the
// original EXE allowed this.
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 01ed21ece5..753287e217 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -47,7 +47,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 96
+#define CURRENT_VER 97
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 2fe5333bfc..c9b37d43b1 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -1164,8 +1164,10 @@ void ScummEngine_v0::walkToActorOrObject(int object) {
VAR(7) = y;
// actor must not move if frozen
- if (a->_miscflags & kActorMiscFlagFreeze)
+ if (a->_miscflags & kActorMiscFlagFreeze) {
a->stopActorMoving();
+ a->_newWalkBoxEntered = false;
+ }
}
bool ScummEngine_v0::checkPendingWalkAction() {
@@ -1179,7 +1181,7 @@ bool ScummEngine_v0::checkPendingWalkAction() {
Actor_v0 *a = (Actor_v0 *)derefActor(actor, "checkPendingWalkAction");
// wait until walking or turning action is finished
- if (a->_moving)
+ if (a->_moving != 2)
return true;
// after walking and turning finally execute the script
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index a7999a2695..609cbd1e89 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -172,7 +172,7 @@ void ScummEngine_v0::setupOpcodes() {
/* 6C */
OPCODE(0x6c, o_stopCurrentScript);
OPCODE(0x6d, o2_putActorInRoom);
- OPCODE(0x6e, o2_dummy);
+ OPCODE(0x6e, o_screenPrepare);
OPCODE(0x6f, o2_ifState08);
/* 70 */
OPCODE(0x70, o_lights);
@@ -589,9 +589,9 @@ void ScummEngine_v0::o_loadRoomWithEgo() {
return;
}
- // The original interpreter seems to set the actors new room X/Y to the last rooms X/Y
- // This fixes a problem with MM: script 158 in room 12, the 'Oompf!' script
- // This scripts runs before the actor position is set to the correct location
+ // The original interpreter sets the actors new room X/Y to the last rooms X/Y
+ // This fixes a problem with MM: script 158 in room 12, the 'Oomph!' script
+ // This scripts runs before the actor position is set to the correct room entry location
a->putActor(a->getPos().x, a->getPos().y, room);
_egoPositioned = false;
@@ -633,12 +633,21 @@ void ScummEngine_v0::setMode(byte mode) {
switch (_currentMode) {
case kModeCutscene:
+ if (_game.features & GF_DEMO) {
+ if (VAR(11) != 0)
+ _drawDemo = true;
+ }
_redrawSentenceLine = false;
// Note: do not change freeze state here
state = USERSTATE_SET_IFACE |
USERSTATE_SET_CURSOR;
+
break;
case kModeKeypad:
+ if (_game.features & GF_DEMO) {
+ if (VAR(11) != 0)
+ _drawDemo = true;
+ }
_redrawSentenceLine = false;
state = USERSTATE_SET_IFACE |
USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON |
@@ -646,6 +655,12 @@ void ScummEngine_v0::setMode(byte mode) {
break;
case kModeNormal:
case kModeNoNewKid:
+ if (_game.features & GF_DEMO) {
+ resetVerbs();
+ _activeVerb = kVerbWalkTo;
+ _redrawSentenceLine = true;
+ _drawDemo = false;
+ }
state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL |
USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON |
USERSTATE_SET_FREEZE;
@@ -707,17 +722,14 @@ void ScummEngine_v0::o_animateActor() {
}
a->animateActor(anim);
- a->animateCostume();
}
void ScummEngine_v0::o_getActorMoving() {
getResultPos();
int act = getVarOrDirectByte(PARAM_1);
Actor *a = derefActor(act, "o_getActorMoving");
- if (a->_moving)
- setResult(1);
- else
- setResult(2);
+
+ setResult(a->_moving);
}
void ScummEngine_v0::o_putActorAtObject() {
@@ -970,6 +982,10 @@ void ScummEngine_v0::o_setOwnerOf() {
setOwnerOf(obj, owner);
}
+void ScummEngine_v0::o_screenPrepare() {
+
+}
+
void ScummEngine_v0::resetSentence() {
_activeVerb = kVerbWalkTo;
_activeObject = 0;
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 74d0aa2483..a7ec2e644f 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -1390,7 +1390,14 @@ void ScummEngine_v2::o2_loadRoomWithEgo() {
a = derefActor(VAR(VAR_EGO), "o2_loadRoomWithEgo");
- a->putActor(0, 0, room);
+ // The original interpreter sets the actors new room X/Y to the last rooms X/Y
+ // This fixes a problem with MM: script 161 in room 12, the 'Oomph!' script
+ // This scripts runs before the actor position is set to the correct room entry location
+ if ((_game.id == GID_MANIAC) && (_game.platform != Common::kPlatformNES)) {
+ a->putActor(a->getPos().x, a->getPos().y, room);
+ } else {
+ a->putActor(0, 0, room);
+ }
_egoPositioned = false;
x = (int8)fetchScriptByte();
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 91afa859a9..4a53ca3fed 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -2497,10 +2497,6 @@ void ScummEngine_v5::walkActorToActor(int actor, int toActor, int dist) {
y = abr.y;
}
a->startWalkActor(x, y, -1);
-
- // WORKAROUND: See bug #2971126 for details on why this is here.
- if (_game.version == 0)
- o5_breakHere();
}
void ScummEngine_v5::o5_walkActorToActor() {
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 0eeff57ff7..5be18fb990 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Wed Jun 25 10:34:07 2014
+ This file was generated by the md5table tool on Sun Dec 7 23:09:10 2014
DO NOT EDIT MANUALLY!
*/
@@ -20,7 +20,7 @@ static const MD5Table md5table[] = {
{ "0354ee0d14cde1264ec762261c04c14a", "loom", "Steam", "Steam", 585728, Common::EN_ANY, Common::kPlatformWindows },
{ "035deab53b47bc43abc763560d0f8d4b", "atlantis", "Floppy", "Demo", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "037385a953789190298494d92b89b3d0", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
- { "03d3b18ee3fd68114e2a687c871e38d5", "freddi4", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows },
+ { "03d3b18ee3fd68114e2a687c871e38d5", "freddi4", "HE 99", "Mini Game", 13609, Common::EN_USA, Common::kPlatformWindows },
{ "0425954a9db5c340861672892c3e678d", "samnmax", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "04401d747f1a2c1c4b388daff71ed378", "ft", "", "", 535405461, Common::DE_DEU, Common::kPlatformMacintosh },
{ "04687cdf7f975a89d2474929f7b80946", "indy3", "FM-TOWNS", "", 7552, Common::EN_ANY, Common::kPlatformFMTowns },
@@ -28,7 +28,7 @@ static const MD5Table md5table[] = {
{ "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD },
{ "06b187468113f9ae5a400b148a847fac", "atlantis", "Floppy", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh },
- { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", 79382, Common::NL_NLD, Common::kPlatformUnknown },
{ "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "07a1eefd8ca95d77310311446c0f53d0", "brstorm", "", "", 5433, Common::EN_ANY, Common::kPlatformUnknown },
{ "07b810e37be7489263f7bc7627d4765d", "freddi4", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },
@@ -37,10 +37,11 @@ static const MD5Table md5table[] = {
{ "08656dd9698ddf1023ba9bf8a195e37b", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "08cc5c3eedaf72ebe12734eee94f7fa2", "balloon", "HE 80", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "09820417db26687bb7fe0c83cc4c553b", "ft", "", "Version A", 19697, Common::EN_ANY, Common::kPlatformUnknown },
+ { "09b0be55c16cd9e88b5080bf89ff281d", "freddi4", "HE 99", "Mini Game", 13609, Common::DE_DEU, Common::kPlatformWindows },
{ "0a212fa35fa8421f31c1f3961272caf0", "monkey", "VGA", "VGA", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "0a295b80f9a9edf818e8e161a0e83830", "freddi2", "HE 80", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "0a41311d462b6639fc45297b9044bf16", "monkey", "No AdLib", "EGA", -1, Common::ES_ESP, Common::kPlatformAtariST },
- { "0a6d7b81b850ed4a77811c60c9b5c555", "PuttTime", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows },
+ { "0a6d7b81b850ed4a77811c60c9b5c555", "PuttTime", "HE 99", "Mini Game", 18458, Common::EN_USA, Common::kPlatformWindows },
{ "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", 6532, Common::EN_ANY, Common::kPlatformPCEngine },
{ "0ab19be9e2a3f6938226638b2a3744fe", "PuttTime", "HE 100", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "0ac41e2e3d2174e5a042a6b565328dba", "puttrace", "HE 98", "Demo", 13110, Common::EN_USA, Common::kPlatformUnknown },
@@ -112,12 +113,14 @@ static const MD5Table md5table[] = {
{ "2108d83dcf09f8adb4bc524669c8cf51", "PuttTime", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "21a6592322f92550f144f68a8a4e685e", "dig", "", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "21abe302e1b1e2b66d6f5c12e241ebfd", "freddicove", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },
- { "2232b0b9411575b1f9961713ebc9de61", "balloon", "HE 80", "", -1, Common::UNK_LANG, Common::kPlatformWindows },
+ { "2232b0b9411575b1f9961713ebc9de61", "balloon", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "225e18566e810c634bf7de63e7568e3e", "mustard", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
+ { "22c7432dc97a821fcfccd480e93e3911", "spyfox2", "", "Mini Game", 14689, Common::NL_NLD, Common::kPlatformWindows },
{ "22c9eb04455440131ffc157aeb8d40a8", "fbear", "HE 70", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "22de86b2f7ec6e5db745ed1123310b44", "spyfox2", "", "Demo", 15832, Common::FR_FRA, Common::kPlatformWindows },
{ "22f4ea88a09da12df9308ba30bcb7d0f", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "23394c8d29cc63c61313959431a12476", "spyfox", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "24942a4200d99bdb4bdb78f9c7e07027", "pajama3", "", "Mini Game", 13911, Common::NL_NLD, Common::kPlatformWindows },
{ "254fede2f15dbb32a23760d601b01816", "zak", "V1", "", -1, Common::EN_ANY, Common::kPlatformC64 },
{ "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "Floppy", "Floppy", 7932, Common::EN_ANY, Common::kPlatformDOS },
{ "27b2ef1653089fe5b897d9cc89ce784f", "balloon", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
@@ -132,6 +135,7 @@ static const MD5Table md5table[] = {
{ "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "2a8658dbd13d84d1bce64a71a35995eb", "pajama2", "HE 99", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows },
{ "2c04aacffb8428f30ccf4f734fbe3adc", "activity", "", "", -1, Common::EN_ANY, Common::kPlatformDOS },
+ { "2cb46375dd5cdfd023e2f07e0a21b530", "maniac", "C64", "Demo", -1, Common::EN_ANY, Common::kPlatformC64 },
{ "2ccd8891ce4d3f1a334d21bff6a88ca2", "monkey", "CD", "", 9455, Common::EN_ANY, Common::kPlatformMacintosh },
{ "2d1e891fe52df707c30185e52c50cd92", "monkey", "CD", "CD", 8955, Common::EN_ANY, Common::kPlatformDOS },
{ "2d388339d6050d8ccaa757b64633954e", "indyloom", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns },
@@ -230,7 +234,7 @@ static const MD5Table md5table[] = {
{ "4f580a021eee026f3b4589e17d130d78", "freddi4", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown },
{ "4fa6870d9bc8c313b65d54b1da5a1891", "pajama", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "4fbbe9f64b8bc547503a379a301183ce", "tentacle", "", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown },
- { "4fe6a2e8df3c4536b278fdd2fbcb181e", "pajama3", "", "Mini Game", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "4fe6a2e8df3c4536b278fdd2fbcb181e", "pajama3", "", "Mini Game", 13911, Common::EN_ANY, Common::kPlatformWindows },
{ "5057fb0e99e5aa29df1836329232f101", "freddi2", "HE 80", "", -1, Common::UNK_LANG, Common::kPlatformWindows },
{ "507bb360688dc4180fdf0d7597352a69", "freddi", "HE 73", "", 26402, Common::SE_SWE, Common::kPlatformWindows },
{ "50b831f11b8c4b83784cf81f4dcc69ea", "spyfox", "HE 101", "", -1, Common::EN_ANY, Common::kPlatformWii },
@@ -302,6 +306,7 @@ static const MD5Table md5table[] = {
{ "6a60d395b78b205c93a956100b1bf5ae", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "6a8133b63d46f6663fbcbb49d5a2edb1", "atlantis", "Steam", "Steam", 520548, Common::EN_ANY, Common::kPlatformMacintosh },
{ "6af2419fe3db5c2fdb091ae4e5833770", "puttrace", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "6b10c9977cad9de503642059359792b1", "spyfox2", "", "Mini Game", 14689, Common::FR_FRA, Common::kPlatformWindows },
{ "6b19d0e25cbf720d05822379b8b90ed9", "PuttTime", "HE 90", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "6b257bb2827dd894b8109a50a1a18b5a", "freddicove", "HE 100", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "6b27dbcd8d5697d5c918eeca0f68ef6a", "puttrace", "HE CUP", "Preview", 3901484, Common::UNK_LANG, Common::kPlatformUnknown },
@@ -310,7 +315,8 @@ static const MD5Table md5table[] = {
{ "6bca7a1a96d16e52b8f3c42b50dbdca3", "fbear", "HE 62", "", -1, Common::JA_JPN, Common::kPlatform3DO },
{ "6bf70eee5de3d24d2403e0dd3d267e8a", "spyfox", "", "", 49221, Common::UNK_LANG, Common::kPlatformWindows },
{ "6c2bff0e327f2962e809c2e1a82d7309", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformAmiga },
- { "6d1baa1065ac5f7b210be8ebe4235e49", "freddi", "HE 73", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "6c375c2236d99f56e6c2cf540e74e474", "farm", "", "Demo", 34333, Common::NL_NLD, Common::kPlatformWindows },
+ { "6d1baa1065ac5f7b210be8ebe4235e49", "freddi", "HE 73", "", 26384, Common::NL_NLD, Common::kPlatformMacintosh },
{ "6dead580b0ff14d5f7b33b4219f04159", "samnmax", "", "Demo", 16556335, Common::EN_ANY, Common::kPlatformMacintosh },
{ "6df20c50c1ab19799de9be7ae7716881", "fbear", "HE 62", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "6e959d65358eedf9b68b81e304b97fa4", "tentacle", "", "CD", 7932, Common::DE_DEU, Common::kPlatformUnknown },
@@ -324,7 +330,7 @@ static const MD5Table md5table[] = {
{ "70b0719ac3a5b47ae233c561823d5b96", "puttzoo", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
{ "71523b539491527d9860f4407faf0411", "monkey", "Demo", "EGA Demo", 7607, Common::EN_ANY, Common::kPlatformDOS },
{ "71d384e7676c53d513ddd333eae1d82c", "Blues123time", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
- { "71fe97c3108678cf604f14abe342341b", "spyfox2", "", "", -1, Common::NL_NLD, Common::kPlatformWindows },
+ { "71fe97c3108678cf604f14abe342341b", "spyfox2", "", "", 51286, Common::NL_NLD, Common::kPlatformUnknown },
{ "7222f260253f325c21fcfa68b5bfab67", "spyfox2", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "72ac6bc980d5101c2142189d746bd62f", "spyfox", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "732845548b1d6c2da572cb6a1bf81b07", "spyfox2", "", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
@@ -348,6 +354,7 @@ static const MD5Table md5table[] = {
{ "78c07ca088526d8d4446a4c2cb501203", "freddi3", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7974365d3dc0f43a2748c975f91ff042", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "79b05f628586837e7166e82b2279bb50", "loom", "PC-Engine", "", -1, Common::JA_JPN, Common::kPlatformPCEngine },
+ { "7a2b6d8e8a645c9d534c8c4edc38a9c9", "freddi4", "HE 99", "Mini Game", 13609, Common::IT_ITA, Common::kPlatformWindows },
{ "7b4ee071eecadc2d8cd0c3509110825c", "puttzoo", "HE 100", "Remastered", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "7bad72e332a59f9fcc1d437f4edad32a", "puttcircus", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "7c2e76087027eeee9c8f8985f93a1cc5", "freddi4", "", "Demo", 13584, Common::EN_ANY, Common::kPlatformUnknown },
@@ -357,6 +364,7 @@ static const MD5Table md5table[] = {
{ "7e151c17adf624f1966c8fc5827c95e9", "puttputt", "HE 61", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "7ea2da67ebabea4ac20cee9f4f9d2934", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "7edd665bbede7ea8b7233f8e650be6f8", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformUnknown },
+ { "7f2578d8d33a9ff525488a2d9ba617e4", "spyfox2", "", "Mini Game", 14689, Common::DE_DEU, Common::kPlatformWindows },
{ "7f45ddd6dbfbf8f80c0c0efea4c295bc", "maniac", "V1", "V1", 1972, Common::EN_ANY, Common::kPlatformDOS },
{ "7f945525abcd48015adf1632637a44a1", "pajama", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7fbcff27c323499beaedd605e1ebd47d", "indy3", "Steam", "Steam", 561152, Common::EN_ANY, Common::kPlatformWindows },
@@ -389,13 +397,15 @@ static const MD5Table md5table[] = {
{ "8afb3cf9f95abf208358e984f0c9e738", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "8bdb0bf87b5e303dd35693afb9351215", "ft", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", 34333, Common::EN_ANY, Common::kPlatformWindows },
+ { "8dd4d590685c19bf651b5016e749ead2", "PuttTime", "HE 99", "Mini Game", 18458, Common::FR_FRA, Common::kPlatformWindows },
{ "8de13897f0121c79d29a2377159f9ad0", "socks", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh },
- { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", 65305, Common::NL_NLD, Common::kPlatformUnknown },
{ "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", 9925, Common::EN_ANY, Common::kPlatformFMTowns },
{ "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
+ { "8f345db2f3f5a25ed6305001957e6f72", "freddicove", "HE 100", "", 41182, Common::NL_NLD, Common::kPlatformUnknown },
{ "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformDOS },
{ "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", 18041, Common::UNK_LANG, Common::kPlatformWindows },
{ "8ffd618a776a4c0d8922bb28b09f8ce8", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -409,11 +419,13 @@ static const MD5Table md5table[] = {
{ "92b078d9d6d9d751da9c26b8b3075779", "tentacle", "Floppy", "Floppy", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "92e7727e67f5cd979d8a1070e4eb8cb3", "puttzoo", "HE 98.5", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "92fc0073a4cf259ff36070ecb8628ba8", "thinkerk", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
+ { "9340b552b0f2dffe6d4f3d13ebebe832", "freddi4", "HE 99", "Mini Game", 13609, Common::NL_NLD, Common::kPlatformWindows },
{ "94aaedbb8f26d71ed3ad6dd34490e29e", "tentacle", "Floppy", "Floppy", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "94db6519da85b8d08c976d8e9a858ea7", "baseball", "HE CUP", "Preview", 10044774, Common::UNK_LANG, Common::kPlatformUnknown },
{ "95818b178d473c989ac753574e8892aa", "readtime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "95b3806e043be08668c54c3ffe98650f", "BluesABCTime", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "95be99181bd0f10fef4872c2d4a771cb", "zak", "V1", "", -1, Common::DE_DEU, Common::kPlatformC64 },
+ { "9684c161258d68e0d464d6cab7024b9c", "spyfox2", "", "Mini Game", 14689, Common::IT_ITA, Common::kPlatformWindows },
{ "96a3069a3c63caa7329588ce1fef41ee", "spyozon", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "9708cf716ed8bcc9ff3fcfc69413b746", "puttputt", "HE 62", "", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "9778341eefc6feb447ca07e7be21791c", "puttrace", "HE 99", "Demo", -1, Common::IT_ITA, Common::kPlatformWindows },
@@ -459,9 +471,11 @@ static const MD5Table md5table[] = {
{ "a59a438cb182124c30c4447d8ed469e9", "freddi", "HE 100", "", 34837, Common::NB_NOR, Common::kPlatformWii },
{ "a5c5388da9bf0e6662fdca8813a79d13", "farm", "", "", 86962, Common::EN_ANY, Common::kPlatformWindows },
{ "a654fb60c3b67d6317a7894ffd9f25c5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
+ { "a71014c53a6d18c66ef2ea0ee42328e9", "PuttTime", "HE 99", "Mini Game", 18458, Common::NL_NLD, Common::kPlatformWindows },
{ "a7cacad9c40c4dc9e1812abf6c8af9d5", "puttcircus", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "a85856675429fe88051744f755b72f93", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "a86f9c49355579c30d4a55b477c0d869", "baseball2001", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "a8fcc3084ad5e3e569722755f205b1ef", "pajama3", "", "Mini Game", 13911, Common::DE_DEU, Common::kPlatformWindows },
{ "a9543ef0d79bcb47cd76ec197ad0a967", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "a99c39ba65b6086be28aef576da69595", "spyozon", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "a9f2f04b1ecaab9495b59befffe9bf88", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
@@ -478,6 +492,7 @@ static const MD5Table md5table[] = {
{ "acad97ab1c6fc2a5b2d98abf6db4a190", "tentacle", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "ae94f110a14ce71fc515d5b648827a8f", "tentacle", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "aeec382acef62e122bf0d5b14581cfa4", "zak", "V1", "", -1, Common::IT_ITA, Common::kPlatformC64 },
+ { "aef415cc5dc063e3668359c2657169f3", "PuttTime", "HE 99", "Mini Game", 18458, Common::DE_DEU, Common::kPlatformWindows },
{ "aefa244ea034b7cd2041f0a44be7d9ba", "pajama3", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "af2bd1a43b50b55915d87994e093203d", "freddi", "HE 99", "Updated", 34829, Common::DE_DEU, Common::kPlatformWindows },
{ "b100abf7ff83146df50db78dbd5e9cfa", "freddicove", "HE 100", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
@@ -505,7 +520,7 @@ static const MD5Table md5table[] = {
{ "be83e882b44f2767bc08d4f766ebc347", "maniac", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAtariST },
{ "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
- { "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", -1, Common::NL_NLD, Common::kPlatformWindows },
+ { "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", 26159, Common::NL_NLD, Common::kPlatformWindows },
{ "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD },
{ "c20848f53c2d48bfacdc840993843765", "freddi2", "HE 80", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "c225bec1b6c0798a2b8c89ac226dc793", "pajama", "HE 101", "", -1, Common::EN_ANY, Common::kPlatformWii },
@@ -516,6 +531,7 @@ static const MD5Table md5table[] = {
{ "c3b22fa4654bb580b20325ebf4174841", "puttzoo", "", "", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "c3df37df9d3b481b45f75283a9907c47", "loom", "EGA", "EGA", -1, Common::IT_ITA, Common::kPlatformDOS },
{ "c4787c3e8b5e2dfda90850ee800af00f", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformDOS },
+ { "c486e4cfa7bd6f8efcd0740f96f7dde3", "freddi4", "HE 99", "Mini Game", 13609, Common::FR_FRA, Common::kPlatformWindows },
{ "c4ffae9fac495475d6bc3343ccc8faf9", "Soccer2004", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "c5cc7cba02a2fbd539c4439e775b0536", "puttzoo", "HE 99", "Updated", 43470, Common::DE_DEU, Common::kPlatformWindows },
{ "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", 7540, Common::EN_ANY, Common::kPlatformFMTowns },
@@ -555,6 +571,7 @@ static const MD5Table md5table[] = {
{ "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformDOS },
{ "d0ad929def3e9cfe39dea55bd12098d4", "puttcircus", "", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "d0b531227a27c6662018d2bd05aac52a", "monkey", "VGA", "VGA", 8357, Common::DE_DEU, Common::kPlatformDOS },
+ { "d1a73e87564477c7c2dcc2b8f616ad0b", "pajama3", "", "Mini Game", 13911, Common::IT_ITA, Common::kPlatformWindows },
{ "d220d154aafbfa12bd6f3ab1b2dae420", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformMacintosh },
{ "d2cc8e31bce61e6cf2951249e10638fe", "basketball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "d37c55388294b66e53e7ced3af88fa68", "freddi2", "HE 100", "Updated Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
@@ -602,7 +619,7 @@ static const MD5Table md5table[] = {
{ "e534d29afb3c6e0ee9dc3d53c5956714", "atlantis", "Floppy", "Floppy", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "e5563c8358443c4352fcddf7402a5e0a", "pajama2", "HE 98.5", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "e5c112140ad6574997de033a8e2a2964", "readtime", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
- { "e62056ba675ad65d8854ab3c5ad4b3c0", "spyfox2", "", "Mini Game", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "e62056ba675ad65d8854ab3c5ad4b3c0", "spyfox2", "", "Mini Game", 14689, Common::EN_ANY, Common::kPlatformWindows },
{ "e63a0b9249b5ca4cc4d3ac34305ae360", "freddi", "HE 99", "", -1, Common::NB_NOR, Common::kPlatformWindows },
{ "e689bdf67f98b1d760ce4487ec0e8d06", "indy3", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformAmiga },
{ "e6cd81b25ab1453a8a6d3482118c391e", "pass", "", "", 7857, Common::EN_ANY, Common::kPlatformDOS },
@@ -624,7 +641,9 @@ static const MD5Table md5table[] = {
{ "edfdb24a499d92c59f824c52987c0eec", "atlantis", "Floppy", "Floppy", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "ee41f6afbc5b26fa475754b56fe92048", "puttputt", "HE 61", "", 8032, Common::JA_JPN, Common::kPlatform3DO },
{ "ee785fe2569bc9965526e774f7ab86f1", "spyfox", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
+ { "ee8cfeb76e55d43a01c25e0865a9db76", "puttrace", "HE 98", "Demo", 13135, Common::NL_NLD, Common::kPlatformMacintosh },
{ "eea4d9ac2fb6f145945a308e8866915b", "maniac", "C64", "", -1, Common::EN_ANY, Common::kPlatformC64 },
+ { "eeb606c2d2ec877a712a9f20c10bcdda", "farm", "", "", 87034, Common::NL_NLD, Common::kPlatformMacintosh },
{ "ef347474f3c7be3b29584eaa133cca05", "samnmax", "Floppy", "Floppy", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "ef71a322b6530ac45b1a070f7c0795f7", "moonbase", "Demo", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "ef74d9071d4e564b037cb44bd6774de7", "fbear", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformDOS },
@@ -649,6 +668,7 @@ static const MD5Table md5table[] = {
{ "fa30c4a7a806629626269b6dcab59a15", "BluesBirthday", "HE CUP", "Preview", 7819264, Common::UNK_LANG, Common::kPlatformUnknown },
{ "fa3cb1541f9d7cf99ccbae6249bc150c", "maniac", "NES", "", -1, Common::IT_ITA, Common::kPlatformNES },
{ "fa84cb1018103a4ee4e5fa8041c1d0d1", "freddi4", "", "Demo", 13609, Common::DE_DEU, Common::kPlatformWindows },
+ { "faa89ab5e67ba4eebb4399f584f7490c", "pajama3", "", "Mini Game", 13911, Common::FR_FRA, Common::kPlatformWindows },
{ "fb66aa42de21675116346213f176a366", "monkey", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "fbb697d89d2beca87360a145f467bdae", "PuttTime", "HE 90", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "fbbbb38a81fc9d6a61d509278390a290", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 475b146a7b..6040344c2c 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -716,7 +716,7 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr)
ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
: ScummEngine_v2(syst, dr) {
-
+ _drawDemo = false;
_currentMode = 0;
_currentLights = 0;
@@ -731,6 +731,9 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
VAR_ACTIVE_OBJECT2 = 0xFF;
VAR_IS_SOUND_RUNNING = 0xFF;
VAR_ACTIVE_VERB = 0xFF;
+
+ if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 )
+ _game.features |= GF_DEMO;
}
ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)
@@ -1091,8 +1094,13 @@ Common::Error ScummEngine::init() {
const char *tmpBuf1, *tmpBuf2;
assert(_game.id == GID_MANIAC || _game.id == GID_ZAK);
if (_game.id == GID_MANIAC) {
- tmpBuf1 = "maniac1.d64";
- tmpBuf2 = "maniac2.d64";
+ if (_game.features & GF_DEMO) {
+ tmpBuf1 = "maniacdemo.d64";
+ tmpBuf2 = "maniacdemo.d64";
+ } else {
+ tmpBuf1 = "maniac1.d64";
+ tmpBuf2 = "maniac2.d64";
+ }
} else {
tmpBuf1 = "zak1.d64";
tmpBuf2 = "zak2.d64";
@@ -2572,7 +2580,7 @@ void ScummEngine::runBootscript() {
int args[NUM_SCRIPT_LOCAL];
memset(args, 0, sizeof(args));
args[0] = _bootParam;
- if (_game.id == GID_MANIAC && (_game.features & GF_DEMO))
+ if (_game.id == GID_MANIAC && (_game.features & GF_DEMO) && (_game.platform != Common::kPlatformC64))
runScript(9, 0, 0, args);
else
runScript(1, 0, 0, args);
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index af118a89a1..967909e505 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -642,7 +642,7 @@ protected:
byte _opcode;
byte _currentScript;
int _scummStackPos;
- int _vmStack[150];
+ int _vmStack[256];
OpcodeEntry _opcodes[256];
@@ -1362,7 +1362,7 @@ public:
byte VAR_SCRIPT_CYCLE; // Used in runScript()/runObjectScript()
byte VAR_NUM_SCRIPT_CYCLES; // Used in runAllScripts()
-
+
byte VAR_QUIT_SCRIPT; // Used in confirmExitDialog()
// Exists both in V7 and in V72HE:
diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h
index 80d047ab9f..4098d639c4 100644
--- a/engines/scumm/scumm_v0.h
+++ b/engines/scumm/scumm_v0.h
@@ -46,6 +46,7 @@ protected:
};
protected:
+ bool _drawDemo;
byte _currentMode;
byte _currentLights;
@@ -67,6 +68,8 @@ public:
virtual void resetScumm();
+ byte walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest);
+
protected:
virtual void resetRoomObject(ObjectData *od, const byte *room, const byte *searchptr = NULL);
@@ -99,6 +102,8 @@ protected:
virtual void handleMouseOver(bool updateInventory);
int verbPrepIdType(int verbid);
void resetVerbs();
+ void verbDemoMode();
+ void verbDrawDemoString(int VerbDemoNumber);
void clearSentenceLine();
void flushSentenceLine();
@@ -116,7 +121,7 @@ protected:
void resetSentence();
- virtual bool areBoxesNeighbors(int box1nr, int box2nr);
+ bool areBoxesNeighbors(int box1nr, int box2nr);
bool ifEqualActiveObject2Common(bool checkType);
@@ -161,6 +166,7 @@ protected:
void o_cutscene();
void o_endCutscene();
void o_setOwnerOf();
+ void o_screenPrepare();
byte VAR_ACTIVE_OBJECT2;
byte VAR_IS_SOUND_RUNNING;
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index cb428d1c15..84d2b37f96 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -1066,9 +1066,9 @@ void Sound::playCDTrackInternal(int track, int numLoops, int startFrame, int dur
Common::File *cddaFile = new Common::File();
if (cddaFile->open("CDDA.SOU")) {
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
- Audio::Timestamp end = Audio::Timestamp(0, startFrame + duration, 75);
+ Audio::Timestamp end = Audio::Timestamp(0, startFrame + duration, 75);
Audio::SeekableAudioStream *stream = makeCDDAStream(cddaFile, DisposeAfterUse::YES);
-
+
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_loomSteamCDAudioHandle,
Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops));
} else {
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index a903ac5804..a6be5c3f3a 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -715,7 +715,7 @@ void ScummEngine_v99he::resetScummVars() {
VAR(140) = 0;
#endif
}
-
+
if (_game.id == GID_PUTTZOO && _game.heversion == 100 && _game.platform == Common::kPlatformWindows) {
// Specific to Nimbus Games version.
VAR(156) = 1;
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index fdb98a8019..fe936b550c 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -80,6 +80,19 @@ static const VerbSettings v0VerbTable_German[] = {
{kVerbWhatIs, 13, 2, "Was ist"}
};
+struct VerbDemo {
+ int color;
+ const char *str;
+};
+static VerbDemo v0DemoStr[] = {
+ {7, " MANIAC MANSION DEMO DISK "},
+ {5, " from Lucasfilm Games "},
+ {5, " Copyright = 1987 by Lucasfilm Ltd. "},
+ {5, " All Rights Reserved. "},
+ {0, " "},
+ {16, " Press F7 to return to menu. "}
+};
+
int ScummEngine_v0::verbPrepIdType(int verbid) {
switch (verbid) {
case kVerbUse: // depends on object1
@@ -93,6 +106,44 @@ int ScummEngine_v0::verbPrepIdType(int verbid) {
}
}
+void ScummEngine_v0::verbDemoMode() {
+ int i;
+
+ for (i = 1; i < 16; i++)
+ killVerb(i);
+
+ for (i = 0; i < 6; i++) {
+ verbDrawDemoString(i);
+ }
+}
+
+void ScummEngine_v0::verbDrawDemoString(int VerbDemoNumber) {
+ byte string[80];
+ const char *ptr = v0DemoStr[VerbDemoNumber].str;
+ int i = 0, len = 0;
+
+ // Maximum length of printable characters
+ int maxChars = 40;
+ while (*ptr) {
+ if (*ptr != '@')
+ len++;
+ if (len > maxChars) {
+ break;
+ }
+
+ string[i++] = *ptr++;
+
+ }
+ string[i] = 0;
+
+ _string[2].charset = 1;
+ _string[2].ypos = _virtscr[kVerbVirtScreen].topline + (8 * VerbDemoNumber);
+ _string[2].xpos = 0;
+ _string[2].right = _virtscr[kVerbVirtScreen].w - 1;
+ _string[2].color = v0DemoStr[VerbDemoNumber].color;
+ drawString(2, (byte *)string);
+}
+
void ScummEngine_v0::resetVerbs() {
VirtScreen *virt = &_virtscr[kVerbVirtScreen];
VerbSlot *vs;
@@ -708,7 +759,6 @@ void ScummEngine_v0::verbExec() {
Actor_v0 *a = (Actor_v0 *)derefActor(VAR(VAR_EGO), "verbExec");
int x = _virtualMouse.x / V12_X_MULTIPLIER;
int y = _virtualMouse.y / V12_Y_MULTIPLIER;
- //actorSetPosInBox();
// 0xB31
VAR(6) = x;
@@ -717,7 +767,6 @@ void ScummEngine_v0::verbExec() {
if (a->_miscflags & kActorMiscFlagFreeze)
return;
- a->stopActorMoving();
a->startWalkActor(VAR(6), VAR(7), -1);
}
@@ -856,6 +905,10 @@ void ScummEngine_v0::checkExecVerbs() {
}
}
}
+
+ if (_drawDemo && _game.features & GF_DEMO) {
+ verbDemoMode();
+ }
if (_redrawSentenceLine)
drawSentenceLine();
diff --git a/engines/sword1/console.cpp b/engines/sword1/console.cpp
index 7fabc62192..3a4b51965b 100644
--- a/engines/sword1/console.cpp
+++ b/engines/sword1/console.cpp
@@ -36,7 +36,7 @@ SwordConsole::SwordConsole(SwordEngine *vm) : GUI::Debugger(), _vm(vm) {
SwordConsole::~SwordConsole() {
}
-
+
bool SwordConsole::Cmd_SpeechEndianness(int argc, const char **argv) {
if (argc == 1) {
debugPrintf("Using %s speech\n", _vm->_sound->_bigEndianSpeech ? "be" : "le");
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 9140bddb65..4deaf06edc 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -144,7 +144,7 @@ void Sound::checkSpeechFileEndianness() {
debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE (%d samples)", be_diff, le_diff, maxSamples);
}
}
-
+
double Sound::endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples) {
if (!data)
return 50000.; // the heuristic value for the wrong endianess is about 21000 (1/3rd of the 16 bits range)
diff --git a/engines/sword25/gfx/renderobjectmanager.cpp b/engines/sword25/gfx/renderobjectmanager.cpp
index 4927b4c58e..8aeecad6b1 100644
--- a/engines/sword25/gfx/renderobjectmanager.cpp
+++ b/engines/sword25/gfx/renderobjectmanager.cpp
@@ -107,7 +107,7 @@ bool RenderObjectManager::render() {
if (!_currQueue->exists(*it))
_uta->addRect((*it)._bbox);
}
-
+
// Add rectangles of objects which are different from the previous frame
for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it) {
if (!_prevQueue->exists(*it))
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index bb0aab3ad4..76142c2534 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -57,7 +57,6 @@ DECLARE_SINGLETON(Sword25::RenderObjectRegistry);
namespace Sword25 {
-const char *const PACKAGE_MANAGER = "archiveFS";
const char *const DEFAULT_SCRIPT_FILE = "/system/boot.lua";
Sword25Engine::Sword25Engine(OSystem *syst, const ADGameDescription *gameDesc):
diff --git a/engines/sword25/util/lua/lapi.cpp b/engines/sword25/util/lua/lapi.cpp
index b97e90012c..d7ebdcbe12 100644
--- a/engines/sword25/util/lua/lapi.cpp
+++ b/engines/sword25/util/lua/lapi.cpp
@@ -30,11 +30,12 @@
#include "common/textconsole.h"
+#if 0
const char lua_ident[] =
"Lua: " LUA_RELEASE " " LUA_COPYRIGHT " \n"
"Authors: " LUA_AUTHORS " \n"
"URL: www.lua.org\n";
-
+#endif
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
diff --git a/engines/sword25/util/lua/liolib.cpp b/engines/sword25/util/lua/liolib.cpp
index 0d27f9677f..403dea2ec2 100644
--- a/engines/sword25/util/lua/liolib.cpp
+++ b/engines/sword25/util/lua/liolib.cpp
@@ -24,7 +24,7 @@
#define IO_OUTPUT 2
-static const char *const fnames[] = {"input", "output"};
+//static const char *const fnames[] = {"input", "output"};
static int pushresult (lua_State *L, int i, const char *filename) {
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index 78b0a815e8..cbe16b0d5b 100644
--- a/engines/sword25/util/pluto/pluto.cpp
+++ b/engines/sword25/util/pluto/pluto.cpp
@@ -325,7 +325,7 @@ static void persisttable(PersistInfo *pi)
#ifdef TOTEXT
printf("persisttable\n");
#endif
-
+
/* perms reftbl ... tbl */
lua_checkstack(pi->L, 3);
if(persistspecialobject(pi, 1)) {
@@ -1192,7 +1192,7 @@ int persist_l(lua_State *L)
wi.buf = NULL;
wi.buflen = 0;
-
+
lua_settop(L, 2);
/* perms? rootobj? */
luaL_checktype(L, 1, LUA_TTABLE);
@@ -1750,7 +1750,7 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
#else
verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
#endif
-
+
//read_size(&upi->zio, (size_t *)&L2->errfunc);
L2->base = L2->stack + stackbase;
L2->top = L2->stack + stacktop;
@@ -2045,7 +2045,7 @@ int unpersist_l(lua_State *L)
int version_l(lua_State *L)
{
const char *version = VERSION;
-
+
lua_settop(L, 0);
/* (empty) */
lua_pushlstring(L, version, strlen(version));
diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp
index c102242dfd..0a2c62330b 100644
--- a/engines/tony/game.cpp
+++ b/engines/tony/game.cpp
@@ -1557,14 +1557,14 @@ void RMPointer::updateCursor() {
for (int i = 0; i < 64; i++) {
uint16 *lineP = src;
for (int j = 0; j < 64; j++) {
- lineP[j] = RMGfxTargetBuffer::_precalcTable[lineP[j] & 0x7FFF];
+ lineP[j] = RMGfxTargetBuffer::_precalcTable[lineP[j]];
}
src += 64;
}
}
// Get the raw pixel data and set the cursor to it
- Graphics::PixelFormat pixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
CursorMan.replaceCursor(cursorData, 64, 64, _cursorHotspot._x, _cursorHotspot._y, 0, 1, &pixelFormat);
}
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index 9254d59df6..2a32926c53 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -422,11 +422,11 @@ uint16 *RMGfxTargetBuffer::_precalcTable = NULL;
* called if the user selects the black & white option.
*/
void RMGfxTargetBuffer::createBWPrecalcTable() {
- _precalcTable = new uint16[0x8000];
+ _precalcTable = new uint16[0x10000];
- for (int i = 0; i < 0x8000; i++) {
- int r = (i >> 10) & 0x1F;
- int g = (i >> 5) & 0x1F;
+ for (int i = 0; i < 0x10000; i++) {
+ int r = (i >> 11) & 0x1F;
+ int g = (i >> 6) & 0x1F;
int b = i & 0x1F;
int min = MIN(r, MIN(g, b));
@@ -434,11 +434,11 @@ void RMGfxTargetBuffer::createBWPrecalcTable() {
min = (min + max) / 2;
- r = CLIP(min + 8 - 8, 0, 31);
- g = CLIP(min + 5 - 8, 0, 31);
- b = CLIP(min + 0 - 8, 0, 31);
+ r = CLIP(min + 8 - 8, 0, 0x1f);
+ g = CLIP(min + 5 - 8, 0, 0x1f);
+ b = CLIP(min + 0 - 8, 0, 0x1f);
- _precalcTable[i] = (r << 10) | (g << 5) | b;
+ _precalcTable[i] = (r << 11) | (g << 6) | b;
}
}
@@ -512,8 +512,9 @@ int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
void RMGfxSourceBufferPal::preparePalette() {
for (int i = 0; i < 256; i++) {
- _palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) << 10) |
- (((int)_pal[i * 3 + 1] >> 3) << 5) |
+ // we convert 555 to 565 here.
+ _palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) << 11) |
+ (((int)_pal[i * 3 + 1] >> 3) << 6) |
(((int)_pal[i * 3 + 2] >> 3) << 0);
}
}
@@ -665,8 +666,8 @@ void RMGfxSourceBuffer8::create(int dimx, int dimy) {
RMGfxBuffer::create(dimx, dimy, 8);
}
-#define GETRED(x) (((x) >> 10) & 0x1F)
-#define GETGREEN(x) (((x) >> 5) & 0x1F)
+#define GETRED(x) (((x) >> 11) & 0x1F)
+#define GETGREEN(x) (((x) >> 5) & 0x3F)
#define GETBLUE(x) ((x) & 0x1F)
/****************************************************************************\
@@ -684,13 +685,13 @@ int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
if (r > 0x1F)
r = 0x1F;
- if (g > 0x1F)
- g = 0x1F;
+ if (g > 0x3F)
+ g = 0x3F;
if (b > 0x1F)
b = 0x1F;
- return (r << 10) | (g << 5) | b;
+ return (r << 11) | (g << 5) | b;
}
void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
@@ -802,8 +803,8 @@ void RMGfxSourceBuffer8RLE::preparePalette() {
// Handle RGB alpha blending
if (_alphaBlendColor != -1) {
- _alphaR = (_palFinal[_alphaBlendColor] >> 10) & 0x1F;
- _alphaG = (_palFinal[_alphaBlendColor] >> 5) & 0x1F;
+ _alphaR = (_palFinal[_alphaBlendColor] >> 11) & 0x1F;
+ _alphaG = (_palFinal[_alphaBlendColor] >> 5) & 0x3F;
_alphaB = (_palFinal[_alphaBlendColor]) & 0x1F;
}
}
@@ -1054,15 +1055,15 @@ RLEByteDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
- *dst ++ = (r << 10) | (g << 5) | b;
+ *dst ++ = (r << 11) | (g << 5) | b;
}
nLength -= n;
@@ -1158,15 +1159,15 @@ RLEByteFlippedDoAlpha2:
if (n > nLength)
n = nLength;
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
- *dst-- = (r << 10) | (g << 5) | b;
+ *dst-- = (r << 11) | (g << 5) | b;
}
nLength -= n;
@@ -1302,15 +1303,15 @@ RLEWordDoAlpha2:
n = nLength;
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
- *dst++ = (r << 10) | (g << 5) | b;
+ *dst++ = (r << 11) | (g << 5) | b;
}
nLength -= n;
@@ -1416,15 +1417,15 @@ RLEWordFlippedDoAlpha2:
n = nLength;
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
- *dst-- = (r << 10) | (g << 5) | b;
+ *dst-- = (r << 11) | (g << 5) | b;
}
nLength -= n;
@@ -1543,15 +1544,15 @@ RLEWordDoAlpha2:
// @@@ SHOULD NOT BE THERE !!!!!
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
b = (b >> 2) + (_alphaB >> 1);
- *dst++ = (r << 10) | (g << 5) | b;
+ *dst++ = (r << 11) | (g << 5) | b;
}
nLength -= n;
@@ -1570,19 +1571,19 @@ RLEWordDoCopy2:
n = nLength;
for (int i = 0; i < n; i++) {
- int r = (*dst >> 10) & 0x1F;
- int g = (*dst >> 5) & 0x1F;
+ int r = (*dst >> 11) & 0x1F;
+ int g = (*dst >> 5) & 0x3F;
int b = *dst & 0x1F;
- int r2 = (_palFinal[*src] >> 10) & 0x1F;
- int g2 = (_palFinal[*src] >> 5) & 0x1F;
+ int r2 = (_palFinal[*src] >> 11) & 0x1F;
+ int g2 = (_palFinal[*src] >> 5) & 0x3F;
int b2 = _palFinal[*src] & 0x1F;
r = (r >> 1) + (r2 >> 1);
g = (g >> 1) + (g2 >> 1);
b = (b >> 1) + (b2 >> 1);
- *dst ++ = (r << 10) | (g << 5) | b;
+ *dst ++ = (r << 11) | (g << 5) | b;
src++;
}
@@ -1732,14 +1733,14 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
g /= 5;
b /= 5;
- if (r > 31)
- r = 31;
- if (g > 31)
- g = 31;
- if (b > 31)
- b = 31;
+ if (r > 0x1f)
+ r = 0x1f;
+ if (g > 0x3f)
+ g = 0x3f;
+ if (b > 0x1f)
+ b = 0x1f;
- mybuf[0] = (r << 10) | (g << 5) | b;
+ mybuf[0] = (r << 11) | (g << 5) | b;
}
}
@@ -1773,14 +1774,14 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
g /= 6;
b /= 6;
- if (r > 31)
- r = 31;
- if (g > 31)
- g = 31;
- if (b > 31)
- b = 31;
+ if (r > 0x1f)
+ r = 0x1f;
+ if (g > 0x3f)
+ g = 0x3f;
+ if (b > 0x1f)
+ b = 0x1f;
- mybuf[0] = (r << 10) | (g << 5) | b;
+ mybuf[0] = (r << 11) | (g << 5) | b;
}
}
@@ -1948,8 +1949,17 @@ void RMGfxSourceBuffer16::prepareImage() {
// Color space conversion if necessary!
uint16 *buf = (uint16 *)_buf;
- for (int i = 0; i < _dimx * _dimy; i++)
- buf[i] = FROM_LE_16(buf[i]) & 0x7FFF;
+ // convert 555 to 565
+ for (int i = 0; i < _dimx * _dimy; i++) {
+ uint16 pixel = FROM_LE_16(buf[i]);
+ int r = (pixel >> 10) & 0x1F;
+ int g = (pixel >> 5) & 0x1F;
+ int b = pixel & 0x1F;
+
+ pixel = (r << 11) | (g << 6) | b;
+
+ buf[i] = pixel;
+ }
}
RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy)
@@ -1983,7 +1993,8 @@ void RMGfxBox::setColor(byte r, byte g, byte b) {
r >>= 3;
g >>= 3;
b >>= 3;
- _wFillColor = (r << 10) | (g << 5) | b;
+ // These are hard-coded colors, so we convert 555 to 565.
+ _wFillColor = (r << 11) | (g << 6) | b;
}
void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
diff --git a/engines/tony/mpal/lzo.cpp b/engines/tony/mpal/lzo.cpp
index 314d6f3ed5..6cc2333315 100644
--- a/engines/tony/mpal/lzo.cpp
+++ b/engines/tony/mpal/lzo.cpp
@@ -116,7 +116,7 @@ int lzo1x_decompress(const byte *in, uint32 in_len, byte *out, uint32 *out_len)
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
- do
+ do
*op++ = *ip++;
while (--t > 0);
diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp
index 5c50a50a57..3b3687419b 100644
--- a/engines/tony/window.cpp
+++ b/engines/tony/window.cpp
@@ -53,9 +53,9 @@ RMWindow::~RMWindow() {
* Initializes the graphics window
*/
void RMWindow::init() {
- Graphics::PixelFormat pixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
initGraphics(RM_SX, RM_SY, true, &pixelFormat);
-
+
reset();
}
@@ -83,7 +83,7 @@ void RMWindow::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w,
for (int i = 0; i < h; i++) {
uint16 *dst = (uint16 *)screen->getBasePtr(x, y + i);
for (int j = 0; j < w; j++) {
- dst[j] = RMGfxTargetBuffer::_precalcTable[src[j] & 0x7FFF];
+ dst[j] = RMGfxTargetBuffer::_precalcTable[src[j]];
}
src += (pitch / 2);
}
@@ -291,8 +291,8 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) {
cursrc = &src[RM_SKIPX + x];
*curOut++ = ((*cursrc) & 0x1F) << 3;
- *curOut++ = (((*cursrc) >> 5) & 0x1F) << 3;
- *curOut++ = (((*cursrc) >> 10) & 0x1F) << 3;
+ *curOut++ = (((*cursrc) >> 5) & 0x3F) << 3;
+ *curOut++ = (((*cursrc) >> 11) & 0x1F) << 3;
if (lpDestBuf)
*lpDestBuf++ = *cursrc;
@@ -319,8 +319,8 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) {
curv = v;
sommab += cursrc[curv * RM_BBX + u] & 0x1F;
- sommag += (cursrc[curv * RM_BBX + u] >> 5) & 0x1F;
- sommar += (cursrc[curv * RM_BBX + u] >> 10) & 0x1F;
+ sommag += (cursrc[curv * RM_BBX + u] >> 6) & 0x1F;
+ sommar += (cursrc[curv * RM_BBX + u] >> 11) & 0x1F;
}
}
_rgb[k + 0] = (byte)(sommab * 8 / (dezoom * dezoom));
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index 51e8dee19f..686fe99beb 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -1059,7 +1059,7 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
_specialAnim->loadAnimation(animName);
_animSpecialId = animId;
-
+
if (_animationInstance) {
_animationInstance->setAnimation(_specialAnim);
_animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1);
diff --git a/engines/toon/state.cpp b/engines/toon/state.cpp
index 6ac5808219..000f94d659 100644
--- a/engines/toon/state.cpp
+++ b/engines/toon/state.cpp
@@ -115,7 +115,7 @@ State::State(void) {
#endif
memset(_conversationState, 0, sizeof(Conversation) * 60);
-
+
_conversationData = nullptr;
_currentConversationId = -1;
_exitConversation = true;
diff --git a/engines/tsage/ringworld2/ringworld2_outpost.cpp b/engines/tsage/ringworld2/ringworld2_outpost.cpp
index 05cfa6259b..cad21b4623 100644
--- a/engines/tsage/ringworld2/ringworld2_outpost.cpp
+++ b/engines/tsage/ringworld2/ringworld2_outpost.cpp
@@ -4605,7 +4605,7 @@ void Scene1337::subD1940(bool flag) {
}
void Scene1337::subD1975(int arg1, int arg2) {
- // No implementation required in ScummVM: Mouse handling with tons of caching
+ // No implementation required in ScummVM: Mouse handling with tons of caching
}
void Scene1337::OptionsDialog::show() {
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index 9eaead630b..8610e0c8bc 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -3878,7 +3878,7 @@ void Scene3500::dispatch() {
Scene::dispatch();
// WORKAROUND: The _mazeUI wasn't originally added to the scene in postInit.
- // This is only needed to fix old savegames
+ // This is only needed to fix old savegames
if (!R2_GLOBALS._sceneObjects->contains(&_mazeUI))
_mazeUI.draw();
diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp
index 7c2e9c8468..2166a3e070 100644
--- a/engines/wintermute/base/base_engine.cpp
+++ b/engines/wintermute/base/base_engine.cpp
@@ -61,10 +61,11 @@ BaseEngine::~BaseEngine() {
delete _classReg;
}
-void BaseEngine::createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang) {
+void BaseEngine::createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang, WMETargetExecutable targetExecutable) {
instance()._targetName = targetName;
instance()._gameId = gameId;
instance()._language = lang;
+ instance()._targetExecutable = targetExecutable;
instance().init();
}
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index dd82cf9c29..0f4a6b0775 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -34,6 +34,8 @@
#include "common/random.h"
#include "common/language.h"
+#include "engines/wintermute/game_description.h"
+
namespace Wintermute {
class BaseFileManager;
@@ -53,10 +55,12 @@ class BaseEngine : public Common::Singleton<Wintermute::BaseEngine> {
Common::RandomSource *_rnd;
SystemClassRegistry *_classReg;
Common::Language _language;
+ WMETargetExecutable _targetExecutable;
public:
BaseEngine();
~BaseEngine();
- static void createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang);
+ static void createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang, WMETargetExecutable targetExecutable = LATEST_VERSION);
+
void setGameRef(BaseGame *gameRef) { _gameRef = gameRef; }
Common::RandomSource *getRandomSource() { return _rnd; }
@@ -73,6 +77,9 @@ public:
const char *getGameTargetName() const { return _targetName.c_str(); }
Common::String getGameId() const { return _gameId; }
Common::Language getLanguage() const { return _language; }
+ WMETargetExecutable getTargetExecutable() const {
+ return _targetExecutable;
+ }
};
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 8df39c825a..668053bb3a 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -3896,6 +3896,11 @@ void BaseGame::expandStringByStringTable(char **str) const {
_settings->expandStringByStringTable(str);
}
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::expandStringByStringTable(Common::String &str) const {
+ _settings->expandStringByStringTable(str);
+}
+
char *BaseGame::getKeyFromStringTable(const char *str) const {
return _settings->getKeyFromStringTable(str);
}
diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h
index cdbbff6c93..e535cc9618 100644
--- a/engines/wintermute/base/base_game.h
+++ b/engines/wintermute/base/base_game.h
@@ -123,6 +123,7 @@ public:
inline BaseObject *getMainObject() { return _mainObject; }
inline BaseFont *getSystemFont() { return _systemFont; }
+ inline BaseFont *getVideoFont() { return _videoFont; }
bool initInput();
bool initLoop();
@@ -140,6 +141,7 @@ public:
// String Table
void expandStringByStringTable(char **str) const;
+ void expandStringByStringTable(Common::String &str) const;
char *getKeyFromStringTable(const char *str) const;
void LOG(bool res, const char *fmt, ...);
diff --git a/engines/wintermute/base/base_game_settings.cpp b/engines/wintermute/base/base_game_settings.cpp
index 61c5894be3..996bada997 100644
--- a/engines/wintermute/base/base_game_settings.cpp
+++ b/engines/wintermute/base/base_game_settings.cpp
@@ -215,6 +215,11 @@ void BaseGameSettings::expandStringByStringTable(char **str) const {
_stringTable->expand(str);
}
+//////////////////////////////////////////////////////////////////////////
+void BaseGameSettings::expandStringByStringTable(Common::String &str) const {
+ _stringTable->expand(str);
+}
+
char *BaseGameSettings::getKeyFromStringTable(const char *str) const {
return _stringTable->getKey(str);
}
diff --git a/engines/wintermute/base/base_game_settings.h b/engines/wintermute/base/base_game_settings.h
index 2059cb075e..15afb06450 100644
--- a/engines/wintermute/base/base_game_settings.h
+++ b/engines/wintermute/base/base_game_settings.h
@@ -46,6 +46,7 @@ public:
bool loadSettings(const char *filename);
bool loadStringTable(const char *filename, bool clearOld);
void expandStringByStringTable(char **str) const;
+ void expandStringByStringTable(Common::String &str) const;
char *getKeyFromStringTable(const char *str) const;
bool persist(BasePersistenceManager *persistMgr);
diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp
index 61087c5836..0babc07586 100644
--- a/engines/wintermute/base/base_keyboard_state.cpp
+++ b/engines/wintermute/base/base_keyboard_state.cpp
@@ -278,10 +278,24 @@ uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) {
enum VKeyCodes {
kVkEscape = 27,
kVkSpace = 32,
+ kVkHome = 36,
kVkLeft = 37,
kVkUp = 38,
kVkRight = 39,
- kVkDown = 40
+ kVkDown = 40,
+
+ kVkF1 = 112,
+ kVkF2 = 113,
+ kVkF3 = 114,
+ kVkF4 = 115,
+ kVkF5 = 116,
+ kVkF6 = 117,
+ kVkF7 = 118,
+ kVkF8 = 119,
+ kVkF9 = 120,
+ kVkF10 = 121,
+ kVkF11 = 122,
+ kVkF12 = 123
};
//////////////////////////////////////////////////////////////////////////
@@ -290,22 +304,42 @@ Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) {
switch (vkey) {
case kVkEscape:
return Common::KEYCODE_ESCAPE;
- break;
case kVkSpace:
return Common::KEYCODE_SPACE;
- break;
+ case kVkHome:
+ return Common::KEYCODE_HOME;
case kVkLeft:
return Common::KEYCODE_LEFT;
- break;
case kVkRight:
return Common::KEYCODE_RIGHT;
- break;
case kVkUp:
return Common::KEYCODE_UP;
- break;
case kVkDown:
return Common::KEYCODE_DOWN;
- break;
+ case kVkF1:
+ return Common::KEYCODE_F1;
+ case kVkF2:
+ return Common::KEYCODE_F2;
+ case kVkF3:
+ return Common::KEYCODE_F3;
+ case kVkF4:
+ return Common::KEYCODE_F4;
+ case kVkF5:
+ return Common::KEYCODE_F5;
+ case kVkF6:
+ return Common::KEYCODE_F6;
+ case kVkF7:
+ return Common::KEYCODE_F7;
+ case kVkF8:
+ return Common::KEYCODE_F8;
+ case kVkF9:
+ return Common::KEYCODE_F9;
+ case kVkF10:
+ return Common::KEYCODE_F10;
+ case kVkF11:
+ return Common::KEYCODE_F11;
+ case kVkF12:
+ return Common::KEYCODE_F12;
default:
warning("Unknown VKEY: %d", vkey);
return (Common::KeyCode)vkey;
diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp
index 04060bff32..09e138a1fd 100644
--- a/engines/wintermute/base/base_sprite.cpp
+++ b/engines/wintermute/base/base_sprite.cpp
@@ -41,6 +41,7 @@
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/game_description.h"
namespace Wintermute {
@@ -347,9 +348,17 @@ void BaseSprite::reset() {
} else {
_currentFrame = -1;
}
-
- killAllSounds();
-
+ if (BaseEngine::instance().getTargetExecutable() >= WME_1_8_6) {
+ /*
+ * This was added in WME 1.8.6
+ *
+ * 5MA and possibly other games ship with pre-1.8.6 WME, and
+ * depends (e.g.: menu sounds, etc) on this not being triggered.
+ *
+ * See bug #6647
+ */
+ killAllSounds();
+ }
_lastFrameTime = 0;
_finished = false;
_moveX = _moveY = 0;
diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp
index 89407a7b0e..4c750ebc93 100644
--- a/engines/wintermute/base/base_string_table.cpp
+++ b/engines/wintermute/base/base_string_table.cpp
@@ -147,6 +147,15 @@ void BaseStringTable::expand(char **str) const {
}
}
+//////////////////////////////////////////////////////////////////////////
+void BaseStringTable::expand(Common::String &str) const {
+ char *tmp = new char[str.size()+1];
+ strcpy(tmp, str.c_str());
+ expand(&tmp);
+ str = tmp;
+ delete[] tmp;
+}
+
//////////////////////////////////////////////////////////////////////////
const char *BaseStringTable::expandStatic(const char *string) const {
diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h
index cdcf11917d..cfa3eeb226 100644
--- a/engines/wintermute/base/base_string_table.h
+++ b/engines/wintermute/base/base_string_table.h
@@ -41,6 +41,7 @@ class BaseStringTable : public BaseClass {
public:
bool loadFile(const char *filename, bool deleteAll = true);
void expand(char **str) const;
+ void expand(Common::String &str) const;
const char *expandStatic(const char *string) const;
bool addString(const char *key, const char *val, bool reportDuplicities = true);
BaseStringTable(BaseGame *inGame);
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index a659c434d0..aca682ae99 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -74,7 +74,7 @@ static const char *directoryGlobs[] = {
class WintermuteMetaEngine : public AdvancedMetaEngine {
public:
- WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(ADGameDescription), Wintermute::wintermuteGames, gameGuiOptions) {
+ WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(WMEGameDescription), Wintermute::wintermuteGames, gameGuiOptions) {
_singleid = "wintermute";
_guioptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS);
_maxScanDepth = 2;
@@ -127,8 +127,8 @@ public:
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
assert(syst);
assert(engine);
-
- *engine = new Wintermute::WintermuteEngine(syst, desc);
+ const WMEGameDescription *gd = (const WMEGameDescription *)desc;
+ *engine = new Wintermute::WintermuteEngine(syst, gd);
return true;
}
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 8206ca9643..4e3320159a 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -90,1342 +90,458 @@ static const PlainGameDescriptor wintermuteGames[] = {
{0, 0}
};
-static const ADGameDescription gameDescriptions[] = {
+// Duplicates WME_ENTRY1s, for consistency
+#define WME_ENTRY1s(f1, h1, s1) { {f1, 0, h1, s1}, AD_LISTEND }
+#define WME_ENTRY2s(f1, h1, s1, f2, h2, s2) { {f1, 0, h1, s1}, {f2, 0, h2, s2}, AD_LISTEND }
+#define WME_ENTRY3s(f1, h1, s1, f2, h2, s2, f3, h3, s3) { {f1, 0, h1, s1}, {f2, 0, h2, s2}, {f3, 0, h3, s3}, AD_LISTEND }
+
+#define WME_PLATENTRY(shortName, extraName, hashEntry, lang, plat, status, version) \
+ { \
+ { \
+ shortName, \
+ extraName, \
+ hashEntry, \
+ lang, \
+ plat, \
+ status, \
+ GUIO0(), \
+ }, \
+ version \
+ }
+
+// Convenience variant, as most of the games are Windows-games
+#define WME_WINENTRY(shortName, extraName, hashEntry, lang, status, version) \
+ { \
+ { \
+ shortName, \
+ extraName, \
+ hashEntry, \
+ lang, \
+ Common::kPlatformWindows, \
+ status, \
+ GUIO0(), \
+ }, \
+ version \
+ }
+
+/* To add new entries:
+ * Make sure you have a target name defined at the top of the file
+ *
+ * If the game has only one language, and can be detected using only one file,
+ * then use WME_WINENTRY, with WME_ENTRY1s as exemplified below.
+ *
+ * If the game has more than one language, and the main data file is common across
+ * the versions, then you should use WME_WINENTRY with WME_ENTRY2s/WME_ENTRY3s, with
+ * the language file as the first hit, and the data file as the second. (Make sure to
+ * NOT create a WME_ENTRY1s matching the same data file as the 2/3 file match)
+ */
+
+static const WMEGameDescription gameDescriptions[] = {
// Five Lethal Demons
- {
- "5ld",
- "",
- AD_ENTRY1s("data.dcp", "1037a77cbd001e0644898addc022322c", 15407750),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("5ld", "",
+ WME_ENTRY1s("data.dcp", "1037a77cbd001e0644898addc022322c", 15407750), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Five Magical Amulets
- {
- "5ma",
- "",
- AD_ENTRY1s("data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("5ma", "",
+ WME_ENTRY1s("data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498), Common::EN_ANY, ADGF_UNSTABLE, WME_1_7_0),
// Actual Destination
- {
- "actualdest",
- "",
- AD_ENTRY1s("data.dcp", "6926f44b26f21ceb1d840eaab9aeb510", 9081740),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("actualdest", "",
+ WME_ENTRY1s("data.dcp", "6926f44b26f21ceb1d840eaab9aeb510", 9081740), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Boredom of Agustin Cordes
- {
- "agustin",
- "",
- AD_ENTRY1s("data.dcp", "abb79c16c9b92e9b06525a4c7c3f5861", 2461949),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("agustin", "",
+ WME_ENTRY1s("data.dcp", "abb79c16c9b92e9b06525a4c7c3f5861", 2461949), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Beyond the Threshold
- {
- "bthreshold",
- "",
- AD_ENTRY1s("data.dcp", "d49bf9ccb2e74507447c82d6ad3e2bc4", 12773712),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("bthreshold", "",
+ WME_ENTRY1s("data.dcp", "d49bf9ccb2e74507447c82d6ad3e2bc4", 12773712), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Bickadoodle
- {
- "bickadoodle",
- "",
- AD_ENTRY1s("data.dcp", "84db4d1594cac95e25614985775d10a8", 35303844),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("bickadoodle", "",
+ WME_ENTRY1s("data.dcp", "84db4d1594cac95e25614985775d10a8", 35303844), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Bickadoodle (Ver 1.1)
- {
- "bickadoodle",
- "Version 1.1",
- AD_ENTRY1s("data.dcp", "8bb52ac9a9ee129c5059e8e808b669d7", 35337760),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("bickadoodle", "Version 1.1",
+ WME_ENTRY1s("data.dcp", "8bb52ac9a9ee129c5059e8e808b669d7", 35337760), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ // Bickadoodle (Ver 1.2)
+ WME_WINENTRY("bickadoodle", "Version 1.2",
+ WME_ENTRY1s("data.dcp", "1796a48f3ed72dd785ce93334ab883cc", 35337760), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Bickadoodle (download from http://aethericgames.com/games/bickadoodle/download-bickadoodle/)
- {
- "bickadoodle",
- "",
- AD_ENTRY1s("data.dcp", "1584d83577c32add0fce27fae91141a2", 35337728),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("bickadoodle", "",
+ WME_ENTRY1s("data.dcp", "1584d83577c32add0fce27fae91141a2", 35337728), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Book of Gron Part One
- {
- "bookofgron",
- "",
- AD_ENTRY1s("data.dcp", "e61b2ebee044a82fa0f8ca0fce2c8946", 83129531),
- Common::RU_RUS,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("bookofgron", "",
+ WME_ENTRY1s("data.dcp", "e61b2ebee044a82fa0f8ca0fce2c8946", 83129531), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 4 - East Side Story (Demo)
- {
- "carolreed4",
- "Demo",
- AD_ENTRY1s("data.dcp", "b3f8b09bb4b05ee3e9d14697525257f9", 59296246),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("carolreed4", "Demo",
+ WME_ENTRY1s("data.dcp", "b3f8b09bb4b05ee3e9d14697525257f9", 59296246), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Carol Reed 4 - East Side Story
- {
- "carolreed4",
- "",
- AD_ENTRY1s("data.dcp", "b26377797f060afc2d440d820100c1ce", 529320536),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("carolreed4", "",
+ WME_ENTRY1s("data.dcp", "b26377797f060afc2d440d820100c1ce", 529320536), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Carol Reed 5 - The Colour of Murder
- {
- "carolreed5",
- "",
- AD_ENTRY1s("data.dcp", "3fcfca44209545d0e26774156427b494", 603660415),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("carolreed5", "",
+ WME_ENTRY1s("data.dcp", "3fcfca44209545d0e26774156427b494", 603660415), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 6 - Black Circle
- {
- "carolreed6",
- "",
- AD_ENTRY1s("data.dcp", "0e4c532beecf23d85012168753f41189", 456258147),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("carolreed6", "",
+ WME_ENTRY1s("data.dcp", "0e4c532beecf23d85012168753f41189", 456258147), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 7 - Blue Madonna (Demo)
- {
- "carolreed7",
- "Demo",
- AD_ENTRY1s("data.dcp", "0372ad0c775266f6355e9e8ae397a2f1", 103719442),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("carolreed7", "Demo",
+ WME_ENTRY1s("data.dcp", "0372ad0c775266f6355e9e8ae397a2f1", 103719442), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Carol Reed 7 - Blue Madonna
- {
- "carolreed7",
- "",
- AD_ENTRY1s("data.dcp", "24e3db3e2fabfc956713796d87a3efb0", 495471147),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("carolreed7", "",
+ WME_ENTRY1s("data.dcp", "24e3db3e2fabfc956713796d87a3efb0", 495471147), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 8 - Amber's Blood
- {
- "carolreed8",
- "",
- AD_ENTRY1s("data.dcp", "859d16b0d5b9b255e470cbded2c6cedc", 502714557),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("carolreed8", "",
+ WME_ENTRY1s("data.dcp", "859d16b0d5b9b255e470cbded2c6cedc", 502714557), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 9 - Cold Case Summer
- {
- "carolreed9",
- "",
- AD_ENTRY1s("data.dcp", "2b343b48a7aee508d728a546b414a255", 620005266),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("carolreed9", "",
+ WME_ENTRY1s("data.dcp", "2b343b48a7aee508d728a546b414a255", 620005266), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Chivalry is Not Dead
- {
- "chivalry",
- "",
- AD_ENTRY1s("data.dcp", "ebd0915d9a12df5224be22f53bb23eb6", 7278306),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_TESTING,
- GUIO0()
- },
+ WME_WINENTRY("chivalry", "",
+ WME_ENTRY1s("data.dcp", "ebd0915d9a12df5224be22f53bb23eb6", 7278306), Common::EN_ANY, ADGF_TESTING, LATEST_VERSION),
// Chivalry is Not Dead (Version from deirdrakai.com)
- {
- "chivalry",
- "",
- AD_ENTRY1s("data.dcp", "ae6d91b9517f4d2851a8ad94c96951c8", 7278302),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_TESTING,
- GUIO0()
- },
+ WME_WINENTRY("chivalry", "",
+ WME_ENTRY1s("data.dcp", "ae6d91b9517f4d2851a8ad94c96951c8", 7278302), Common::EN_ANY, ADGF_TESTING, LATEST_VERSION),
// Conspiracao Dumont
- {
- "conspiracao",
- "",
- AD_ENTRY1s("ConspiracaoDumont.exe", "106f3f2c8f18bb5ffffeed634ace256c", 32908032),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("conspiracao", "",
+ WME_ENTRY1s("ConspiracaoDumont.exe", "106f3f2c8f18bb5ffffeed634ace256c", 32908032), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Corrosion: Cold Winter Waiting
- {
- "corrosion",
- "",
- AD_ENTRY1s("data.dcp", "ae885b1a8faa0b27f43c0e8f0df02fc9", 525931618),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_TESTING,
- GUIO0()
- },
+ WME_WINENTRY("corrosion", "",
+ WME_ENTRY1s("data.dcp", "ae885b1a8faa0b27f43c0e8f0df02fc9", 525931618), Common::EN_ANY, ADGF_TESTING, LATEST_VERSION),
// Dead City (Czech)
- {
- "deadcity",
- "",
- {
- // The Czech data are in data.dcp, so in this case we'll have to
- // just detect the english version twice, to give the user a choice.
- {"english.dcp", 0, "c591046d6de7e381d76f70e0787b2b1f", 415935},
- {"data.dcp", 0, "7ebfd50d1a22370ed7b079bcaa631d62", 9070205},
- AD_LISTEND
- },
- Common::CZ_CZE,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ // The Czech data are in data.dcp, so in this case we'll have to
+ // just detect the english version twice, to give the user a choice.
+ WME_WINENTRY("deadcity", "",
+ WME_ENTRY2s("english.dcp", "c591046d6de7e381d76f70e0787b2b1f", 415935,
+ "data.dcp", "7ebfd50d1a22370ed7b079bcaa631d62", 9070205), Common::CZ_CZE, ADGF_UNSTABLE, LATEST_VERSION),
// Dead City (English)
- {
- "deadcity",
- "",
- {
- {"english.dcp", 0, "c591046d6de7e381d76f70e0787b2b1f", 415935},
- {"data.dcp", 0, "7ebfd50d1a22370ed7b079bcaa631d62", 9070205},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("deadcity", "",
+ WME_ENTRY2s("english.dcp", "c591046d6de7e381d76f70e0787b2b1f", 415935,
+ "data.dcp", "7ebfd50d1a22370ed7b079bcaa631d62", 9070205), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Dead City (Italian)
- {
- "deadcity",
- "",
- {
- {"italian.dcp", 0, "92d8efb94436bec7bd1b7fe0b548192e", 454037},
- {"data.dcp", 0, "7ebfd50d1a22370ed7b079bcaa631d62", 9070205},
- AD_LISTEND
- },
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("deadcity", "",
+ WME_ENTRY2s("italian.dcp", "92d8efb94436bec7bd1b7fe0b548192e", 454037,
+ "data.dcp", "7ebfd50d1a22370ed7b079bcaa631d62", 9070205), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// Dead City (Russian)
- {
- "deadcity",
- "",
- {
- {"russian.dcp", 0, "a0ae71e9e1185596fffb07ad2c951eb9", 653317},
- {"data.dcp", 0, "7ebfd50d1a22370ed7b079bcaa631d62", 9070205},
- AD_LISTEND
- },
- Common::RU_RUS,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("deadcity", "",
+ WME_ENTRY2s("russian.dcp", "a0ae71e9e1185596fffb07ad2c951eb9", 653317,
+ "data.dcp", "7ebfd50d1a22370ed7b079bcaa631d62", 9070205), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (Czech)
- {
- "dirtysplit",
- "",
- {
- {"czech.dcp", 0, "08a71446467cf8f9444cfea446b46ad6", 127697934},
- {"data.dcp", 0, "8b4b81b718bf65f30a67fc0b1e329eb5", 88577623},
- },
- Common::CZ_CZE,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY2s("czech.dcp", "08a71446467cf8f9444cfea446b46ad6", 127697934,
+ "data.dcp", "8b4b81b718bf65f30a67fc0b1e329eb5", 88577623), Common::CZ_CZE, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (English)
- {
- "dirtysplit",
- "",
- AD_ENTRY1s("data.dcp", "8f3dae199361ece0f59fb20cfff6eed3", 88577621),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY1s("data.dcp", "8f3dae199361ece0f59fb20cfff6eed3", 88577621), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (French)
- {
- "dirtysplit",
- "",
- {
- {"french.dcp", 0, "a0508dedebd0fe478d0158fa4c2a1136", 125534323},
- {"data.dcp", 0, "e6d70c7f5d181b761cfcf974adf9186a", 88577623},
- AD_LISTEND
- },
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY2s("french.dcp", "a0508dedebd0fe478d0158fa4c2a1136", 125534323,
+ "data.dcp", "e6d70c7f5d181b761cfcf974adf9186a", 88577623), Common::FR_FRA, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (German)
- {
- "dirtysplit",
- "",
- AD_ENTRY1s("data.dcp", "139d8a25579e969f8b37d20e6e3de5f9", 92668291),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY1s("data.dcp", "139d8a25579e969f8b37d20e6e3de5f9", 92668291), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (Italian)
- {
- "dirtysplit",
- "",
- {
- {"italian.dcp", 0, "8108807fbd8af70be1ec452d0fd1131b", 125513726},
- {"data.dcp", 0, "35a150e22af274185883fdbb142c6fb1", 88577623},
- },
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY2s("italian.dcp", "8108807fbd8af70be1ec452d0fd1131b", 125513726,
+ "data.dcp", "35a150e22af274185883fdbb142c6fb1", 88577623), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// Dirty Split (Spanish)
- {
- "dirtysplit",
- "",
- {
- {"spanish.dcp", 0, "b3982c0a5e85b42e1e38240fef004aa4", 164428596},
- {"data.dcp", 0, "63766d6c68b9f00b632ea1736fc8a95c", 88577621},
- },
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dirtysplit", "",
+ WME_ENTRY2s("spanish.dcp", "b3982c0a5e85b42e1e38240fef004aa4", 164428596,
+ "data.dcp", "63766d6c68b9f00b632ea1736fc8a95c", 88577621), Common::ES_ESP, ADGF_UNSTABLE, LATEST_VERSION),
// Des Reves Elastiques Avec Mille Insectes Nommes Georges
- {
- "dreaming",
- "",
- AD_ENTRY1s("data.dcp", "4af26d97ea063fc1277ce30ae431de90", 8804073),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dreaming", "",
+ WME_ENTRY1s("data.dcp", "4af26d97ea063fc1277ce30ae431de90", 8804073), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Dreamscape
- {
- "dreamscape",
- "",
- AD_ENTRY1s("data.dcp", "7a5752ed4446c862be9f02d7932acf54", 17034377),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("dreamscape", "",
+ WME_ENTRY1s("data.dcp", "7a5752ed4446c862be9f02d7932acf54", 17034377), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Escape from the Mansion
- {
- "escapemansion",
- "Beta 1",
- AD_ENTRY1s("data.dcp", "d8e348b2312cc36a929cad75f12e0b3a", 21452380),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("escapemansion", "Beta 1",
+ WME_ENTRY1s("data.dcp", "d8e348b2312cc36a929cad75f12e0b3a", 21452380), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Escape from the Mansion
- {
- "escapemansion",
- "Beta 2",
- AD_ENTRY1s("data.dcp", "ded5fa6c5f2afdaf2cafb53e52cd3dd8", 21455763),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("escapemansion", "Beta 2",
+ WME_ENTRY1s("data.dcp", "ded5fa6c5f2afdaf2cafb53e52cd3dd8", 21455763), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Escape from the Mansion
- {
- "escapemansion",
- "1.3",
- AD_ENTRY1s("data.dcp", "1e5d231b56c8a228cd15cb690f50253e", 29261972),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("escapemansion", "1.3",
+ WME_ENTRY1s("data.dcp", "1e5d231b56c8a228cd15cb690f50253e", 29261972), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Four
- {
- "four",
- "",
- AD_ENTRY1s("data.dcp", "ec05cd5e37c9a524053b8859635a4234", 62599855),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("four", "",
+ WME_ENTRY1s("data.dcp", "ec05cd5e37c9a524053b8859635a4234", 62599855), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Framed
- {
- "framed",
- "",
- AD_ENTRY1s("data.dcp", "e7259fb36f2c6f9f28242291e0c3de98", 34690568),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("framed", "",
+ WME_ENTRY1s("data.dcp", "e7259fb36f2c6f9f28242291e0c3de98", 34690568), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Ghost in the Sheet
- {
- "ghostsheet",
- "",
- {
- {"english.dcp", 0, "e6d0aad2c89996bcabe416105a3d6d3a", 12221017},
- {"data.dcp", 0, "b2f8b05328e4881e15e98e845b63f451", 168003},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("ghostsheet", "",
+ WME_ENTRY2s("english.dcp", "e6d0aad2c89996bcabe416105a3d6d3a", 12221017,
+ "data.dcp", "b2f8b05328e4881e15e98e845b63f451", 168003), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Ghost in the Sheet (Demo)
- {
- "ghostsheet",
- "Demo",
- AD_ENTRY1s("data.dcp", "dc1f6595f412ac25a52eaf47dad4ab81", 169083),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("ghostsheet", "Demo",
+ WME_ENTRY1s("data.dcp", "dc1f6595f412ac25a52eaf47dad4ab81", 169083), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Hamlet or the last game without MMORPS features, shaders and product placement
- {
- "hamlet",
- "",
- AD_ENTRY1s("data.dcp", "f624add957a77c9930529fb28cc2450f", 88183022),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("hamlet", "",
+
+ WME_ENTRY1s("data.dcp", "f624add957a77c9930529fb28cc2450f", 88183022), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Helga Deep In Trouble (English)
- {
- "helga",
- "",
- {
- {"english.dcp", 0, "bfa136b21bdbc7d8691c0770a6d40bc3", 135931},
- {"data.dcp", 0, "25cb955a60b58326f2eeda1ce288fb37", 183251259},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("helga", "",
+ WME_ENTRY2s("english.dcp", "bfa136b21bdbc7d8691c0770a6d40bc3", 135931,
+ "data.dcp", "25cb955a60b58326f2eeda1ce288fb37", 183251259), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Helga Deep In Trouble (Demo) (English)
- {
- "helga",
- "Demo",
- {
- {"english.dcp", 0, "b3a93e678f0ef97200f691cd1724643f", 135864},
- {"data.dcp", 0, "45134ed93bc391edf148b79cdcbf2a09", 154266028},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("helga", "Demo",
+ WME_ENTRY2s("english.dcp", "b3a93e678f0ef97200f691cd1724643f", 135864,
+ "data.dcp", "45134ed93bc391edf148b79cdcbf2a09", 154266028), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// James Peris: No License Nor Control (English)
- {
- "jamesperis",
- "",
- AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("jamesperis", "",
+ WME_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// James Peris: No License Nor Control (Spanish)
- {
- "jamesperis",
- "",
- AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("jamesperis", "",
+ WME_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032), Common::ES_ESP, ADGF_UNSTABLE, LATEST_VERSION),
// James Peris: No License Nor Control (Demo) (English)
- {
- "jamesperis",
- "Demo",
- AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("jamesperis", "Demo",
+ WME_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// James Peris: No License Nor Control (Demo) (Spanish)
- {
- "jamesperis",
- "Demo",
- AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("jamesperis", "Demo",
+ WME_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507), Common::ES_ESP, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// J.U.L.I.A. (English)
- {
- "julia",
- "",
- AD_ENTRY1s("data.dcp", "c2264b4f8fcd132d2913ff5b6076a24f", 10109741),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("julia", "",
+ WME_ENTRY1s("data.dcp", "c2264b4f8fcd132d2913ff5b6076a24f", 10109741), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// J.U.L.I.A. (English, Bundle in a box-version)
- {
- "julia",
- "Version 1.2",
- AD_ENTRY1s("data.dcp", "fe90023ccc22f35185b40b910e0d03a2", 10101373),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("julia", "Version 1.2",
+ WME_ENTRY1s("data.dcp", "fe90023ccc22f35185b40b910e0d03a2", 10101373), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// J.U.L.I.A. (English) (Demo)
- {
- "julia",
- "Demo",
- AD_ENTRY1s("data.dcp", "f0bbc3394555a9811f6050dae428cab6", 7655237),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("julia", "Demo",
+ WME_ENTRY1s("data.dcp", "f0bbc3394555a9811f6050dae428cab6", 7655237), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// J.U.L.I.A. (English) (Greenlight Demo)
- {
- "julia",
- "Greenlight Demo",
- AD_ENTRY1s("data.dcp", "4befd448d36b0dae9c3ab1aa7cb8b78d", 7271886),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("julia", "Greenlight Demo",
+ WME_ENTRY1s("data.dcp", "4befd448d36b0dae9c3ab1aa7cb8b78d", 7271886), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Kulivocko (Czech)
- {
- "kulivocko",
- "",
- AD_ENTRY1s("data.dcp", "44306dc470e9b27474043932eccee02f", 155106392),
- Common::CZ_CZE,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("kulivocko", "",
+ WME_ENTRY1s("data.dcp", "44306dc470e9b27474043932eccee02f", 155106392), Common::CZ_CZE, ADGF_UNSTABLE, LATEST_VERSION),
// Kulivocko (Czech) (Demo)
- {
- "kulivocko",
- "Demo",
- AD_ENTRY1s("data.dcp", "63b164bdfadecbb0deb5da691afb8154", 48362234),
- Common::CZ_CZE,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("kulivocko", "Demo",
+ WME_ENTRY1s("data.dcp", "63b164bdfadecbb0deb5da691afb8154", 48362234), Common::CZ_CZE, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Life In 3 Minutes
- {
- "lifein3minutes",
- "",
- AD_ENTRY1s("data.dcp", "c6368950e37a95bf098b02b4eaa5b929", 141787214),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("lifein3minutes", "",
+ WME_ENTRY1s("data.dcp", "c6368950e37a95bf098b02b4eaa5b929", 141787214), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Looky Demo (English)
- {
- "looky",
- "Demo",
- {
- {"english.dcp", 0, "1388e1dd320f4d553dea3b0316812f9d", 1358442},
- {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("looky", "Demo",
+ WME_ENTRY2s("english.dcp", "1388e1dd320f4d553dea3b0316812f9d", 1358442,
+ "data.dcp", "7074bcd7bc7ad7eb04c271aafb964c32", 13815660), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Looky Demo (German)
- {
- "looky",
- "Demo",
- {
- {"german.dcp", 0, "606c048426dfbe94442b59fd34a5c76e", 14339496},
- {"data.dcp", 0, "7074bcd7bc7ad7eb04c271aafb964c32", 13815660},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("looky", "Demo",
+ WME_ENTRY2s("german.dcp", "606c048426dfbe94442b59fd34a5c76e", 14339496,
+ "data.dcp", "7074bcd7bc7ad7eb04c271aafb964c32", 13815660), Common::DE_DEU, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Looky (German)
- {
- "looky",
- "",
- {
- {"german.dcp", 0, "bf4c2b8c26342342441a6d64934ab832", 107027865},
- {"data.dcp", 0, "50de0beaa5ad621aa9f020df901d1e74", 1342214},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("looky", "",
+ WME_ENTRY2s("german.dcp", "bf4c2b8c26342342441a6d64934ab832", 107027865,
+ "data.dcp", "50de0beaa5ad621aa9f020df901d1e74", 1342214), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Mirage
- {
- "mirage",
- "",
- AD_ENTRY1s("data.dcp", "d230b0b99c0aa77b9ecd094d8ee5573b", 17844056),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("mirage", "",
+ WME_ENTRY1s("data.dcp", "d230b0b99c0aa77b9ecd094d8ee5573b", 17844056), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Oknytt
- {
- "oknytt",
- "Version 1.0",
- AD_ENTRY1s("data.dcp", "6456cf8f429905c83f07509f9da536dd", 109502959),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("oknytt", "Version 1.0",
+ WME_ENTRY1s("data.dcp", "6456cf8f429905c83f07509f9da536dd", 109502959), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Night Train Demo
- {
- "nighttrain",
- "",
- AD_ENTRY1s("data.dcp", "5a027ef84b083a730c9a4c85ec1d3a32", 131760816),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("nighttrain", "",
+ WME_ENTRY1s("data.dcp", "5a027ef84b083a730c9a4c85ec1d3a32", 131760816), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Paintaria
- {
- "paintaria",
- "",
- AD_ENTRY1s("data.dcp", "354c08440c98150ff0d4008dd2865880", 48326040),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("paintaria", "",
+ WME_ENTRY1s("data.dcp", "354c08440c98150ff0d4008dd2865880", 48326040), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Pigeons in the Park
- {
- "pigeons",
- "",
- AD_ENTRY1s("data.dcp", "9143a5b6ff8206aefe3c4c643add3ec7", 2611100),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("pigeons", "",
+ WME_ENTRY1s("data.dcp", "9143a5b6ff8206aefe3c4c643add3ec7", 2611100), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Project: Doom
- {
- "projectdoom",
- "",
- AD_ENTRY1s("data.dcp", "d5894b65a40706845434b99870bcab92", 99223761),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("projectdoom", "",
+ WME_ENTRY1s("data.dcp", "d5894b65a40706845434b99870bcab92", 99223761), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Project Joe
- {
- "projectjoe",
- "",
- AD_ENTRY1s("data.dcp", "ada3c08542901295076b5349e655e73f", 160780037),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("projectjoe", "",
+ WME_ENTRY1s("data.dcp", "ada3c08542901295076b5349e655e73f", 160780037), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Project Lonely Robot
- {
- "lonelyrobot",
- "beta",
- AD_ENTRY1s("data.dcp", "a0cf7ad5bab957416dcda454e9f28ef0", 3420120),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("lonelyrobot", "beta",
+ WME_ENTRY1s("data.dcp", "a0cf7ad5bab957416dcda454e9f28ef0", 3420120), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Reversion: The Escape Version 1.0
- {
- "reversion1",
- "Version 1.0",
- AD_ENTRY1s("data.dcp", "cd616f98ebfd047e0c540b50b4b70761", 254384531),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.0",
+ WME_ENTRY1s("data.dcp", "cd616f98ebfd047e0c540b50b4b70761", 254384531), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (Chinese)
- {
- "reversion1",
- "Version 1.1",
- {
- {"chinese.dcp", 0, "cf97150739499a4c15f51dc534ff85a1", 6330561},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::ZH_CNA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("chinese.dcp", "cf97150739499a4c15f51dc534ff85a1", 6330561,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::ZH_CNA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (English)
- {
- "reversion1",
- "Version 1.1",
- {
- {"english.dcp", 0, "7b2f061d7c91365c5d04605f1de032b3", 5702699},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("english.dcp", "7b2f061d7c91365c5d04605f1de032b3", 5702699,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (French)
- {
- "reversion1",
- "Version 1.1",
- {
- {"french.dcp", 0, "214204b6022c5ed67fada44557690faf", 6327400},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("french.dcp", "214204b6022c5ed67fada44557690faf", 6327400,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::FR_FRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (German)
- {
- "reversion1",
- "Version 1.1",
- {
- {"german.dcp", 0, "96677823b36d580a4a29e3659071071c", 6340699},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("german.dcp", "96677823b36d580a4a29e3659071071c", 6340699,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (Italian)
- {
- "reversion1",
- "Version 1.1",
- {
- {"italian.dcp", 0, "9ce80c1835108f10170a02969f71efe1", 6301836},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("italian.dcp", "9ce80c1835108f10170a02969f71efe1", 6301836,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.1 (Portuguese)
- {
- "reversion1",
- "Version 1.1",
- {
- {"portugues.dcp", 0, "8772501afa2c630a7c697eb99e9c7bda", 5053303},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::PT_BRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.1",
+ WME_ENTRY2s("portugues.dcp", "8772501afa2c630a7c697eb99e9c7bda", 5053303,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::PT_BRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (Chinese)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_nz.dcp", 0, "92c4065156e464211685bf799b3279fd", 5130600},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::ZH_CNA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_nz.dcp", "92c4065156e464211685bf799b3279fd", 5130600,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::ZH_CNA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (English)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_en.dcp", 0, "05845e1283920a6e4044f2a54f7a9519", 4818543},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_en.dcp", "05845e1283920a6e4044f2a54f7a9519", 4818543,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (French)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_fr.dcp", 0, "441795490e9307eb2ed07830779881ac", 5425959},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_fr.dcp", "441795490e9307eb2ed07830779881ac", 5425959,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::FR_FRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (German)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_de.dcp", 0, "b588041015b93e54b4c246ca77d01e76", 5423798},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_de.dcp", "b588041015b93e54b4c246ca77d01e76", 5423798,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (Italian)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_it.dcp", 0, "a1f4199079b75ee10cded41f05b45d5f", 5386424},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_it.dcp", "a1f4199079b75ee10cded41f05b45d5f", 5386424,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3 (Portuguese)
- {
- "reversion1",
- "Version 1.3",
- {
- {"xlanguage_pt.dcp", 0, "3d653debd37e56756a79401e1004c4d2", 4149165},
- {"data.dcp", 0, "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907},
- AD_LISTEND
- },
- Common::PT_BRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3",
+ WME_ENTRY2s("xlanguage_pt.dcp", "3d653debd37e56756a79401e1004c4d2", 4149165,
+ "data.dcp", "9ebb12f6fd7c038d079f81beb3bd96d5", 254185907), Common::PT_BRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (Chinese)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_nz.dcp", 0, "7146dfa43ffdf0886e034fffe2c8a0c0", 13722261},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::ZH_CNA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_nz.dcp", "7146dfa43ffdf0886e034fffe2c8a0c0", 13722261,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::ZH_CNA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (English)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_en.dcp", 0, "64b6fa7eedc09c231f6ce046e77fee05", 11339619},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_en.dcp", "64b6fa7eedc09c231f6ce046e77fee05", 11339619,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (French)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_fr.dcp", 0, "d561d562224afea809153a1fd9fdb0c0", 11963210},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_fr.dcp", "d561d562224afea809153a1fd9fdb0c0", 11963210,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::FR_FRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (German)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_de.dcp", 0, "4e3f614c36bd6bae74b8cc83e663a8f0", 14040310},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_de.dcp", "4e3f614c36bd6bae74b8cc83e663a8f0", 14040310,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (Italian)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_it.dcp", 0, "10d09b7fe61946f09dd91d5e8d090f94", 11913752},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_it.dcp", "10d09b7fe61946f09dd91d5e8d090f94", 11913752,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (Latvian)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_lv.dcp", 0, "704359ab5040b0dab6545064d7aa6eb9", 11414925},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::LV_LAT,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_lv.dcp", "704359ab5040b0dab6545064d7aa6eb9", 11414925,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::LV_LAT, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (Polish)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_pl.dcp", 0, "c4ad33f57e1e998169552d521c1d6638", 11532215},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::PL_POL,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_pl.dcp", "c4ad33f57e1e998169552d521c1d6638", 11532215,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::PL_POL, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Escape Version 1.3.2369 (Portuguese)
- {
- "reversion1",
- "Version 1.3.2369",
- {
- {"xlanguage_pt.dcp", 0, "886886b6b14aadac844078de856799a6", 10620797},
- {"data.dcp", 0, "aecb5deeea7b0baa871fbd0cef35a648", 254219204},
- AD_LISTEND
- },
- Common::PT_BRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion1", "Version 1.3.2369",
+ WME_ENTRY2s("xlanguage_pt.dcp", "886886b6b14aadac844078de856799a6", 10620797,
+ "data.dcp", "aecb5deeea7b0baa871fbd0cef35a648", 254219204), Common::PT_BRA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Meeting (Chinese)
- {
- "reversion2",
- "",
- {
- {"xlanguage_nz.dcp", 0, "8c3709474a87a7876109025dff41ff3f", 8746015},
- {"data.dcp", 0, "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032},
- AD_LISTEND
- },
- Common::ZH_CNA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion2", "",
+ WME_ENTRY2s("xlanguage_nz.dcp", "8c3709474a87a7876109025dff41ff3f", 8746015,
+ "data.dcp", "cb9865dc7e1db2990a8cf4bc13cf4999", 257643032), Common::ZH_CNA, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Meeting (English)
- {
- "reversion2",
- "",
- {
- {"xlanguage_en.dcp", 0, "ca357d86618d1ab76a21c913f4403cbd", 8414976},
- {"data.dcp", 0, "f7938cbfdc48f07934550245a3286921", 255672016},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion2", "",
+ WME_ENTRY2s("xlanguage_en.dcp", "ca357d86618d1ab76a21c913f4403cbd", 8414976,
+ "data.dcp", "f7938cbfdc48f07934550245a3286921", 255672016), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Meeting (Spanish)
- {
- "reversion2",
- "",
- AD_ENTRY1s("data.dcp", "f7938cbfdc48f07934550245a3286921", 255672016),
- Common::ES_ESP,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("reversion2", "",
+ WME_ENTRY1s("data.dcp", "f7938cbfdc48f07934550245a3286921", 255672016), Common::ES_ESP, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Meeting Version 2.0.2412 (Chinese)
- {
- "reversion2",
- "Version 2.0.2412",
- {
- {"data.dcp", 0, "f4ffc4df24b7bebad56a24930f33a2bc", 255766600},
- {"xlanguage_nz.dcp", 0, "17c79af4928e24484bee77a7e807cc2a", 10737127},
- {"Linux.dcp", 0, "21858bd77dc86b03f701fd47900e2f51", 984535},
- AD_LISTEND
- },
- Common::ZH_CNA,
- Common::kPlatformLinux,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_PLATENTRY("reversion2", "Version 2.0.2412",
+ WME_ENTRY3s("data.dcp", "f4ffc4df24b7bebad56a24930f33a2bc", 255766600,
+ "xlanguage_nz.dcp", "17c79af4928e24484bee77a7e807cc2a", 10737127,
+ "Linux.dcp", "21858bd77dc86b03f701fd47900e2f51", 984535), Common::ZH_CNA, Common::kPlatformLinux, ADGF_UNSTABLE, LATEST_VERSION),
// Reversion: The Meeting Version 2.0.2412 (English)
- {
- "reversion2",
- "Version 2.0.2412",
- {
- {"data.dcp", 0, "f4ffc4df24b7bebad56a24930f33a2bc", 255766600},
- {"xlanguage_en.dcp", 0, "0598bf752ce93b42bcaf1094df537c7b", 8533057},
- {"Linux.dcp", 0, "21858bd77dc86b03f701fd47900e2f51", 984535},
- AD_LISTEND
- },
- Common::EN_ANY,
- Common::kPlatformLinux,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_PLATENTRY("reversion2", "Version 2.0.2412",
+ WME_ENTRY3s("data.dcp", "f4ffc4df24b7bebad56a24930f33a2bc", 255766600,
+ "xlanguage_en.dcp", "0598bf752ce93b42bcaf1094df537c7b", 8533057,
+ "Linux.dcp", "21858bd77dc86b03f701fd47900e2f51", 984535), Common::EN_ANY, Common::kPlatformLinux, ADGF_UNSTABLE, LATEST_VERSION),
// Rhiannon: Curse of the four Branches
- {
- "rhiannon",
- "",
- AD_ENTRY1s("data.dcp", "870f348900b735f1cc79c0608ce32b0e", 1046169851),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("rhiannon", "",
+ WME_ENTRY1s("data.dcp", "870f348900b735f1cc79c0608ce32b0e", 1046169851), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Rhiannon: Curse of the four Branches (English PC DVD)
- {
- "rhiannon",
- "DVD",
- AD_ENTRY1s("data.dcp", "6736bbc921bb6ce5161b3ad095a97bd4", 1053441028),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("rhiannon", "DVD",
+ WME_ENTRY1s("data.dcp", "6736bbc921bb6ce5161b3ad095a97bd4", 1053441028), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// 1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde
- {
- "ritter",
- "",
- AD_ENTRY1s("data.dcp", "5ac416cee605d3a30f4d59687b1cdab2", 364260278),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("ritter", "",
+ WME_ENTRY1s("data.dcp", "5ac416cee605d3a30f4d59687b1cdab2", 364260278), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
// Satan and Son
- {
- "satanandson",
- "",
- AD_ENTRY1s("data.dcp", "16a6ba8174b697bbba9299619d1e20c4", 67539054),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("satanandson", "",
+ WME_ENTRY1s("data.dcp", "16a6ba8174b697bbba9299619d1e20c4", 67539054), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Rosemary
- {
- "rosemary",
- "",
- AD_ENTRY1s("data.dcp", "4f2631138bd4d27587d9043f8aeff3df", 29483643),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("rosemary", "",
+ WME_ENTRY1s("data.dcp", "4f2631138bd4d27587d9043f8aeff3df", 29483643), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Securanote
- {
- "securanote",
- "",
- AD_ENTRY1s("data.dcp", "5213d3e59b9e95b7fbd5c56f7de5341a", 2625554),
- Common::EN_ANY,
- Common::kPlatformIOS,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_PLATENTRY("securanote", "",
+ WME_ENTRY1s("data.dcp", "5213d3e59b9e95b7fbd5c56f7de5341a", 2625554), Common::EN_ANY, Common::kPlatformIOS, ADGF_UNSTABLE, LATEST_VERSION),
// Shaban
- {
- "shaban",
- "",
- AD_ENTRY1s("data.dcp", "35f702ca9baabc5c620e0be230195c8a", 755388466),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("shaban", "",
+ WME_ENTRY1s("data.dcp", "35f702ca9baabc5c620e0be230195c8a", 755388466), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Shine of a Star
- {
- "shinestar",
- "",
- AD_ENTRY1s("data.dcp", "f05abe9e2427a5e4f73648fa09c4ba8e", 94113060),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("shinestar", "",
+ WME_ENTRY1s("data.dcp", "f05abe9e2427a5e4f73648fa09c4ba8e", 94113060), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Sofia's Debt
- {
- "sofiasdebt",
- "",
- AD_ENTRY1s("SD.exe", "e9515f9ba1a2925bb6733476a826a650", 9915047),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("sofiasdebt", "",
+ WME_ENTRY1s("SD.exe", "e9515f9ba1a2925bb6733476a826a650", 9915047), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Space Invaders (Demo)
- {
- "spaceinvaders",
- "Demo",
- AD_ENTRY1s("data.dcp", "3f27adefdf72f2c1601cf555c80a509f", 1308361),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("spaceinvaders", "Demo",
+ WME_ENTRY1s("data.dcp", "3f27adefdf72f2c1601cf555c80a509f", 1308361), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Space Madness
- {
- "spacemadness",
- "1.0.2",
- AD_ENTRY1s("data.dcp", "b9b83135dc7a9e1b4b5f50195dbeb630", 39546622),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("spacemadness", "1.0.2",
+ WME_ENTRY1s("data.dcp", "b9b83135dc7a9e1b4b5f50195dbeb630", 39546622), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Ancient Mark - Episode 1
- {
- "theancientmark1",
- "",
- AD_ENTRY1s("data.dcp", "ca04c26f03b2bd307368b306b297ddd7", 364664692),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("theancientmark1", "",
+ WME_ENTRY1s("data.dcp", "ca04c26f03b2bd307368b306b297ddd7", 364664692), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Box
- {
- "thebox",
- "",
- AD_ENTRY1s("data.dcp", "ec5f0c7e8174e307701447b53afe7e2f", 108372483),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thebox", "",
+ WME_ENTRY1s("data.dcp", "ec5f0c7e8174e307701447b53afe7e2f", 108372483), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Kite (Version 1.1)
- {
- "thekite",
- "Version 1.1",
- AD_ENTRY1s("data.dcp", "92d29428f464469bda2d81b03d4d5c3e", 47332296),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thekite", "Version 1.1",
+ WME_ENTRY1s("data.dcp", "92d29428f464469bda2d81b03d4d5c3e", 47332296), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Kite (Version 1.2.e)
- {
- "thekite",
- "Version 1.2.e",
- AD_ENTRY1s("data.dcp", "92451578b1bdd2b32a1db592a4f6d5fc", 47360539),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thekite", "Version 1.2.e",
+ WME_ENTRY1s("data.dcp", "92451578b1bdd2b32a1db592a4f6d5fc", 47360539), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// The Kite (Version 1.2.i) (Italian)
- {
- "thekite",
- "Version 1.2.i",
- AD_ENTRY1s("data.dcp", "d3435b106a1b3b4c1df8ad596d271586", 47509274),
- Common::IT_ITA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thekite", "Version 1.2.i",
+ WME_ENTRY1s("data.dcp", "d3435b106a1b3b4c1df8ad596d271586", 47509274), Common::IT_ITA, ADGF_UNSTABLE, LATEST_VERSION),
// The Kite (Version 1.2.r) (Russian)
- {
- "thekite",
- "Version 1.2.r",
- AD_ENTRY1s("data.dcp", "d531e097dd884737469da014ed882cde", 47554582 ),
- Common::RU_RUS,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thekite", "Version 1.2.r",
+ WME_ENTRY1s("data.dcp", "d531e097dd884737469da014ed882cde", 47554582 ), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
// The Kite (Version 1.3.e)
- {
- "thekite",
- "Version 1.3.e",
- AD_ENTRY1s("data.dcp", "9761827b51370263b7623721545d7627", 47382987),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("thekite", "Version 1.3.e",
+ WME_ENTRY1s("data.dcp", "9761827b51370263b7623721545d7627", 47382987), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Fairy Tales About Toshechka and Boshechka
- {
- "tib",
- "",
- AD_ENTRY1s("data.dcp", "87d296ef3f46570ed18f000d3885db77", 340264526),
- Common::RU_RUS,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("tib", "",
+ WME_ENTRY1s("data.dcp", "87d296ef3f46570ed18f000d3885db77", 340264526), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
// The Trader of Stories
- {
- "tradestory",
- "Demo",
- AD_ENTRY1s("data.dcp", "0a0b51191636cc8ead89b905281c3218", 40401902),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("tradestory", "Demo",
+ WME_ENTRY1s("data.dcp", "0a0b51191636cc8ead89b905281c3218", 40401902), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// the white chamber (multi-language)
- {
- "twc",
- "",
- AD_ENTRY1s("data.dcp", "0011d01142547c61e51ba24dc42b579e", 186451273),
- Common::UNK_LANG,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("twc", "",
+ WME_ENTRY1s("data.dcp", "0011d01142547c61e51ba24dc42b579e", 186451273), Common::UNK_LANG, ADGF_UNSTABLE, LATEST_VERSION),
// Vsevolod Prologue (Demo)
- {
- "vsevolod",
- "Prologue",
- AD_ENTRY1s("data.dcp", "f2dcffd2692dbfcc9371fa1a87970fe7", 388669493),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE |
- ADGF_DEMO,
- GUIO0()
- },
+ WME_WINENTRY("vsevolod", "Prologue",
+ WME_ENTRY1s("data.dcp", "f2dcffd2692dbfcc9371fa1a87970fe7", 388669493), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// War
- {
- "war",
- "",
- AD_ENTRY1s("data.dcp", "003e317cda6d0137bbd5e5d7f089ee4d", 32591890),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("war", "",
+ WME_ENTRY1s("data.dcp", "003e317cda6d0137bbd5e5d7f089ee4d", 32591890), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Wilma Tetris
- {
- "wtetris",
- "",
- AD_ENTRY1s("data.dcp", "946e3a0496e6c12fb344c9ed861ff015", 2780093),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
+ WME_WINENTRY("wtetris", "",
+ WME_ENTRY1s("data.dcp", "946e3a0496e6c12fb344c9ed861ff015", 2780093), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Zilm: A Game of Reflex 1.0
+ WME_WINENTRY("Zilm", "1.0",
+ WME_ENTRY1s("data.dcp", "098dffaf03d8adbb4cb5633e4733e63c", 351726), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
{
- "Zilm",
- "1.0",
- AD_ENTRY1s("data.dcp", "098dffaf03d8adbb4cb5633e4733e63c", 351726),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO0()
- },
- AD_TABLE_END_MARKER
+ AD_TABLE_END_MARKER,
+ LATEST_VERSION
+ }
};
} // End of namespace Wintermute
+#undef WEM_ENTRY1s
+#undef WEM_ENTRY2s
+#undef WEM_ENTRY3s
+#undef WME_WINENTRY
+#undef WME_PLATENTRY
+
diff --git a/engines/zvision/inventory/inventory_manager.h b/engines/wintermute/game_description.h
index f9d2ff294a..313fff8bbf 100644
--- a/engines/zvision/inventory/inventory_manager.h
+++ b/engines/wintermute/game_description.h
@@ -20,9 +20,34 @@
*
*/
-#ifndef ZVISION_INVENTORY_MANAGER_H
-#define ZVISION_INVENTORY_MANAGER_H
+#ifndef WINTERMUTE_GAME_DESCRIPTION_H
+#define WINTERMUTE_GAME_DESCRIPTION_H
-// TODO: Implement InventoryManager
+#include "engines/advancedDetector.h"
-#endif
+namespace Wintermute {
+
+enum WMETargetExecutable {
+ OLDEST_VERSION,
+ WME_1_0_0,
+ WME_1_1_0,
+ WME_1_2_0,
+ WME_1_3_0,
+ WME_1_4_0,
+ WME_1_5_0,
+ WME_1_6_0,
+ WME_1_7_0,
+ WME_1_8_0,
+ WME_1_8_6,
+ WME_1_9_0,
+ LATEST_VERSION
+};
+
+struct WMEGameDescription {
+ ADGameDescription adDesc;
+ WMETargetExecutable targetExecutable;
+};
+
+}
+
+#endif /* WINTERMUTE_GAME_DESCRIPTION_H_ */
diff --git a/engines/wintermute/math/rect32.h b/engines/wintermute/math/rect32.h
index 93b5c68a30..00326d6747 100644
--- a/engines/wintermute/math/rect32.h
+++ b/engines/wintermute/math/rect32.h
@@ -50,7 +50,7 @@ struct Point32 {
y -= delta.y;
return *this;
}
-
+
operator FloatPoint() {
return FloatPoint(x,y);
}
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index 1b6c52e0b7..4c95314a02 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -108,7 +108,9 @@ MODULE_OBJS := \
utils/path_util.o \
utils/string_util.o \
utils/utils.o \
+ video/subtitle_card.o \
video/video_player.o \
+ video/video_subtitler.o \
video/video_theora_player.o \
debugger.o \
wintermute.o \
diff --git a/engines/wintermute/video/subtitle_card.cpp b/engines/wintermute/video/subtitle_card.cpp
new file mode 100644
index 0000000000..5d882502fd
--- /dev/null
+++ b/engines/wintermute/video/subtitle_card.cpp
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on Wintermute Engine
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/video/subtitle_card.h"
+#include "engines/wintermute/base/base_game.h"
+
+namespace Wintermute {
+
+SubtitleCard::SubtitleCard(BaseGame *inGame,
+ const Common::String &text,
+ const uint &startFrame,
+ const uint &endFrame) : _gameRef(inGame),
+ _startFrame(startFrame),
+ _endFrame(endFrame) {
+ _text = text;
+ _gameRef->expandStringByStringTable(_text);
+}
+
+uint32 SubtitleCard::getStartFrame() const {
+ return _startFrame;
+}
+
+uint32 SubtitleCard::getEndFrame() const {
+ return _endFrame;
+}
+
+Common::String SubtitleCard::getText() const {
+ return _text;
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/video/subtitle_card.h b/engines/wintermute/video/subtitle_card.h
new file mode 100644
index 0000000000..629df77287
--- /dev/null
+++ b/engines/wintermute/video/subtitle_card.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on Wintermute Engine
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SUBTITLECARD_H
+#define WINTERMUTE_SUBTITLECARD_H
+
+#include "common/str.h"
+
+namespace Wintermute {
+
+class BaseGame;
+
+class SubtitleCard {
+public:
+ SubtitleCard(BaseGame *inGame, const Common::String &text, const uint &startFrame, const uint &endFrame);
+ uint32 getEndFrame() const;
+ uint32 getStartFrame() const;
+ Common::String getText() const;
+private:
+ BaseGame *_gameRef;
+ uint32 _endFrame;
+ uint32 _startFrame;
+ Common::String _text;
+};
+
+} // End of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/video/video_subtitler.cpp b/engines/wintermute/video/video_subtitler.cpp
new file mode 100644
index 0000000000..95d938574b
--- /dev/null
+++ b/engines/wintermute/video/video_subtitler.cpp
@@ -0,0 +1,266 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on Wintermute Engine
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/video/video_subtitler.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/path_util.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+
+namespace Wintermute {
+
+VideoSubtitler::VideoSubtitler(BaseGame *inGame): BaseClass(inGame) {
+ _lastSample = -1;
+ _currentSubtitle = 0;
+ _showSubtitle = false;
+}
+
+VideoSubtitler::~VideoSubtitler(void) {
+ _subtitles.clear();
+}
+
+bool VideoSubtitler::loadSubtitles(const Common::String &filename, const Common::String &subtitleFile) {
+ if (filename.size() == 0) {
+ return false;
+ }
+
+ _subtitles.clear();
+
+ _lastSample = -1;
+ _currentSubtitle = 0;
+ _showSubtitle = false;
+
+ Common::String newFile;
+
+ /*
+ * Okay, the expected behaviour is this: either we are
+ * provided with a subtitle file to use by the script when
+ * calling PlayTheora(), or we try to autodetect a suitable
+ * one which, for /some/path/movie/ogg is to be called
+ * /some/path/movie.sub
+ */
+ if (subtitleFile.size() != 0) {
+ newFile = subtitleFile;
+ } else {
+ Common::String path = PathUtil::getDirectoryName(filename);
+ Common::String name = PathUtil::getFileNameWithoutExtension(filename);
+ Common::String ext = ".SUB";
+ newFile = PathUtil::combine(path, name + ext);
+ }
+
+ Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(newFile, true, false);
+
+ if (file == nullptr) {
+ return false; // no subtitles
+ }
+
+ int fileSize = file->size();
+ char *buffer = new char[fileSize];
+
+ file->read(buffer, fileSize);
+
+ /* This is where we parse .sub files.
+ * Subtitles cards are in the form
+ * {StartFrame}{EndFrame} FirstLine | SecondLine \n
+ */
+ int pos = 0;
+
+ while (pos < fileSize) {
+ char *tokenStart = 0;
+ int tokenLength = 0;
+ int tokenPos = -1;
+ int lineLength = 0;
+ int start = -1;
+ int end = -1;
+ bool inToken = false;
+
+ while (pos + lineLength < fileSize &&
+ buffer[pos + lineLength] != '\n' &&
+ buffer[pos + lineLength] != '\0') {
+ // Measure the line until we hit EOL, EOS or just hit the boundary
+ lineLength++;
+ }
+
+ int realLength;
+
+ if (pos + lineLength >= fileSize) {
+ realLength = lineLength - 0;
+ } else {
+ // If we got here the above loop exited after hitting "\0" "\n"
+ realLength = lineLength - 1;
+ }
+
+ Common::String cardText;
+ char *fileLine = (char *)&buffer[pos];
+
+ for (int i = 0; i < realLength; i++) {
+ if (fileLine[i] == '{') {
+ if (!inToken) {
+ // We've hit the start of a Start/EndFrame token
+ inToken = true;
+ tokenStart = fileLine + i + 1;
+ tokenLength = 0;
+ tokenPos++;
+ } else {
+ // Actually, we were already inside an (invalid) one.
+ tokenLength++;
+ }
+ } else if (fileLine[i] == '}') {
+ if (inToken) {
+ // we were /inside/ a {.*} token, so this is the end of the block
+ inToken = false;
+ char *token = new char[tokenLength + 1];
+ strncpy(token, tokenStart, tokenLength);
+ token[tokenLength] = '\0';
+ if (tokenPos == 0) {
+ // Was this StartFrame...
+ start = atoi(token);
+ } else if (tokenPos == 1) {
+ // Or the EndFrame?
+ end = atoi(token);
+ }
+ delete[] token;
+ } else {
+ // This char is part of the plain text, just append it
+ cardText += fileLine[i];
+ }
+ } else {
+ if (inToken) {
+ tokenLength++;
+ } else {
+ if (fileLine[i] == '|') {
+ // The pipe character signals a linebreak in the text
+ cardText += '\n';
+ } else {
+ // This char is part of the plain text, just append it
+ cardText += fileLine[i];
+ }
+ }
+ }
+ }
+
+ if (start != -1 && cardText.size() > 0 && (start != 1 || end != 1)){
+ // Add a subtitlecard based on the line we have just parsed
+ _subtitles.push_back(SubtitleCard(_gameRef, cardText, start, end));
+ }
+
+ pos += lineLength + 1;
+ }
+
+ delete[] buffer;
+ // Succeeded loading subtitles!
+
+ return true;
+}
+
+void VideoSubtitler::display() {
+ if (_showSubtitle) {
+
+ BaseFont *font;
+
+ if (_gameRef->getVideoFont() == nullptr) {
+ font = _gameRef->getSystemFont();
+ } else {
+ font = _gameRef->getVideoFont();
+ }
+
+ int textHeight = font->getTextHeight(
+ (const byte *)_subtitles[_currentSubtitle].getText().c_str(),
+ _gameRef->_renderer->getWidth());
+
+ font->drawText(
+ (const byte *)_subtitles[_currentSubtitle].getText().c_str(),
+ 0,
+ (_gameRef->_renderer->getHeight() - textHeight - 5),
+ (_gameRef->_renderer->getWidth()),
+ TAL_CENTER);
+ }
+}
+
+void VideoSubtitler::update(uint32 frame) {
+ if (_subtitles.size() == 0) {
+ // Edge case: we have loaded subtitles early on... from a blank file.
+ return;
+ }
+
+ if ((int32)frame != _lastSample) {
+ /*
+ * If the frame count hasn't advanced the previous state still matches
+ * the current frame (obviously).
+ */
+
+ _lastSample = frame;
+ // Otherwise, we update _lastSample; see above.
+
+ _showSubtitle = false;
+
+ bool overdue = (frame > _subtitles[_currentSubtitle].getEndFrame());
+ bool hasNext = (_currentSubtitle + 1 < _subtitles.size());
+ bool nextStarted = false;
+ if (hasNext) {
+ nextStarted = (_subtitles[_currentSubtitle + 1].getStartFrame() <= frame);
+ }
+
+ while (_currentSubtitle < _subtitles.size() &&
+ overdue && hasNext && nextStarted) {
+ /*
+ * We advance until we get past all overdue subtitles.
+ * We should exit the cycle when we either reach the first
+ * subtitle which is not overdue whose subsequent subtitle
+ * has not started yet (aka the one we must display now or
+ * the one which WILL be displayed when its time comes)
+ * and / or when we reach the last one.
+ */
+
+ _currentSubtitle++;
+
+ overdue = (frame > _subtitles[_currentSubtitle].getEndFrame());
+ hasNext = (_currentSubtitle + 1 < _subtitles.size());
+ if (hasNext) {
+ nextStarted = (_subtitles[_currentSubtitle + 1].getStartFrame() <= frame);
+ } else {
+ nextStarted = false;
+ }
+ }
+
+ bool currentValid = (_subtitles[_currentSubtitle].getEndFrame() != 0);
+ /*
+ * No idea why we do this check, carried over from Mnemonic's code.
+ * Possibly a workaround for buggy subtitles or some kind of sentinel? :-\
+ */
+
+ bool currentStarted = frame >= _subtitles[_currentSubtitle].getStartFrame();
+
+ if (currentStarted && !overdue && currentValid) {
+ _showSubtitle = true;
+ }
+ }
+}
+
+} // End of namespace Wintermute
diff --git a/engines/wintermute/video/video_subtitler.h b/engines/wintermute/video/video_subtitler.h
new file mode 100644
index 0000000000..94f22909a1
--- /dev/null
+++ b/engines/wintermute/video/video_subtitler.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on Wintermute Engine
+ * http://dead-code.org/redir.php?target=wme
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_VIDSUBTITLER_H
+#define WINTERMUTE_VIDSUBTITLER_H
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/video/subtitle_card.h"
+
+namespace Wintermute {
+
+class VideoSubtitler : public BaseClass {
+public:
+ VideoSubtitler(BaseGame *inGame);
+ virtual ~VideoSubtitler(void);
+ bool loadSubtitles(const Common::String &filename, const Common::String &subtitleFile);
+ void display();
+ void update(uint32 frame);
+private:
+ Common::Array<SubtitleCard> _subtitles;
+ int32 _lastSample;
+ bool _showSubtitle;
+ uint32 _currentSubtitle;
+};
+
+} // End of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index e1553580ec..22c235c848 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -85,14 +85,14 @@ void VideoTheoraPlayer::SetDefaults() {
_volume = 100;
_theoraDecoder = nullptr;
- // TODO: Add subtitles-support
- //_subtitler = nullptr;
+ _subtitler = new VideoSubtitler(_gameRef);
+ _foundSubtitles = false;
}
//////////////////////////////////////////////////////////////////////////
VideoTheoraPlayer::~VideoTheoraPlayer(void) {
cleanup();
-// SAFE_DELETE(_subtitler);
+ delete _subtitler;
}
//////////////////////////////////////////////////////////////////////////
@@ -130,6 +130,9 @@ bool VideoTheoraPlayer::initialize(const Common::String &filename, const Common:
warning("VideoTheoraPlayer::initialize - Theora support not compiled in, video will be skipped: %s", filename.c_str());
return STATUS_FAILED;
#endif
+
+ _foundSubtitles = _subtitler->loadSubtitles(_filename, subtitleFile);
+
_theoraDecoder->loadStream(_file);
if (!_theoraDecoder->isVideoLoaded()) {
@@ -214,7 +217,10 @@ bool VideoTheoraPlayer::play(TVideoPlayback type, int x, int y, bool freezeGame,
_state = THEORA_STATE_PLAYING;
_looping = looping;
_playbackType = type;
-
+ if (_subtitler && _foundSubtitles && _gameRef->_subtitles) {
+ _subtitler->update(_theoraDecoder->getFrameCount());
+ _subtitler->display();
+ }
_startTime = startTime;
_volume = volume;
_posX = x;
@@ -256,7 +262,7 @@ bool VideoTheoraPlayer::play(TVideoPlayback type, int x, int y, bool freezeGame,
#if 0 // Stubbed for now as theora isn't seekable
if (StartTime) SeekToTime(StartTime);
- Update();
+ update();
#endif
return STATUS_FAILED;
}
@@ -289,6 +295,10 @@ bool VideoTheoraPlayer::update() {
}
if (_theoraDecoder) {
+ if (_subtitler && _foundSubtitles && _gameRef->_subtitles) {
+ _subtitler->update(_theoraDecoder->getCurFrame());
+ }
+
if (_theoraDecoder->endOfVideo() && _looping) {
warning("Should loop movie %s, hacked for now", _filename.c_str());
_theoraDecoder->rewind();
@@ -412,11 +422,10 @@ bool VideoTheoraPlayer::display(uint32 alpha) {
} else {
res = STATUS_FAILED;
}
- // TODO: Add subtitles-support
-/* if (m_Subtitler && _gameRef->m_VideoSubtitles) {
- m_Subtitler->display();
- }*/
+ if (_subtitler && _foundSubtitles && _gameRef->_subtitles) {
+ _subtitler->display();
+ }
return res;
}
diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h
index 8274a1444f..0b9b3d487a 100644
--- a/engines/wintermute/video/video_theora_player.h
+++ b/engines/wintermute/video/video_theora_player.h
@@ -31,6 +31,7 @@
#include "engines/wintermute/base/base.h"
#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/video/video_subtitler.h"
#include "video/video_decoder.h"
#include "common/stream.h"
#include "graphics/surface.h"
@@ -59,7 +60,7 @@ public:
Common::String _filename;
BaseSurface *_texture;
- //CVidSubtitler *_subtitler;
+ VideoSubtitler *_subtitler;
// control methods
bool initialize(const Common::String &filename, const Common::String &subtitleFile = Common::String());
@@ -137,9 +138,10 @@ private:
bool _playbackStarted;
+ bool _foundSubtitles;
+
// helpers
void SetDefaults();
-
};
} // End of namespace Wintermute
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 81b6e53c9f..e35bb60c3d 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -53,7 +53,7 @@ WintermuteEngine::WintermuteEngine() : Engine(g_system) {
_gameDescription = nullptr;
}
-WintermuteEngine::WintermuteEngine(OSystem *syst, const ADGameDescription *desc)
+WintermuteEngine::WintermuteEngine(OSystem *syst, const WMEGameDescription *desc)
: Engine(syst), _gameDescription(desc) {
// Put your engine in a sane state, but do nothing big yet;
// in particular, do not load data from files; rather, if you
@@ -133,7 +133,7 @@ Common::Error WintermuteEngine::run() {
}
int WintermuteEngine::init() {
- BaseEngine::createInstance(_targetName, _gameDescription->gameid, _gameDescription->language);
+ BaseEngine::createInstance(_targetName, _gameDescription->adDesc.gameid, _gameDescription->adDesc.language, _gameDescription->targetExecutable);
_game = new AdGame(_targetName);
if (!_game) {
return 1;
diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h
index 017809d56a..f8f5fc7deb 100644
--- a/engines/wintermute/wintermute.h
+++ b/engines/wintermute/wintermute.h
@@ -26,6 +26,7 @@
#include "engines/engine.h"
#include "engines/advancedDetector.h"
#include "gui/debugger.h"
+#include "engines/wintermute/game_description.h"
namespace Wintermute {
@@ -44,7 +45,7 @@ enum {
class WintermuteEngine : public Engine {
public:
- WintermuteEngine(OSystem *syst, const ADGameDescription *desc);
+ WintermuteEngine(OSystem *syst, const WMEGameDescription *desc);
WintermuteEngine();
~WintermuteEngine();
@@ -67,7 +68,7 @@ private:
int messageLoop();
GUI::Debugger *_debugger;
BaseGame *_game;
- const ADGameDescription *_gameDescription;
+ const WMEGameDescription *_gameDescription;
friend class Console;
};
diff --git a/engines/zvision/animation/meta_animation.cpp b/engines/zvision/animation/meta_animation.cpp
new file mode 100644
index 0000000000..857a0dd688
--- /dev/null
+++ b/engines/zvision/animation/meta_animation.cpp
@@ -0,0 +1,132 @@
+/* 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 "zvision/animation/meta_animation.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/animation/rlf_animation.h"
+#include "zvision/video/zork_avi_decoder.h"
+
+#include "video/video_decoder.h"
+
+#include "graphics/surface.h"
+
+namespace ZVision {
+
+MetaAnimation::MetaAnimation(const Common::String &fileName, ZVision *engine)
+ : _fileType(RLF),
+ _curFrame(NULL) {
+ Common::String tmpFileName = fileName;
+ tmpFileName.toLowercase();
+ if (tmpFileName.hasSuffix(".rlf")) {
+ _fileType = RLF;
+ Common::File *_file = engine->getSearchManager()->openFile(tmpFileName);
+ _animation.rlf = new RlfAnimation(_file, false);
+ _frmDelay = _animation.rlf->frameTime();
+ } else if (tmpFileName.hasSuffix(".avi")) {
+ _fileType = AVI;
+ Common::File *_file = engine->getSearchManager()->openFile(tmpFileName);
+ _animation.avi = new ZorkAVIDecoder();
+ _animation.avi->loadStream(_file);
+ _frmDelay = 1000.0 / _animation.avi->getDuration().framerate();
+ } else {
+ warning("Unrecognized animation file type: %s", fileName.c_str());
+ }
+}
+
+MetaAnimation::~MetaAnimation() {
+ if (_fileType == RLF) {
+ delete _animation.rlf;
+ } else if (_fileType == AVI) {
+ delete _animation.avi;
+ }
+}
+
+uint MetaAnimation::frameCount() {
+ if (_fileType == RLF) {
+ return _animation.rlf->frameCount();
+ } else
+ return _animation.avi->getFrameCount();
+
+}
+
+uint MetaAnimation::width() {
+ if (_fileType == RLF) {
+ return _animation.rlf->width();
+ } else
+ return _animation.avi->getWidth();
+}
+uint MetaAnimation::height() {
+ if (_fileType == RLF) {
+ return _animation.rlf->height();
+ } else
+ return _animation.avi->getHeight();
+}
+uint32 MetaAnimation::frameTime() {
+ return _frmDelay;
+}
+
+void MetaAnimation::seekToFrame(int frameNumber) {
+ if (frameNumber >= (int)frameCount())
+ frameNumber = frameCount() - 1;
+
+ if (_fileType == RLF) {
+ _animation.rlf->seekToFrame(frameNumber);
+ } else
+ _animation.avi->seekToFrame(frameNumber);
+}
+
+const Graphics::Surface *MetaAnimation::decodeNextFrame() {
+ if (_fileType == RLF)
+ _curFrame = _animation.rlf->decodeNextFrame();
+ else
+ _curFrame = _animation.avi->decodeNextFrame();
+
+ return _curFrame;
+}
+
+const Graphics::Surface *MetaAnimation::getFrameData(uint frameNumber) {
+ if (frameNumber >= frameCount())
+ frameNumber = frameCount() - 1;
+
+ if (_fileType == RLF) {
+ _curFrame = _animation.rlf->getFrameData(frameNumber);
+ return _curFrame;
+ } else {
+ _animation.avi->seekToFrame(frameNumber);
+ _curFrame = _animation.avi->decodeNextFrame();
+ return _curFrame;
+ }
+}
+
+bool MetaAnimation::endOfAnimation() {
+ if (_fileType == RLF) {
+ return _animation.rlf->endOfAnimation();
+ } else
+ return _animation.avi->endOfVideo();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/animation_control.h b/engines/zvision/animation/meta_animation.h
index 6c4d6dfcf7..93b69587c4 100644
--- a/engines/zvision/scripting/controls/animation_control.h
+++ b/engines/zvision/animation/meta_animation.h
@@ -8,23 +8,25 @@
* 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 ZVISION_ANIMATION_CONTROL_H
-#define ZVISION_ANIMATION_CONTROL_H
-
-#include "zvision/scripting/control.h"
+#ifndef ZVISION_METAANIM_NODE_H
+#define ZVISION_METAANIM_NODE_H
+#include "zvision/scripting/sidefx.h"
+#include "zvision/zvision.h"
+#include "common/rect.h"
+#include "common/list.h"
namespace Common {
class String;
@@ -43,10 +45,21 @@ namespace ZVision {
class ZVision;
class RlfAnimation;
-class AnimationControl : public Control {
+class MetaAnimation {
public:
- AnimationControl(ZVision *engine, uint32 controlKey, const Common::String &fileName);
- ~AnimationControl();
+ MetaAnimation(const Common::String &fileName, ZVision *engine);
+ ~MetaAnimation();
+
+ struct playnode {
+ Common::Rect pos;
+ int32 slot;
+ int32 start;
+ int32 stop;
+ int32 loop;
+ int32 _curFrame;
+ int32 _delay;
+ Graphics::Surface *_scaled;
+ };
private:
enum FileType {
@@ -55,31 +68,29 @@ private:
};
private:
- uint32 _animationKey;
-
union {
RlfAnimation *rlf;
Video::VideoDecoder *avi;
} _animation;
FileType _fileType;
- uint _loopCount;
- int32 _x;
- int32 _y;
-
- uint _accumulatedTime;
- uint _currentLoop;
+ int32 _frmDelay;
- Graphics::Surface *_cachedFrame;
- bool _cachedFrameNeedsDeletion;
+ const Graphics::Surface *_curFrame;
public:
- bool process(uint32 deltaTimeInMillis);
- void setAnimationKey(uint32 animationKey) { _animationKey = animationKey; }
- void setLoopCount(uint loopCount) { _loopCount = loopCount; }
- void setXPos(int32 x) { _x = x; }
- void setYPost(int32 y) { _y = y; }
+ uint frameCount();
+ uint width();
+ uint height();
+ uint32 frameTime();
+
+ void seekToFrame(int frameNumber);
+
+ const Graphics::Surface *decodeNextFrame();
+ const Graphics::Surface *getFrameData(uint frameNumber);
+
+ bool endOfAnimation();
};
} // End of namespace ZVision
diff --git a/engines/zvision/animation/rlf_animation.cpp b/engines/zvision/animation/rlf_animation.cpp
index 945461e7b2..d9b8fa3894 100644
--- a/engines/zvision/animation/rlf_animation.cpp
+++ b/engines/zvision/animation/rlf_animation.cpp
@@ -1,24 +1,24 @@
/* 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.
- *
- */
+*
+* 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"
@@ -32,24 +32,28 @@
#include "graphics/colormasks.h"
-
namespace ZVision {
RlfAnimation::RlfAnimation(const Common::String &fileName, bool stream)
- : _stream(stream),
- _lastFrameRead(0),
- _frameCount(0),
- _width(0),
- _height(0),
- _frameTime(0),
- _frames(0),
- _currentFrame(-1),
- _frameBufferByteSize(0) {
- if (!_file.open(fileName)) {
+ : _stream(stream),
+ _readStream(NULL),
+ _lastFrameRead(0),
+ _frameCount(0),
+ _width(0),
+ _height(0),
+ _frameTime(0),
+ _frames(0),
+ _nextFrame(0),
+ _frameBufferByteSize(0) {
+
+ Common::File *_file = new Common::File;
+ if (!_file->open(fileName)) {
warning("RLF animation file %s could not be opened", fileName.c_str());
return;
}
+ _readStream = _file;
+
if (!readHeader()) {
warning("%s is not a RLF animation file. Wrong magic number", fileName.c_str());
return;
@@ -68,59 +72,90 @@ RlfAnimation::RlfAnimation(const Common::String &fileName, bool stream)
}
}
+RlfAnimation::RlfAnimation(Common::SeekableReadStream *rstream, bool stream)
+ : _stream(stream),
+ _readStream(rstream),
+ _lastFrameRead(0),
+ _frameCount(0),
+ _width(0),
+ _height(0),
+ _frameTime(0),
+ _frames(0),
+ _nextFrame(0),
+ _frameBufferByteSize(0) {
+
+ if (!readHeader()) {
+ warning("Stream is not a RLF animation. Wrong magic number");
+ return;
+ }
+
+ _currentFrameBuffer.create(_width, _height, Graphics::createPixelFormat<565>());
+ _frameBufferByteSize = _width * _height * sizeof(uint16);
+
+ if (!stream) {
+ _frames = new Frame[_frameCount];
+
+ // Read in each frame
+ for (uint i = 0; i < _frameCount; ++i) {
+ _frames[i] = readNextFrame();
+ }
+ }
+}
+
RlfAnimation::~RlfAnimation() {
for (uint i = 0; i < _frameCount; ++i) {
delete[] _frames[i].encodedData;
}
delete[] _frames;
+ delete _readStream;
_currentFrameBuffer.free();
}
bool RlfAnimation::readHeader() {
- if (_file.readUint32BE() != MKTAG('F', 'E', 'L', 'R')) {
+ if (_readStream->readUint32BE() != MKTAG('F', 'E', 'L', 'R')) {
return false;
}
// Read the header
- _file.readUint32LE(); // Size1
- _file.readUint32LE(); // Unknown1
- _file.readUint32LE(); // Unknown2
- _frameCount = _file.readUint32LE(); // Frame count
+ _readStream->readUint32LE(); // Size1
+ _readStream->readUint32LE(); // Unknown1
+ _readStream->readUint32LE(); // Unknown2
+ _frameCount = _readStream->readUint32LE(); // Frame count
// Since we don't need any of the data, we can just seek right to the
// entries we need rather than read in all the individual entries.
- _file.seek(136, SEEK_CUR);
+ _readStream->seek(136, SEEK_CUR);
//// Read CIN header
- //_file.readUint32BE(); // Magic number FNIC
- //_file.readUint32LE(); // Size2
- //_file.readUint32LE(); // Unknown3
- //_file.readUint32LE(); // Unknown4
- //_file.readUint32LE(); // Unknown5
- //_file.seek(0x18, SEEK_CUR); // VRLE
- //_file.readUint32LE(); // LRVD
- //_file.readUint32LE(); // Unknown6
- //_file.seek(0x18, SEEK_CUR); // HRLE
- //_file.readUint32LE(); // ELHD
- //_file.readUint32LE(); // Unknown7
- //_file.seek(0x18, SEEK_CUR); // HKEY
- //_file.readUint32LE(); // ELRH
+ //_readStream->readUint32BE(); // Magic number FNIC
+ //_readStream->readUint32LE(); // Size2
+ //_readStream->readUint32LE(); // Unknown3
+ //_readStream->readUint32LE(); // Unknown4
+ //_readStream->readUint32LE(); // Unknown5
+ //_readStream->seek(0x18, SEEK_CUR); // VRLE
+ //_readStream->readUint32LE(); // LRVD
+ //_readStream->readUint32LE(); // Unknown6
+ //_readStream->seek(0x18, SEEK_CUR); // HRLE
+ //_readStream->readUint32LE(); // ELHD
+ //_readStream->readUint32LE(); // Unknown7
+ //_readStream->seek(0x18, SEEK_CUR); // HKEY
+ //_readStream->readUint32LE(); // ELRH
//// Read MIN info header
- //_file.readUint32BE(); // Magic number FNIM
- //_file.readUint32LE(); // Size3
- //_file.readUint32LE(); // OEDV
- //_file.readUint32LE(); // Unknown8
- //_file.readUint32LE(); // Unknown9
- //_file.readUint32LE(); // Unknown10
- _width = _file.readUint32LE(); // Width
- _height = _file.readUint32LE(); // Height
+ //_readStream->readUint32BE(); // Magic number FNIM
+ //_readStream->readUint32LE(); // Size3
+ //_readStream->readUint32LE(); // OEDV
+ //_readStream->readUint32LE(); // Unknown8
+ //_readStream->readUint32LE(); // Unknown9
+ //_readStream->readUint32LE(); // Unknown10
+ _width = _readStream->readUint32LE(); // Width
+ _height = _readStream->readUint32LE(); // Height
// Read time header
- _file.readUint32BE(); // Magic number EMIT
- _file.readUint32LE(); // Size4
- _file.readUint32LE(); // Unknown11
- _frameTime = _file.readUint32LE() / 10; // Frame time in microseconds
+ _readStream->readUint32BE(); // Magic number EMIT
+ _readStream->readUint32LE(); // Size4
+ _readStream->readUint32LE(); // Unknown11
+ _frameTime = _readStream->readUint32LE() / 10; // Frame time in microseconds
return true;
}
@@ -128,17 +163,17 @@ bool RlfAnimation::readHeader() {
RlfAnimation::Frame RlfAnimation::readNextFrame() {
RlfAnimation::Frame frame;
- _file.readUint32BE(); // Magic number MARF
- uint32 size = _file.readUint32LE(); // Size
- _file.readUint32LE(); // Unknown1
- _file.readUint32LE(); // Unknown2
- uint32 type = _file.readUint32BE(); // Either ELHD or ELRH
- uint32 headerSize = _file.readUint32LE(); // Offset from the beginning of this frame to the frame data. Should always be 28
- _file.readUint32LE(); // Unknown3
+ _readStream->readUint32BE(); // Magic number MARF
+ uint32 size = _readStream->readUint32LE(); // Size
+ _readStream->readUint32LE(); // Unknown1
+ _readStream->readUint32LE(); // Unknown2
+ uint32 type = _readStream->readUint32BE(); // Either ELHD or ELRH
+ uint32 headerSize = _readStream->readUint32LE(); // Offset from the beginning of this frame to the frame data. Should always be 28
+ _readStream->readUint32LE(); // Unknown3
frame.encodedSize = size - headerSize;
frame.encodedData = new int8[frame.encodedSize];
- _file.read(frame.encodedData, frame.encodedSize);
+ _readStream->read(frame.encodedData, frame.encodedSize);
if (type == MKTAG('E', 'L', 'H', 'D')) {
frame.type = Masked;
@@ -157,26 +192,40 @@ void RlfAnimation::seekToFrame(int frameNumber) {
assert(!_stream);
assert(frameNumber < (int)_frameCount || frameNumber >= -1);
- if (frameNumber == -1) {
- _currentFrame = -1;
+ if (_nextFrame == frameNumber)
+ return;
+
+ if (frameNumber < 0) {
+ _nextFrame = 0;
return;
}
- int closestFrame = _currentFrame;
- int distance = (int)frameNumber - _currentFrame;
- for (uint i = 0; i < _completeFrames.size(); ++i) {
- int newDistance = (int)frameNumber - (int)(_completeFrames[i]);
- if (newDistance > 0 && (closestFrame == -1 || newDistance < distance)) {
+ int closestFrame = _nextFrame;
+ int distance = (int)frameNumber - _nextFrame;
+
+ if (distance < 0) {
+ for (uint i = 0; i < _completeFrames.size(); ++i) {
+ if ((int)_completeFrames[i] > frameNumber)
+ break;
closestFrame = _completeFrames[i];
- distance = newDistance;
+ }
+ } else {
+ for (uint i = 0; i < _completeFrames.size(); ++i) {
+ int newDistance = (int)frameNumber - (int)(_completeFrames[i]);
+ if (newDistance < 0)
+ break;
+ if (newDistance < distance) {
+ closestFrame = _completeFrames[i];
+ distance = newDistance;
+ }
}
}
- for (int i = closestFrame; i <= frameNumber; ++i) {
+ for (int i = closestFrame; i < frameNumber; ++i) {
applyFrameToCurrent(i);
}
- _currentFrame = frameNumber;
+ _nextFrame = frameNumber;
}
const Graphics::Surface *RlfAnimation::getFrameData(uint frameNumber) {
@@ -184,27 +233,27 @@ const Graphics::Surface *RlfAnimation::getFrameData(uint frameNumber) {
assert(frameNumber < _frameCount);
// Since this method is so expensive, first check to see if we can use
- // getNextFrame() it's cheap.
- if ((int)frameNumber == _currentFrame) {
+ // decodeNextFrame() it's cheap.
+ if ((int)frameNumber == _nextFrame - 1) {
return &_currentFrameBuffer;
- } else if (_currentFrame + 1 == (int)frameNumber) {
- return getNextFrame();
+ } else if (_nextFrame == (int)frameNumber) {
+ return decodeNextFrame();
}
seekToFrame(frameNumber);
- return &_currentFrameBuffer;
+ return decodeNextFrame();
}
-const Graphics::Surface *RlfAnimation::getNextFrame() {
- assert(_currentFrame + 1 < (int)_frameCount);
+const Graphics::Surface *RlfAnimation::decodeNextFrame() {
+ assert(_nextFrame < (int)_frameCount);
if (_stream) {
applyFrameToCurrent(readNextFrame());
} else {
- applyFrameToCurrent(_currentFrame + 1);
+ applyFrameToCurrent(_nextFrame);
}
- _currentFrame++;
+ _nextFrame++;
return &_currentFrameBuffer;
}
@@ -227,6 +276,7 @@ void RlfAnimation::applyFrameToCurrent(const RlfAnimation::Frame &frame) {
void RlfAnimation::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
uint32 sourceOffset = 0;
uint32 destOffset = 0;
+ int16 numberOfCopy = 0;
while (sourceOffset < sourceSize) {
int8 numberOfSamples = source[sourceOffset];
@@ -235,9 +285,9 @@ void RlfAnimation::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint3
// If numberOfSamples is negative, the next abs(numberOfSamples) samples should
// be copied directly from source to dest
if (numberOfSamples < 0) {
- numberOfSamples = ABS(numberOfSamples);
+ numberOfCopy = -numberOfSamples;
- while (numberOfSamples > 0) {
+ while (numberOfCopy > 0) {
if (sourceOffset + 1 >= sourceSize) {
return;
} else if (destOffset + 1 >= destSize) {
@@ -252,11 +302,11 @@ void RlfAnimation::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint3
sourceOffset += 2;
destOffset += 2;
- numberOfSamples--;
+ numberOfCopy--;
}
- // If numberOfSamples is >= 0, move destOffset forward ((numberOfSamples * 2) + 2)
- // This function assumes the dest buffer has been memset with 0's.
+ // If numberOfSamples is >= 0, move destOffset forward ((numberOfSamples * 2) + 2)
+ // This function assumes the dest buffer has been memset with 0's.
} else {
if (sourceOffset + 1 >= sourceSize) {
return;
@@ -273,6 +323,7 @@ void RlfAnimation::decodeMaskedRunLengthEncoding(int8 *source, int8 *dest, uint3
void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint32 sourceSize, uint32 destSize) const {
uint32 sourceOffset = 0;
uint32 destOffset = 0;
+ int16 numberOfCopy = 0;
while (sourceOffset < sourceSize) {
int8 numberOfSamples = source[sourceOffset];
@@ -281,9 +332,9 @@ void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint3
// If numberOfSamples is negative, the next abs(numberOfSamples) samples should
// be copied directly from source to dest
if (numberOfSamples < 0) {
- numberOfSamples = ABS(numberOfSamples);
+ numberOfCopy = -numberOfSamples;
- while (numberOfSamples > 0) {
+ while (numberOfCopy > 0) {
if (sourceOffset + 1 >= sourceSize) {
return;
} else if (destOffset + 1 >= destSize) {
@@ -298,11 +349,11 @@ void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint3
sourceOffset += 2;
destOffset += 2;
- numberOfSamples--;
+ numberOfCopy--;
}
- // If numberOfSamples is >= 0, copy one sample from source to the
- // next (numberOfSamples + 2) dest spots
+ // If numberOfSamples is >= 0, copy one sample from source to the
+ // next (numberOfSamples + 2) dest spots
} else {
if (sourceOffset + 1 >= sourceSize) {
return;
@@ -313,8 +364,8 @@ void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint3
uint16 sampleColor = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
sourceOffset += 2;
- numberOfSamples += 2;
- while (numberOfSamples > 0) {
+ numberOfCopy = numberOfSamples + 2;
+ while (numberOfCopy > 0) {
if (destOffset + 1 >= destSize) {
debug(2, "Frame decoding overflow\n\tsourceOffset=%u\tsourceSize=%u\n\tdestOffset=%u\tdestSize=%u", sourceOffset, sourceSize, destOffset, destSize);
return;
@@ -322,7 +373,7 @@ void RlfAnimation::decodeSimpleRunLengthEncoding(int8 *source, int8 *dest, uint3
WRITE_UINT16(dest + destOffset, sampleColor);
destOffset += 2;
- numberOfSamples--;
+ numberOfCopy--;
}
}
}
diff --git a/engines/zvision/animation/rlf_animation.h b/engines/zvision/animation/rlf_animation.h
index 4bb779301b..c8b2930676 100644
--- a/engines/zvision/animation/rlf_animation.h
+++ b/engines/zvision/animation/rlf_animation.h
@@ -27,7 +27,6 @@
#include "graphics/surface.h"
-
namespace Common {
class String;
}
@@ -37,6 +36,7 @@ namespace ZVision {
class RlfAnimation {
public:
RlfAnimation(const Common::String &fileName, bool stream = true);
+ RlfAnimation(Common::SeekableReadStream *rstream, bool stream);
~RlfAnimation();
private:
@@ -52,7 +52,7 @@ private:
};
private:
- Common::File _file;
+ Common::SeekableReadStream *_readStream;
bool _stream;
uint _lastFrameRead;
@@ -63,15 +63,23 @@ private:
Frame *_frames;
Common::Array<uint> _completeFrames;
- int _currentFrame;
+ int _nextFrame;
Graphics::Surface _currentFrameBuffer;
uint32 _frameBufferByteSize;
public:
- uint frameCount() { return _frameCount; }
- uint width() { return _width; }
- uint height() { return _height; }
- uint32 frameTime() { return _frameTime; }
+ uint frameCount() {
+ return _frameCount;
+ }
+ uint width() {
+ return _width;
+ }
+ uint height() {
+ return _height;
+ }
+ uint32 frameTime() {
+ return _frameTime;
+ }
/**
* Seeks to the frameNumber and updates the internal Surface with
@@ -84,7 +92,7 @@ public:
/**
* Returns the pixel data of the frame specified. It will try to use
- * getNextFrame() if possible. If not, it uses seekToFrame() to
+ * decodeNextFrame() if possible. If not, it uses seekToFrame() to
* update the internal Surface and then returns a pointer to it.
* This function requires _stream = false
*
@@ -93,18 +101,19 @@ public:
*/
const Graphics::Surface *getFrameData(uint frameNumber);
/**
- * Returns the pixel data of the next frame. It is up to the user to
- * check if the next frame is valid before calling this.
+ * Returns the pixel data of current frame and go to next. It is up to the user to
+ * check if the current frame is valid before calling this.
* IE. Use endOfAnimation()
*
* @return A pointer to the pixel data. Do NOT delete this.
*/
- const Graphics::Surface *getNextFrame();
-
+ const Graphics::Surface *decodeNextFrame();
/**
* @return Is the currentFrame is the last frame in the animation?
*/
- bool endOfAnimation() { return _currentFrame == (int)_frameCount - 1; }
+ bool endOfAnimation() {
+ return _nextFrame == (int)_frameCount;
+ }
private:
/**
diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp
index e610f34474..e641783338 100644
--- a/engines/zvision/core/console.cpp
+++ b/engines/zvision/core/console.cpp
@@ -1,24 +1,24 @@
/* 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.
- *
- */
+*
+* 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"
@@ -27,7 +27,7 @@
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
-#include "zvision/strings/string_manager.h"
+#include "zvision/text/string_manager.h"
#include "zvision/video/zork_avi_decoder.h"
#include "zvision/sound/zork_raw.h"
#include "zvision/utility/utility.h"
@@ -41,11 +41,9 @@
#include "audio/mixer.h"
-
namespace ZVision {
Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) {
- registerCmd("loadimage", WRAP_METHOD(Console, cmdLoadImage));
registerCmd("loadvideo", WRAP_METHOD(Console, cmdLoadVideo));
registerCmd("loadsound", WRAP_METHOD(Console, cmdLoadSound));
registerCmd("raw2wav", WRAP_METHOD(Console, cmdRawToWav));
@@ -56,18 +54,6 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) {
registerCmd("changelocation", WRAP_METHOD(Console, cmdChangeLocation));
registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile));
registerCmd("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles));
- registerCmd("rendertext", WRAP_METHOD(Console, cmdRenderText));
-}
-
-bool Console::cmdLoadImage(int argc, const char **argv) {
- if (argc == 4)
- _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3]));
- else {
- debugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n");
- return true;
- }
-
- return true;
}
bool Console::cmdLoadVideo(int argc, const char **argv) {
@@ -118,7 +104,42 @@ bool Console::cmdRawToWav(int argc, const char **argv) {
return true;
}
- convertRawToWav(argv[1], _engine, argv[2]);
+ Common::File file;
+ if (!file.open(argv[1]))
+ return true;
+
+ Audio::AudioStream *audioStream = makeRawZorkStream(argv[1], _engine);
+
+ Common::DumpFile output;
+ output.open(argv[2]);
+
+ output.writeUint32BE(MKTAG('R', 'I', 'F', 'F'));
+ output.writeUint32LE(file.size() * 2 + 36);
+ output.writeUint32BE(MKTAG('W', 'A', 'V', 'E'));
+ output.writeUint32BE(MKTAG('f', 'm', 't', ' '));
+ output.writeUint32LE(16);
+ output.writeUint16LE(1);
+ uint16 numChannels;
+ if (audioStream->isStereo()) {
+ numChannels = 2;
+ output.writeUint16LE(2);
+ } else {
+ numChannels = 1;
+ output.writeUint16LE(1);
+ }
+ output.writeUint32LE(audioStream->getRate());
+ output.writeUint32LE(audioStream->getRate() * numChannels * 2);
+ output.writeUint16LE(numChannels * 2);
+ output.writeUint16LE(16);
+ output.writeUint32BE(MKTAG('d', 'a', 't', 'a'));
+ output.writeUint32LE(file.size() * 2);
+ int16 *buffer = new int16[file.size()];
+ audioStream->readBuffer(buffer, file.size());
+ output.write(buffer, file.size() * 2);
+
+ delete[] buffer;
+
+
return true;
}
@@ -187,7 +208,23 @@ bool Console::cmdDumpFile(int argc, const char **argv) {
return true;
}
- writeFileContentsToFile(argv[1], argv[1]);
+ Common::File f;
+ if (!_engine->getSearchManager()->openFile(f, argv[1])) {
+ warning("File not found: %s", argv[1]);
+ return true;
+ }
+
+ byte *buffer = new byte[f.size()];
+ f.read(buffer, f.size());
+
+ Common::DumpFile dumpFile;
+ dumpFile.open(argv[1]);
+
+ dumpFile.write(buffer, f.size());
+ dumpFile.flush();
+ dumpFile.close();
+
+ delete[] buffer;
return true;
}
@@ -197,22 +234,9 @@ bool Console::cmdParseAllScrFiles(int argc, const char **argv) {
SearchMan.listMatchingMembers(list, "*.scr");
for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
- _engine->getScriptManager()->parseScrFile((*iter)->getName());
}
return true;
}
-bool Console::cmdRenderText(int argc, const char **argv) {
- if (argc != 7) {
- debugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n");
- return true;
- }
-
- StringManager::TextStyle style = _engine->getStringManager()->getTextStyle(atoi(argv[2]));
- _engine->getRenderManager()->renderTextToWorkingWindow(333, Common::String(argv[1]), style.font, atoi(argv[3]), atoi(argv[4]), style.color, atoi(argv[5]), -1, Graphics::kTextAlignLeft, atoi(argv[6]) == 0 ? false : true);
-
- return true;
-}
-
} // End of namespace ZVision
diff --git a/engines/zvision/core/console.h b/engines/zvision/core/console.h
index 29523c57ee..994e05ba35 100644
--- a/engines/zvision/core/console.h
+++ b/engines/zvision/core/console.h
@@ -37,7 +37,6 @@ public:
private:
ZVision *_engine;
- bool cmdLoadImage(int argc, const char **argv);
bool cmdLoadVideo(int argc, const char **argv);
bool cmdLoadSound(int argc, const char **argv);
bool cmdRawToWav(int argc, const char **argv);
@@ -48,7 +47,6 @@ private:
bool cmdChangeLocation(int argc, const char **argv);
bool cmdDumpFile(int argc, const char **argv);
bool cmdParseAllScrFiles(int argc, const char **argv);
- bool cmdRenderText(int argc, const char **argv);
};
} // End of namespace ZVision
diff --git a/engines/zvision/core/events.cpp b/engines/zvision/core/events.cpp
index 83d6c17dec..52d71c92f6 100644
--- a/engines/zvision/core/events.cpp
+++ b/engines/zvision/core/events.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -29,6 +29,8 @@
#include "zvision/graphics/render_manager.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/animation/rlf_animation.h"
+#include "zvision/core/menu.h"
+#include "zvision/sound/zork_raw.h"
#include "common/events.h"
#include "common/system.h"
@@ -36,29 +38,151 @@
#include "engines/util.h"
-
namespace ZVision {
+void ZVision::shortKeys(Common::Event event) {
+ if (event.kbd.hasFlags(Common::KBD_CTRL)) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_s:
+ if (getMenuBarEnable() & menuBar_Save)
+ _scriptManager->changeLocation('g', 'j', 's', 'e', 0);
+ break;
+ case Common::KEYCODE_r:
+ if (getMenuBarEnable() & menuBar_Restore)
+ _scriptManager->changeLocation('g', 'j', 'r', 'e', 0);
+ break;
+ case Common::KEYCODE_p:
+ if (getMenuBarEnable() & menuBar_Settings)
+ _scriptManager->changeLocation('g', 'j', 'p', 'e', 0);
+ break;
+ case Common::KEYCODE_q:
+ if (getMenuBarEnable() & menuBar_Exit)
+ ifQuit();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void ZVision::cheatCodes(uint8 key) {
+ pushKeyToCheatBuf(key);
+
+ if (getGameId() == GID_GRANDINQUISITOR) {
+ if (checkCode("IMNOTDEAF")) {
+ // Unknown cheat
+ showDebugMsg(Common::String::format("IMNOTDEAF cheat or debug, not implemented"));
+ }
+
+ if (checkCode("3100OPB")) {
+ showDebugMsg(Common::String::format("Current location: %c%c%c%c",
+ _scriptManager->getStateValue(StateKey_World),
+ _scriptManager->getStateValue(StateKey_Room),
+ _scriptManager->getStateValue(StateKey_Node),
+ _scriptManager->getStateValue(StateKey_View)));
+ }
+
+ if (checkCode("KILLMENOW")) {
+ _scriptManager->changeLocation('g', 'j', 'd', 'e', 0);
+ _scriptManager->setStateValue(2201, 35);
+ }
+
+ if (checkCode("MIKESPANTS")) {
+ _scriptManager->changeLocation('g', 'j', 't', 'm', 0);
+ }
+
+ // There are 3 more cheats in script files:
+ // - "EAT ME": gjcr.scr
+ // - "WHOAMI": hp1e.scr
+ // - "HUISOK": uh1f.scr
+ } else if (getGameId() == GID_NEMESIS) {
+ if (checkCode("CHLOE")) {
+ _scriptManager->changeLocation('t', 'm', '2', 'g', 0);
+ _scriptManager->setStateValue(224, 1);
+ }
+
+ if (checkCode("77MASSAVE")) {
+ showDebugMsg(Common::String::format("Current location: %c%c%c%c",
+ _scriptManager->getStateValue(StateKey_World),
+ _scriptManager->getStateValue(StateKey_Room),
+ _scriptManager->getStateValue(StateKey_Node),
+ _scriptManager->getStateValue(StateKey_View)));
+ }
+
+ if (checkCode("IDKFA")) {
+ _scriptManager->changeLocation('t', 'w', '3', 'f', 0);
+ _scriptManager->setStateValue(249, 1);
+ }
+
+ if (checkCode("309NEWDORMA")) {
+ _scriptManager->changeLocation('g', 'j', 'g', 'j', 0);
+ }
+
+ if (checkCode("HELLOSAILOR")) {
+ Location loc = _scriptManager->getCurrentLocation();
+ Audio::AudioStream *soundStream;
+ if (loc.world == 'v' && loc.room == 'b' && loc.node == '1' && loc.view == '0') {
+ soundStream = makeRawZorkStream("v000hpta.raw", this);
+ } else {
+ soundStream = makeRawZorkStream("v000hnta.raw", this);
+ }
+ Audio::SoundHandle handle;
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream);
+ }
+ }
+
+ if (checkCode("FRAME"))
+ showDebugMsg(Common::String::format("FPS: ???, not implemented"));
+
+ if (checkCode("XYZZY"))
+ _scriptManager->setStateValue(StateKey_DebugCheats, 1 - _scriptManager->getStateValue(StateKey_DebugCheats));
+
+ if (checkCode("COMPUTERARCH"))
+ showDebugMsg(Common::String::format("COMPUTERARCH: var-viewer not implemented"));
+
+ if (_scriptManager->getStateValue(StateKey_DebugCheats) == 1)
+ if (checkCode("GO????"))
+ _scriptManager->changeLocation(getBufferedKey(3),
+ getBufferedKey(2),
+ getBufferedKey(1),
+ getBufferedKey(0), 0);
+}
+
void ZVision::processEvents() {
while (_eventMan->pollEvent(_event)) {
switch (_event.type) {
case Common::EVENT_LBUTTONDOWN:
- onMouseDown(_event.mouse);
+ _cursorManager->cursorDown(true);
+ _scriptManager->setStateValue(StateKey_LMouse, 1);
+ _menu->onMouseDown(_event.mouse);
+ _scriptManager->addEvent(_event);
break;
case Common::EVENT_LBUTTONUP:
- onMouseUp(_event.mouse);
+ _cursorManager->cursorDown(false);
+ _scriptManager->setStateValue(StateKey_LMouse, 0);
+ _menu->onMouseUp(_event.mouse);
+ _scriptManager->addEvent(_event);
break;
case Common::EVENT_RBUTTONDOWN:
- // TODO: Inventory logic
+ _cursorManager->cursorDown(true);
+ _scriptManager->setStateValue(StateKey_RMouse, 1);
+
+ if (getGameId() == GID_NEMESIS)
+ _scriptManager->inventoryCycle();
+ break;
+
+ case Common::EVENT_RBUTTONUP:
+ _cursorManager->cursorDown(false);
+ _scriptManager->setStateValue(StateKey_RMouse, 0);
break;
case Common::EVENT_MOUSEMOVE:
onMouseMove(_event.mouse);
break;
- case Common::EVENT_KEYDOWN:
+ case Common::EVENT_KEYDOWN: {
switch (_event.kbd.keycode) {
case Common::KEYCODE_d:
if (_event.kbd.hasFlags(Common::KBD_CTRL)) {
@@ -67,18 +191,52 @@ void ZVision::processEvents() {
_console->onFrame();
}
break;
- case Common::KEYCODE_q:
- if (_event.kbd.hasFlags(Common::KBD_CTRL))
- quitGame();
+
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_RIGHT:
+ if (_renderManager->getRenderTable()->getRenderState() == RenderTable::PANORAMA)
+ _kbdVelocity = (_event.kbd.keycode == Common::KEYCODE_LEFT ?
+ -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) :
+ _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2;
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_DOWN:
+ if (_renderManager->getRenderTable()->getRenderState() == RenderTable::TILT)
+ _kbdVelocity = (_event.kbd.keycode == Common::KEYCODE_UP ?
+ -_scriptManager->getStateValue(StateKey_KbdRotateSpeed) :
+ _scriptManager->getStateValue(StateKey_KbdRotateSpeed)) * 2;
break;
+
default:
break;
}
- _scriptManager->onKeyDown(_event.kbd);
- break;
+ uint8 vkKey = getZvisionKey(_event.kbd.keycode);
+
+ _scriptManager->setStateValue(StateKey_KeyPress, vkKey);
+
+ _scriptManager->addEvent(_event);
+ shortKeys(_event);
+ cheatCodes(vkKey);
+ }
+ break;
case Common::EVENT_KEYUP:
- _scriptManager->onKeyUp(_event.kbd);
+ _scriptManager->addEvent(_event);
+ switch (_event.kbd.keycode) {
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_RIGHT:
+ if (_renderManager->getRenderTable()->getRenderState() == RenderTable::PANORAMA)
+ _kbdVelocity = 0;
+ break;
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_DOWN:
+ if (_renderManager->getRenderTable()->getRenderState() == RenderTable::TILT)
+ _kbdVelocity = 0;
+ break;
+ default:
+ break;
+ }
break;
default:
break;
@@ -86,24 +244,11 @@ void ZVision::processEvents() {
}
}
-void ZVision::onMouseDown(const Common::Point &pos) {
- _cursorManager->cursorDown(true);
-
- Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
- _scriptManager->onMouseDown(pos, imageCoord);
-}
-
-void ZVision::onMouseUp(const Common::Point &pos) {
- _cursorManager->cursorDown(false);
-
- Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
- _scriptManager->onMouseUp(pos, imageCoord);
-}
-
void ZVision::onMouseMove(const Common::Point &pos) {
+ _menu->onMouseMove(pos);
Common::Point imageCoord(_renderManager->screenSpaceToImageSpace(pos));
- bool cursorWasChanged = _scriptManager->onMouseMove(pos, imageCoord);
+ bool cursorWasChanged = false;
// Graph of the function governing rotation velocity:
//
@@ -136,51 +281,165 @@ void ZVision::onMouseMove(const Common::Point &pos) {
// ^
if (_workingWindow.contains(pos)) {
+ cursorWasChanged = _scriptManager->onMouseMove(pos, imageCoord);
+
RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState();
if (renderState == RenderTable::PANORAMA) {
if (pos.x >= _workingWindow.left && pos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) {
- // Linear function of distance to the left edge (y = -mx + b)
- // We use fixed point math to get better accuracy
- Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.left)) - MAX_ROTATION_SPEED;
- _renderManager->setBackgroundVelocity(velocity.toInt());
- _cursorManager->setLeftCursor();
+
+ int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4;
+ if (mspeed <= 0)
+ mspeed = 400 >> 4;
+ _mouseVelocity = (((pos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7;
+
+ _cursorManager->changeCursor(CursorIndex_Left);
cursorWasChanged = true;
} else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) {
- // Linear function of distance to the right edge (y = mx)
- // We use fixed point math to get better accuracy
- Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET);
- _renderManager->setBackgroundVelocity(velocity.toInt());
- _cursorManager->setRightCursor();
+
+ int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4;
+ if (mspeed <= 0)
+ mspeed = 400 >> 4;
+ _mouseVelocity = (((pos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7;
+
+ _cursorManager->changeCursor(CursorIndex_Right);
cursorWasChanged = true;
} else {
- _renderManager->setBackgroundVelocity(0);
+ _mouseVelocity = 0;
}
} else if (renderState == RenderTable::TILT) {
if (pos.y >= _workingWindow.top && pos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) {
- // Linear function of distance to top edge
- // We use fixed point math to get better accuracy
- Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - MAX_ROTATION_SPEED;
- _renderManager->setBackgroundVelocity(velocity.toInt());
- _cursorManager->setUpCursor();
+
+ int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4;
+ if (mspeed <= 0)
+ mspeed = 400 >> 4;
+ _mouseVelocity = (((pos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7;
+
+ _cursorManager->changeCursor(CursorIndex_UpArr);
cursorWasChanged = true;
} else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) {
- // Linear function of distance to the bottom edge (y = mx)
- // We use fixed point math to get better accuracy
- Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET);
- _renderManager->setBackgroundVelocity(velocity.toInt());
- _cursorManager->setDownCursor();
+
+ int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4;
+ if (mspeed <= 0)
+ mspeed = 400 >> 4;
+ _mouseVelocity = (((pos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7;
+
+ _cursorManager->changeCursor(CursorIndex_DownArr);
cursorWasChanged = true;
} else {
- _renderManager->setBackgroundVelocity(0);
+ _mouseVelocity = 0;
}
+ } else {
+ _mouseVelocity = 0;
}
} else {
- _renderManager->setBackgroundVelocity(0);
+ _mouseVelocity = 0;
}
if (!cursorWasChanged) {
- _cursorManager->revertToIdle();
+ _cursorManager->changeCursor(CursorIndex_Idle);
}
}
+uint8 ZVision::getZvisionKey(Common::KeyCode scummKeyCode) {
+ if (scummKeyCode >= Common::KEYCODE_a && scummKeyCode <= Common::KEYCODE_z)
+ return 0x41 + scummKeyCode - Common::KEYCODE_a;
+ if (scummKeyCode >= Common::KEYCODE_0 && scummKeyCode <= Common::KEYCODE_9)
+ return 0x30 + scummKeyCode - Common::KEYCODE_0;
+ if (scummKeyCode >= Common::KEYCODE_F1 && scummKeyCode <= Common::KEYCODE_F15)
+ return 0x70 + scummKeyCode - Common::KEYCODE_F1;
+ if (scummKeyCode >= Common::KEYCODE_KP0 && scummKeyCode <= Common::KEYCODE_KP9)
+ return 0x60 + scummKeyCode - Common::KEYCODE_KP0;
+
+ switch (scummKeyCode) {
+ case Common::KEYCODE_BACKSPACE:
+ return 0x8;
+ case Common::KEYCODE_TAB:
+ return 0x9;
+ case Common::KEYCODE_CLEAR:
+ return 0xC;
+ case Common::KEYCODE_RETURN:
+ return 0xD;
+ case Common::KEYCODE_CAPSLOCK:
+ return 0x14;
+ case Common::KEYCODE_ESCAPE:
+ return 0x1B;
+ case Common::KEYCODE_SPACE:
+ return 0x20;
+ case Common::KEYCODE_PAGEUP:
+ return 0x21;
+ case Common::KEYCODE_PAGEDOWN:
+ return 0x22;
+ case Common::KEYCODE_END:
+ return 0x23;
+ case Common::KEYCODE_HOME:
+ return 0x24;
+ case Common::KEYCODE_LEFT:
+ return 0x25;
+ case Common::KEYCODE_UP:
+ return 0x26;
+ case Common::KEYCODE_RIGHT:
+ return 0x27;
+ case Common::KEYCODE_DOWN:
+ return 0x28;
+ case Common::KEYCODE_PRINT:
+ return 0x2A;
+ case Common::KEYCODE_INSERT:
+ return 0x2D;
+ case Common::KEYCODE_DELETE:
+ return 0x2E;
+ case Common::KEYCODE_HELP:
+ return 0x2F;
+ case Common::KEYCODE_KP_MULTIPLY:
+ return 0x6A;
+ case Common::KEYCODE_KP_PLUS:
+ return 0x6B;
+ case Common::KEYCODE_KP_MINUS:
+ return 0x6D;
+ case Common::KEYCODE_KP_PERIOD:
+ return 0x6E;
+ case Common::KEYCODE_KP_DIVIDE:
+ return 0x6F;
+ case Common::KEYCODE_NUMLOCK:
+ return 0x90;
+ case Common::KEYCODE_SCROLLOCK:
+ return 0x91;
+ case Common::KEYCODE_LSHIFT:
+ return 0xA0;
+ case Common::KEYCODE_RSHIFT:
+ return 0xA1;
+ case Common::KEYCODE_LCTRL:
+ return 0xA2;
+ case Common::KEYCODE_RCTRL:
+ return 0xA3;
+ case Common::KEYCODE_MENU:
+ return 0xA5;
+ case Common::KEYCODE_LEFTBRACKET:
+ return 0xDB;
+ case Common::KEYCODE_RIGHTBRACKET:
+ return 0xDD;
+ case Common::KEYCODE_SEMICOLON:
+ return 0xBA;
+ case Common::KEYCODE_BACKSLASH:
+ return 0xDC;
+ case Common::KEYCODE_QUOTE:
+ return 0xDE;
+ case Common::KEYCODE_SLASH:
+ return 0xBF;
+ case Common::KEYCODE_TILDE:
+ return 0xC0;
+ case Common::KEYCODE_COMMA:
+ return 0xBC;
+ case Common::KEYCODE_PERIOD:
+ return 0xBE;
+ case Common::KEYCODE_MINUS:
+ return 0xBD;
+ case Common::KEYCODE_PLUS:
+ return 0xBB;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/core/menu.cpp b/engines/zvision/core/menu.cpp
new file mode 100644
index 0000000000..c7898a4fbd
--- /dev/null
+++ b/engines/zvision/core/menu.cpp
@@ -0,0 +1,761 @@
+/* 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 "zvision/core/menu.h"
+
+#include "zvision/graphics/render_manager.h"
+
+namespace ZVision {
+
+enum {
+ SLOT_START_SLOT = 151,
+ SLOT_SPELL_1 = 191,
+ SLOT_USER_CHOSE_THIS_SPELL = 205,
+ SLOT_REVERSED_SPELLBOOK = 206
+};
+
+enum {
+ menu_MAIN_SAVE = 0,
+ menu_MAIN_REST = 1,
+ menu_MAIN_PREF = 2,
+ menu_MAIN_EXIT = 3
+};
+
+MenuHandler::MenuHandler(ZVision *engine) {
+ _engine = engine;
+ menuBarFlag = 0xFFFF;
+}
+
+MenuZGI::MenuZGI(ZVision *engine) :
+ MenuHandler(engine) {
+ menuMouseFocus = -1;
+ inmenu = false;
+ scrolled[0] = false;
+ scrolled[1] = false;
+ scrolled[2] = false;
+ scrollPos[0] = 0.0;
+ scrollPos[1] = 0.0;
+ scrollPos[2] = 0.0;
+ mouseOnItem = -1;
+
+ char buf[24];
+ for (int i = 1; i < 4; i++) {
+ sprintf(buf, "gmzau%2.2x1.tga", i);
+ _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][0], false);
+ sprintf(buf, "gmzau%2.2x1.tga", i + 0x10);
+ _engine->getRenderManager()->readImageToSurface(buf, menuback[i - 1][1], false);
+ }
+ for (int i = 0; i < 4; i++) {
+ sprintf(buf, "gmzmu%2.2x1.tga", i);
+ _engine->getRenderManager()->readImageToSurface(buf, menubar[i][0], false);
+ sprintf(buf, "gmznu%2.2x1.tga", i);
+ _engine->getRenderManager()->readImageToSurface(buf, menubar[i][1], false);
+ }
+
+ for (int i = 0; i < 50; i++) {
+ items[i][0] = NULL;
+ items[i][1] = NULL;
+ itemId[i] = 0;
+ }
+
+ for (int i = 0; i < 12; i++) {
+ magic[i][0] = NULL;
+ magic[i][1] = NULL;
+ magicId[i] = 0;
+ }
+}
+
+MenuZGI::~MenuZGI() {
+ for (int i = 0; i < 3; i++) {
+ menuback[i][0].free();
+ menuback[i][1].free();
+ }
+ for (int i = 0; i < 4; i++) {
+ menubar[i][0].free();
+ menubar[i][1].free();
+ }
+ for (int i = 0; i < 50; i++) {
+ if (items[i][0]) {
+ items[i][0]->free();
+ delete items[i][0];
+ }
+ if (items[i][1]) {
+ items[i][1]->free();
+ delete items[i][1];
+ }
+ }
+ for (int i = 0; i < 12; i++) {
+ if (magic[i][0]) {
+ magic[i][0]->free();
+ delete magic[i][0];
+ }
+ if (magic[i][1]) {
+ magic[i][1]->free();
+ delete magic[i][1];
+ }
+ }
+}
+
+void MenuZGI::onMouseUp(const Common::Point &Pos) {
+ if (Pos.y < 40) {
+ switch (menuMouseFocus) {
+ case menu_ITEM:
+ if (menuBarFlag & menuBar_Items) {
+ int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots);
+ if (itemCount == 0)
+ itemCount = 20;
+
+ for (int i = 0; i < itemCount; i++) {
+ int itemspace = (600 - 28) / itemCount;
+
+ if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0,
+ scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) {
+ int32 mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
+ if (mouseItem >= 0 && mouseItem < 0xE0) {
+ _engine->getScriptManager()->inventoryDrop(mouseItem);
+ _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i));
+ _engine->getScriptManager()->setStateValue(SLOT_START_SLOT + i, mouseItem);
+
+ redraw = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case menu_MAGIC:
+ if (menuBarFlag & menuBar_Magic) {
+ for (int i = 0; i < 12; i++) {
+
+ uint itemnum = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i);
+ if (itemnum != 0) {
+ if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1)
+ itemnum = 0xEE + i;
+ else
+ itemnum = 0xE0 + i;
+ }
+ if (itemnum)
+ if (_engine->getScriptManager()->getStateValue(StateKey_InventoryItem) == 0 || _engine->getScriptManager()->getStateValue(StateKey_InventoryItem) >= 0xE0)
+ if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0,
+ 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos))
+ _engine->getScriptManager()->setStateValue(SLOT_USER_CHOSE_THIS_SPELL, itemnum);
+ }
+
+ }
+ break;
+
+ case menu_MAIN:
+
+ // Exit
+ if (menuBarFlag & menuBar_Exit)
+ if (Common::Rect(320 + 135,
+ scrollPos[menu_MAIN],
+ 320 + 135 + 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ _engine->ifQuit();
+ }
+
+ // Settings
+ if (menuBarFlag & menuBar_Settings)
+ if (Common::Rect(320 ,
+ scrollPos[menu_MAIN],
+ 320 + 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0);
+ }
+
+ // Load
+ if (menuBarFlag & menuBar_Restore)
+ if (Common::Rect(320 - 135,
+ scrollPos[menu_MAIN],
+ 320,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0);
+ }
+
+ // Save
+ if (menuBarFlag & menuBar_Save)
+ if (Common::Rect(320 - 135 * 2,
+ scrollPos[menu_MAIN],
+ 320 - 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0);
+ }
+ break;
+ }
+ }
+}
+
+void MenuZGI::onMouseMove(const Common::Point &Pos) {
+ if (Pos.y < 40) {
+
+ if (!inmenu)
+ redraw = true;
+ inmenu = true;
+ switch (menuMouseFocus) {
+ case menu_ITEM:
+ if (menuBarFlag & menuBar_Items) {
+ int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots);
+ if (itemCount == 0)
+ itemCount = 20;
+ else if (itemCount > 50)
+ itemCount = 50;
+
+ int lastItem = mouseOnItem;
+
+ mouseOnItem = -1;
+
+ for (int i = 0; i < itemCount; i++) {
+ int itemspace = (600 - 28) / itemCount;
+
+ if (Common::Rect(scrollPos[menu_ITEM] + itemspace * i, 0,
+ scrollPos[menu_ITEM] + itemspace * i + 28, 32).contains(Pos)) {
+ mouseOnItem = i;
+ break;
+ }
+ }
+
+ if (lastItem != mouseOnItem)
+ if (_engine->getScriptManager()->getStateValue(SLOT_START_SLOT + mouseOnItem) ||
+ _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + lastItem))
+ redraw = true;
+ }
+ break;
+
+ case menu_MAGIC:
+ if (menuBarFlag & menuBar_Magic) {
+ int lastItem = mouseOnItem;
+ mouseOnItem = -1;
+ for (int i = 0; i < 12; i++) {
+ if (Common::Rect(668 + 47 * i - scrollPos[menu_MAGIC], 0,
+ 668 + 47 * i - scrollPos[menu_MAGIC] + 28, 32).contains(Pos)) {
+ mouseOnItem = i;
+ break;
+ }
+ }
+
+ if (lastItem != mouseOnItem)
+ if (_engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + mouseOnItem) ||
+ _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + lastItem))
+ redraw = true;
+
+ }
+ break;
+
+ case menu_MAIN: {
+ int lastItem = mouseOnItem;
+ mouseOnItem = -1;
+
+ // Exit
+ if (menuBarFlag & menuBar_Exit)
+ if (Common::Rect(320 + 135,
+ scrollPos[menu_MAIN],
+ 320 + 135 + 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_EXIT;
+ }
+
+ // Settings
+ if (menuBarFlag & menuBar_Settings)
+ if (Common::Rect(320 ,
+ scrollPos[menu_MAIN],
+ 320 + 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_PREF;
+ }
+
+ // Load
+ if (menuBarFlag & menuBar_Restore)
+ if (Common::Rect(320 - 135,
+ scrollPos[menu_MAIN],
+ 320,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_REST;
+ }
+
+ // Save
+ if (menuBarFlag & menuBar_Save)
+ if (Common::Rect(320 - 135 * 2,
+ scrollPos[menu_MAIN],
+ 320 - 135,
+ scrollPos[menu_MAIN] + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_SAVE;
+ }
+
+ if (lastItem != mouseOnItem)
+ redraw = true;
+ }
+ break;
+
+ default:
+ int cur_menu = menuMouseFocus;
+ if (Common::Rect(64, 0, 64 + 512, 8).contains(Pos)) { // Main
+ menuMouseFocus = menu_MAIN;
+ scrolled[menu_MAIN] = false;
+ scrollPos[menu_MAIN] = menuback[menu_MAIN][1].h - menuback[menu_MAIN][0].h;
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2);
+ }
+
+ if (menuBarFlag & menuBar_Magic)
+ if (Common::Rect(640 - 28, 0, 640, 32).contains(Pos)) { // Magic
+ menuMouseFocus = menu_MAGIC;
+ scrolled[menu_MAGIC] = false;
+ scrollPos[menu_MAGIC] = 28;
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 3);
+ }
+
+ if (menuBarFlag & menuBar_Items)
+ if (Common::Rect(0, 0, 28, 32).contains(Pos)) { // Items
+ menuMouseFocus = menu_ITEM;
+ scrolled[menu_ITEM] = false;
+ scrollPos[menu_ITEM] = 28 - 600;
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 1);
+ }
+
+ if (cur_menu != menuMouseFocus)
+ clean = true;
+
+ break;
+ }
+ } else {
+ if (inmenu)
+ clean = true;
+ inmenu = false;
+ if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0)
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0);
+ menuMouseFocus = -1;
+ }
+}
+
+void MenuZGI::process(uint32 deltatime) {
+ if (clean) {
+ _engine->getRenderManager()->clearMenuSurface();
+ clean = false;
+ }
+ switch (menuMouseFocus) {
+ case menu_ITEM:
+ if (menuBarFlag & menuBar_Items)
+ if (!scrolled[menu_ITEM]) {
+ redraw = true;
+ float scrl = 600.0 * (deltatime / 1000.0);
+
+ if (scrl == 0)
+ scrl = 1.0;
+
+ scrollPos [menu_ITEM] += scrl;
+
+ if (scrollPos[menu_ITEM] >= 0) {
+ scrolled[menu_ITEM] = true;
+ scrollPos [menu_ITEM] = 0;
+ }
+ }
+ if (redraw) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][0], scrollPos[menu_ITEM], 0);
+
+ int itemCount = _engine->getScriptManager()->getStateValue(StateKey_Inv_TotalSlots);
+ if (itemCount == 0)
+ itemCount = 20;
+ else if (itemCount > 50)
+ itemCount = 50;
+
+ for (int i = 0; i < itemCount; i++) {
+ int itemspace = (600 - 28) / itemCount;
+
+ bool inrect = false;
+
+ if (mouseOnItem == i)
+ inrect = true;
+
+ uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_START_SLOT + i);
+
+ if (curItemId != 0) {
+ if (itemId[i] != curItemId) {
+ char buf[16];
+ sprintf(buf, "gmzwu%2.2x1.tga", curItemId);
+ items[i][0] = _engine->getRenderManager()->loadImage(buf, false);
+ sprintf(buf, "gmzxu%2.2x1.tga", curItemId);
+ items[i][1] = _engine->getRenderManager()->loadImage(buf, false);
+ itemId[i] = curItemId;
+ }
+
+ if (inrect)
+ _engine->getRenderManager()->blitSurfaceToMenu(*items[i][1], scrollPos[menu_ITEM] + itemspace * i, 0, 0);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(*items[i][0], scrollPos[menu_ITEM] + itemspace * i, 0, 0);
+
+ } else {
+ if (items[i][0]) {
+ items[i][0]->free();
+ delete items[i][0];
+ items[i][0] = NULL;
+ }
+ if (items[i][1]) {
+ items[i][1]->free();
+ delete items[i][1];
+ items[i][1] = NULL;
+ }
+ itemId[i] = 0;
+ }
+ }
+
+ redraw = false;
+ }
+ break;
+
+ case menu_MAGIC:
+ if (menuBarFlag & menuBar_Magic)
+ if (!scrolled[menu_MAGIC]) {
+ redraw = true;
+ float scrl = 600.0 * (deltatime / 1000.0);
+
+ if (scrl == 0)
+ scrl = 1.0;
+
+ scrollPos [menu_MAGIC] += scrl;
+
+ if (scrollPos[menu_MAGIC] >= 600) {
+ scrolled[menu_MAGIC] = true;
+ scrollPos [menu_MAGIC] = 600;
+ }
+ }
+ if (redraw) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][0], 640 - scrollPos[menu_MAGIC], 0);
+
+ for (int i = 0; i < 12; i++) {
+ bool inrect = false;
+
+ if (mouseOnItem == i)
+ inrect = true;
+
+ uint curItemId = _engine->getScriptManager()->getStateValue(SLOT_SPELL_1 + i);
+ if (curItemId) {
+ if (_engine->getScriptManager()->getStateValue(SLOT_REVERSED_SPELLBOOK) == 1)
+ curItemId = 0xEE + i;
+ else
+ curItemId = 0xE0 + i;
+ }
+
+ if (curItemId != 0) {
+ if (itemId[i] != curItemId) {
+ char buf[16];
+ sprintf(buf, "gmzwu%2.2x1.tga", curItemId);
+ magic[i][0] = _engine->getRenderManager()->loadImage(buf, false);
+ sprintf(buf, "gmzxu%2.2x1.tga", curItemId);
+ magic[i][1] = _engine->getRenderManager()->loadImage(buf, false);
+ magicId[i] = curItemId;
+ }
+
+ if (inrect)
+ _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][1], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(*magic[i][0], 668 + 47 * i - scrollPos[menu_MAGIC], 0, 0);
+
+ } else {
+ if (magic[i][0]) {
+ magic[i][0]->free();
+ delete magic[i][0];
+ magic[i][0] = NULL;
+ }
+ if (magic[i][1]) {
+ magic[i][1]->free();
+ delete magic[i][1];
+ magic[i][1] = NULL;
+ }
+ magicId[i] = 0;
+ }
+ }
+ redraw = false;
+ }
+ break;
+
+ case menu_MAIN:
+ if (!scrolled[menu_MAIN]) {
+ redraw = true;
+ float scrl = 32.0 * 2.0 * (deltatime / 1000.0);
+
+ if (scrl == 0)
+ scrl = 1.0;
+
+ scrollPos [menu_MAIN] += scrl;
+
+ if (scrollPos[menu_MAIN] >= 0) {
+ scrolled[menu_MAIN] = true;
+ scrollPos [menu_MAIN] = 0;
+ }
+ }
+ if (redraw) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][0], 30, scrollPos[menu_MAIN]);
+
+ if (menuBarFlag & menuBar_Exit) {
+ if (mouseOnItem == menu_MAIN_EXIT)
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][1], 320 + 135, scrollPos[menu_MAIN]);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_EXIT][0], 320 + 135, scrollPos[menu_MAIN]);
+ }
+ if (menuBarFlag & menuBar_Settings) {
+ if (mouseOnItem == menu_MAIN_PREF)
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][1], 320, scrollPos[menu_MAIN]);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_PREF][0], 320, scrollPos[menu_MAIN]);
+ }
+ if (menuBarFlag & menuBar_Restore) {
+ if (mouseOnItem == menu_MAIN_REST)
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][1], 320 - 135, scrollPos[menu_MAIN]);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_REST][0], 320 - 135, scrollPos[menu_MAIN]);
+ }
+ if (menuBarFlag & menuBar_Save) {
+ if (mouseOnItem == menu_MAIN_SAVE)
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][1], 320 - 135 * 2, scrollPos[menu_MAIN]);
+ else
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar[menu_MAIN_SAVE][0], 320 - 135 * 2, scrollPos[menu_MAIN]);
+ }
+ redraw = false;
+ }
+ break;
+ default:
+ if (redraw) {
+ if (inmenu) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAIN][1], 30, 0);
+
+ if (menuBarFlag & menuBar_Items)
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_ITEM][1], 0, 0);
+
+ if (menuBarFlag & menuBar_Magic)
+ _engine->getRenderManager()->blitSurfaceToMenu(menuback[menu_MAGIC][1], 640 - 28, 0);
+ }
+ redraw = false;
+ }
+ break;
+ }
+}
+
+MenuNemesis::MenuNemesis(ZVision *engine) :
+ MenuHandler(engine) {
+ inmenu = false;
+ scrolled = false;
+ scrollPos = 0.0;
+ mouseOnItem = -1;
+
+ char buf[24];
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 6; j++) {
+ sprintf(buf, "butfrm%d%d.tga", i + 1, j);
+ _engine->getRenderManager()->readImageToSurface(buf, but[i][j], false);
+ }
+
+ _engine->getRenderManager()->readImageToSurface("bar.tga", menubar, false);
+
+ frm = 0;
+}
+
+MenuNemesis::~MenuNemesis() {
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 6; j++)
+ but[i][j].free();
+
+ menubar.free();
+}
+
+static const int16 buts[4][2] = { {120 , 64}, {144, 184}, {128, 328}, {120, 456} };
+
+void MenuNemesis::onMouseUp(const Common::Point &Pos) {
+ if (Pos.y < 40) {
+ // Exit
+ if (menuBarFlag & menuBar_Exit)
+ if (Common::Rect(buts[3][1],
+ scrollPos,
+ buts[3][0] + buts[3][1],
+ scrollPos + 32).contains(Pos)) {
+ _engine->ifQuit();
+ frm = 5;
+ redraw = true;
+ }
+
+ // Settings
+ if (menuBarFlag & menuBar_Settings)
+ if (Common::Rect(buts[2][1],
+ scrollPos,
+ buts[2][0] + buts[2][1],
+ scrollPos + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 'p', 'e', 0);
+ frm = 5;
+ redraw = true;
+ }
+
+ // Load
+ if (menuBarFlag & menuBar_Restore)
+ if (Common::Rect(buts[1][1],
+ scrollPos,
+ buts[1][0] + buts[1][1],
+ scrollPos + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 'r', 'e', 0);
+ frm = 5;
+ redraw = true;
+ }
+
+ // Save
+ if (menuBarFlag & menuBar_Save)
+ if (Common::Rect(buts[0][1],
+ scrollPos,
+ buts[0][0] + buts[0][1],
+ scrollPos + 32).contains(Pos)) {
+ _engine->getScriptManager()->changeLocation('g', 'j', 's', 'e', 0);
+ frm = 5;
+ redraw = true;
+ }
+ }
+}
+
+void MenuNemesis::onMouseMove(const Common::Point &Pos) {
+ if (Pos.y < 40) {
+
+ inmenu = true;
+
+ if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 2)
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 2);
+
+ int lastItem = mouseOnItem;
+ mouseOnItem = -1;
+
+ // Exit
+ if (menuBarFlag & menuBar_Exit)
+ if (Common::Rect(buts[3][1],
+ scrollPos,
+ buts[3][0] + buts[3][1],
+ scrollPos + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_EXIT;
+ }
+
+ // Settings
+ if (menuBarFlag & menuBar_Settings)
+ if (Common::Rect(buts[2][1],
+ scrollPos,
+ buts[2][0] + buts[2][1],
+ scrollPos + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_PREF;
+ }
+
+ // Load
+ if (menuBarFlag & menuBar_Restore)
+ if (Common::Rect(buts[1][1],
+ scrollPos,
+ buts[1][0] + buts[1][1],
+ scrollPos + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_REST;
+ }
+
+ // Save
+ if (menuBarFlag & menuBar_Save)
+ if (Common::Rect(buts[0][1],
+ scrollPos,
+ buts[0][0] + buts[0][1],
+ scrollPos + 32).contains(Pos)) {
+ mouseOnItem = menu_MAIN_SAVE;
+ }
+
+ if (lastItem != mouseOnItem) {
+ redraw = true;
+ frm = 0;
+ delay = 200;
+ }
+ } else {
+ inmenu = false;
+ if (_engine->getScriptManager()->getStateValue(StateKey_MenuState) != 0)
+ _engine->getScriptManager()->setStateValue(StateKey_MenuState, 0);
+ mouseOnItem = -1;
+ }
+}
+
+void MenuNemesis::process(uint32 deltatime) {
+ if (inmenu) {
+ if (!scrolled) {
+ float scrl = 32.0 * 2.0 * (deltatime / 1000.0);
+
+ if (scrl == 0)
+ scrl = 1.0;
+
+ scrollPos += scrl;
+ redraw = true;
+ }
+
+ if (scrollPos >= 0) {
+ scrolled = true;
+ scrollPos = 0;
+ }
+
+ if (mouseOnItem != -1) {
+ delay -= deltatime;
+ if (delay <= 0 && frm < 4) {
+ delay = 200;
+ frm++;
+ redraw = true;
+ }
+ }
+
+ if (redraw) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos);
+
+ if (menuBarFlag & menuBar_Exit)
+ if (mouseOnItem == menu_MAIN_EXIT)
+ _engine->getRenderManager()->blitSurfaceToMenu(but[3][frm], buts[3][1], scrollPos);
+
+ if (menuBarFlag & menuBar_Settings)
+ if (mouseOnItem == menu_MAIN_PREF)
+ _engine->getRenderManager()->blitSurfaceToMenu(but[2][frm], buts[2][1], scrollPos);
+
+ if (menuBarFlag & menuBar_Restore)
+ if (mouseOnItem == menu_MAIN_REST)
+ _engine->getRenderManager()->blitSurfaceToMenu(but[1][frm], buts[1][1], scrollPos);
+
+ if (menuBarFlag & menuBar_Save)
+ if (mouseOnItem == menu_MAIN_SAVE)
+ _engine->getRenderManager()->blitSurfaceToMenu(but[0][frm], buts[0][1], scrollPos);
+
+ redraw = false;
+ }
+ } else {
+ scrolled = false;
+ if (scrollPos > -32) {
+ float scrl = 32.0 * 2.0 * (deltatime / 1000.0);
+
+ if (scrl == 0)
+ scrl = 1.0;
+
+ Common::Rect cl(64, 32 + scrollPos - scrl, 64 + 512, 32 + scrollPos + 1);
+ _engine->getRenderManager()->clearMenuSurface(cl);
+
+ scrollPos -= scrl;
+ redraw = true;
+ } else
+ scrollPos = -32;
+
+ if (redraw) {
+ _engine->getRenderManager()->blitSurfaceToMenu(menubar, 64, scrollPos);
+ redraw = false;
+ }
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/core/menu.h b/engines/zvision/core/menu.h
index 3ab6d4c2ec..ebe0bb50ac 100644
--- a/engines/zvision/core/menu.h
+++ b/engines/zvision/core/menu.h
@@ -23,6 +23,103 @@
#ifndef ZVISION_MENU_H
#define ZVISION_MENU_H
-// TODO: Implement MenuHandler
+#include "graphics/surface.h"
+#include "common/rect.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+
+namespace ZVision {
+
+enum menuBar {
+ menuBar_Exit = 0x1,
+ menuBar_Settings = 0x2,
+ menuBar_Restore = 0x4,
+ menuBar_Save = 0x8,
+ menuBar_Items = 0x100,
+ menuBar_Magic = 0x200
+};
+
+class MenuHandler {
+public:
+ MenuHandler(ZVision *engine);
+ virtual ~MenuHandler() {};
+ virtual void onMouseMove(const Common::Point &Pos) {};
+ virtual void onMouseDown(const Common::Point &Pos) {};
+ virtual void onMouseUp(const Common::Point &Pos) {};
+ virtual void process(uint32 deltaTimeInMillis) {};
+
+ void setEnable(uint16 flags) {
+ menuBarFlag = flags;
+ }
+ uint16 getEnable() {
+ return menuBarFlag;
+ }
+protected:
+ uint16 menuBarFlag;
+ ZVision *_engine;
+};
+
+class MenuZGI: public MenuHandler {
+public:
+ MenuZGI(ZVision *engine);
+ ~MenuZGI();
+ void onMouseMove(const Common::Point &Pos);
+ void onMouseUp(const Common::Point &Pos);
+ void process(uint32 deltaTimeInMillis);
+private:
+ Graphics::Surface menuback[3][2];
+ Graphics::Surface menubar[4][2];
+ Graphics::Surface *items[50][2];
+ uint itemId[50];
+
+ Graphics::Surface *magic[12][2];
+ uint magicId[12];
+
+ int menuMouseFocus;
+ bool inmenu;
+
+ int mouseOnItem;
+
+ bool scrolled[3];
+ int16 scrollPos[3];
+
+ enum {
+ menu_ITEM = 0,
+ menu_MAGIC = 1,
+ menu_MAIN = 2
+ };
+
+ bool clean;
+ bool redraw;
+
+};
+
+class MenuNemesis: public MenuHandler {
+public:
+ MenuNemesis(ZVision *engine);
+ ~MenuNemesis();
+ void onMouseMove(const Common::Point &Pos);
+ void onMouseUp(const Common::Point &Pos);
+ void process(uint32 deltaTimeInMillis);
+private:
+ Graphics::Surface but[4][6];
+ Graphics::Surface menubar;
+
+ bool inmenu;
+
+ int mouseOnItem;
+
+ bool scrolled;
+ int16 scrollPos;
+
+ bool redraw;
+
+ int frm;
+ int16 delay;
+
+};
+
+}
#endif
diff --git a/engines/zvision/core/midi.cpp b/engines/zvision/core/midi.cpp
new file mode 100644
index 0000000000..736be1311d
--- /dev/null
+++ b/engines/zvision/core/midi.cpp
@@ -0,0 +1,89 @@
+/* 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 "zvision/core/midi.h"
+
+namespace ZVision {
+
+MidiManager::MidiManager() {
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
+ _driver = MidiDriver::createMidi(dev);
+ _driver->open();
+}
+
+MidiManager::~MidiManager() {
+ stop();
+ _driver->close();
+ delete _driver;
+}
+
+void MidiManager::stop() {
+ for (int8 i = 0; i < 16; i++)
+ if (_playChannels[i].playing)
+ noteOff(i);
+}
+
+void MidiManager::noteOn(int8 channel, int8 note, int8 velocity) {
+ assert(channel <= 15);
+
+ _playChannels[channel].playing = true;
+ _playChannels[channel].note = note;
+ _driver->send(channel | (velocity << 16) | (note << 8) | 0x90);
+}
+
+void MidiManager::noteOff(int8 channel) {
+ assert(channel <= 15);
+
+ if (_playChannels[channel].playing) {
+ _playChannels[channel].playing = false;
+ _driver->send(channel | (_playChannels[channel].note << 8) | 0x80);
+ }
+}
+
+int8 MidiManager::getFreeChannel() {
+ for (int8 i = 0; i < 16; i++)
+ if (!_playChannels[i].playing)
+ return i;
+ return -1;
+}
+
+void MidiManager::setPan(int8 channel, int8 pan) {
+ assert(channel <= 15);
+
+ _driver->send(channel | (pan << 16) | 0xAB0);
+}
+
+void MidiManager::setVolume(int8 channel, int8 volume) {
+ assert(channel <= 15);
+
+ _driver->send(channel | (volume << 16) | 0x7B0);
+}
+
+void MidiManager::setProgram(int8 channel, int8 prog) {
+ assert(channel <= 15);
+
+ _driver->send(channel | (prog << 8) | 0xC0);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/core/midi.h b/engines/zvision/core/midi.h
new file mode 100644
index 0000000000..a3bac19636
--- /dev/null
+++ b/engines/zvision/core/midi.h
@@ -0,0 +1,59 @@
+/* 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 ZVISION_MIDI_H
+#define ZVISION_MIDI_H
+
+#include "audio/mididrv.h"
+
+namespace ZVision {
+
+class MidiManager {
+public:
+ MidiManager();
+ ~MidiManager();
+
+ void stop();
+ void noteOn(int8 channel, int8 noteNumber, int8 velocity);
+ void noteOff(int8 channel);
+ void setPan(int8 channel, int8 pan);
+ void setVolume(int8 channel, int8 volume);
+ void setProgram(int8 channel, int8 prog);
+
+ int8 getFreeChannel();
+
+protected:
+
+ struct chan {
+ bool playing;
+ int8 note;
+
+ chan() : playing(false), note(0) {};
+ };
+
+ MidiDriver *_driver;
+ chan _playChannels[16];
+};
+
+}
+
+#endif
diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp
index 07fb7637e7..20bd39fde5 100644
--- a/engines/zvision/core/save_manager.cpp
+++ b/engines/zvision/core/save_manager.cpp
@@ -23,90 +23,120 @@
#include "common/scummsys.h"
#include "zvision/core/save_manager.h"
-
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
#include "common/system.h"
+#include "common/translation.h"
#include "graphics/surface.h"
#include "graphics/thumbnail.h"
#include "gui/message.h"
-
+#include "gui/saveload.h"
namespace ZVision {
const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G');
+bool SaveManager::scummVMSaveLoadDialog(bool isSave) {
+ GUI::SaveLoadChooser *dialog;
+ Common::String desc;
+ int slot;
+
+ if (isSave) {
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ slot = dialog->runModalWithCurrentTarget();
+ desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ // create our own description for the saved game, the user didnt enter it
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+
+ if (desc.size() > 28)
+ desc = Common::String(desc.c_str(), 28);
+ } else {
+ dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ slot = dialog->runModalWithCurrentTarget();
+ }
+
+ delete dialog;
+
+ if (slot < 0)
+ return false;
+
+ if (isSave) {
+ saveGame(slot, desc);
+ return true;
+ } else {
+ Common::ErrorCode result = loadGame(slot).getCode();
+ return (result == Common::kNoError);
+ }
+}
+
void SaveManager::saveGame(uint slot, const Common::String &saveName) {
// The games only support 20 slots
- assert(slot <= 1 && slot <= 20);
+ //assert(slot <= 1 && slot <= 20);
Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
- // Write out the savegame header
- file->writeUint32BE(SAVEGAME_ID);
+ writeSaveGameHeader(file, saveName);
- // Write version
- file->writeByte(SAVE_VERSION);
+ _engine->getScriptManager()->serialize(file);
- // Write savegame name
- file->writeString(saveName);
- file->writeByte(0);
-
- // We can't call writeGameSaveData because the save menu is actually
- // a room, so writeGameSaveData would save us in the save menu.
- // However, an auto save is performed before each room change, so we
- // can copy the data from there. We can guarantee that an auto save file will
- // exist before this is called because the save menu can only be accessed
- // after the first room (the main menu) has loaded.
- Common::InSaveFile *autoSaveFile = saveFileManager->openForLoading(_engine->generateAutoSaveFileName());
+ file->finalize();
+ delete file;
+}
- // Skip over the header info
- autoSaveFile->readSint32BE(); // SAVEGAME_ID
- autoSaveFile->readByte(); // Version
- autoSaveFile->seek(5, SEEK_CUR); // The string "auto" with terminating NULL
+void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) {
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
- // Read the rest to a buffer
- uint32 size = autoSaveFile->size() - autoSaveFile->pos();
- byte *buffer = new byte[size];
- autoSaveFile->read(buffer, size);
+ writeSaveGameHeader(file, saveName);
- // Then write the buffer to the new file
- file->write(buffer, size);
+ file->write(stream->getData(), stream->size());
- // Cleanup
- delete[] buffer;
file->finalize();
delete file;
}
+void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) {
+ if (_tempSave) {
+ saveGame(slot, saveName, _tempSave);
+ flushSaveBuffer();
+ }
+}
+
void SaveManager::autoSave() {
Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving(_engine->generateAutoSaveFileName());
- // Write out the savegame header
- file->writeUint32BE(SAVEGAME_ID);
-
- // Version
- file->writeByte(SAVE_VERSION);
-
- file->writeString("auto");
- file->writeByte(0);
+ writeSaveGameHeader(file, "auto");
- writeSaveGameData(file);
+ _engine->getScriptManager()->serialize(file);
// Cleanup
file->finalize();
delete file;
}
-void SaveManager::writeSaveGameData(Common::OutSaveFile *file) {
+void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) {
+
+ file->writeUint32BE(SAVEGAME_ID);
+
+ // Write version
+ file->writeByte(SAVE_VERSION);
+
+ // Write savegame name
+ file->writeString(saveName);
+ file->writeByte(0);
+
// Create a thumbnail and save it
Graphics::saveThumbnail(*file);
-
+
// Write out the save date/time
TimeDate td;
g_system->getTimeAndDate(td);
@@ -115,28 +145,13 @@ void SaveManager::writeSaveGameData(Common::OutSaveFile *file) {
file->writeSint16LE(td.tm_mday);
file->writeSint16LE(td.tm_hour);
file->writeSint16LE(td.tm_min);
-
- ScriptManager *scriptManager = _engine->getScriptManager();
- // Write out the current location
- Location currentLocation = scriptManager->getCurrentLocation();
- file->writeByte(currentLocation.world);
- file->writeByte(currentLocation.room);
- file->writeByte(currentLocation.node);
- file->writeByte(currentLocation.view);
- file->writeUint32LE(currentLocation.offset);
-
- // Write out the current state table values
- scriptManager->serializeStateTable(file);
-
- // Write out any controls needing to save state
- scriptManager->serializeControls(file);
}
Common::Error SaveManager::loadGame(uint slot) {
// The games only support 20 slots
- assert(slot <= 1 && slot <= 20);
+ //assert(slot <= 1 && slot <= 20);
- Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ Common::SeekableReadStream *saveFile = getSlotFile(slot);
if (saveFile == 0) {
return Common::kPathDoesNotExist;
}
@@ -147,31 +162,64 @@ Common::Error SaveManager::loadGame(uint slot) {
return Common::kUnknownError;
}
- char world = (char)saveFile->readByte();
- char room = (char)saveFile->readByte();
- char node = (char)saveFile->readByte();
- char view = (char)saveFile->readByte();
- uint32 offset = (char)saveFile->readUint32LE();
-
ScriptManager *scriptManager = _engine->getScriptManager();
// Update the state table values
- scriptManager->deserializeStateTable(saveFile);
+ scriptManager->deserialize(saveFile);
+
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
+
+ return Common::kNoError;
+}
+
+Common::Error SaveManager::loadGame(const Common::String &saveName) {
+ Common::File *saveFile = _engine->getSearchManager()->openFile(saveName);
+ if (saveFile == NULL) {
+ saveFile = new Common::File;
+ if (!saveFile->open(saveName)) {
+ delete saveFile;
+ return Common::kPathDoesNotExist;
+ }
+ }
+
+ // Read the header
+ SaveGameHeader header;
+ if (!readSaveGameHeader(saveFile, header)) {
+ return Common::kUnknownError;
+ }
- // Load the room
- scriptManager->changeLocation(world, room, node, view, offset);
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Update the state table values
+ scriptManager->deserialize(saveFile);
- // Update the controls
- scriptManager->deserializeControls(saveFile);
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
return Common::kNoError;
}
bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
- if (in->readUint32BE() != SAVEGAME_ID) {
+ uint32 tag = in->readUint32BE();
+ // Check if it's original savegame than fill header structure
+ if (tag == MKTAG('Z', 'N', 'S', 'G')) {
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.saveName = "Original Save";
+ header.thumbnail = NULL;
+ header.version = SAVE_ORIGINAL;
+ in->seek(-4, SEEK_CUR);
+ return true;
+ }
+ if (tag != SAVEGAME_ID) {
warning("File is not a ZVision save file. Aborting load");
return false;
}
-
+
// Read in the version
header.version = in->readByte();
@@ -203,4 +251,45 @@ bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &hea
return true;
}
+Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) {
+ Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ if (saveFile == NULL) {
+ // Try to load standard save file
+ Common::String filename;
+ if (_engine->getGameId() == GID_GRANDINQUISITOR)
+ filename = Common::String::format("inqsav%u.sav", slot);
+ else if (_engine->getGameId() == GID_NEMESIS)
+ filename = Common::String::format("nemsav%u.sav", slot);
+
+ saveFile = _engine->getSearchManager()->openFile(filename);
+ if (saveFile == NULL) {
+ Common::File *tmpFile = new Common::File;
+ if (!tmpFile->open(filename)) {
+ delete tmpFile;
+ } else {
+ saveFile = tmpFile;
+ }
+ }
+
+ }
+
+ return saveFile;
+}
+
+void SaveManager::prepareSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = new Common::MemoryWriteStreamDynamic;
+
+ _engine->getScriptManager()->serialize(_tempSave);
+}
+
+void SaveManager::flushSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = NULL;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/core/save_manager.h b/engines/zvision/core/save_manager.h
index 43fb0c0faf..75841331e7 100644
--- a/engines/zvision/core/save_manager.h
+++ b/engines/zvision/core/save_manager.h
@@ -24,6 +24,7 @@
#define ZVISION_SAVE_MANAGER_H
#include "common/savefile.h"
+#include "common/memstream.h"
namespace Common {
class String;
@@ -47,16 +48,22 @@ struct SaveGameHeader {
class SaveManager {
public:
- SaveManager(ZVision *engine) : _engine(engine) {}
+ SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL) {}
+ ~SaveManager() {
+ flushSaveBuffer();
+ }
private:
ZVision *_engine;
static const uint32 SAVEGAME_ID;
enum {
+ SAVE_ORIGINAL = 0,
SAVE_VERSION = 1
};
+ Common::MemoryWriteStreamDynamic *_tempSave;
+
public:
/**
* Called every room change. Saves the state of the room just before
@@ -73,6 +80,8 @@ public:
* @param saveName The internal name for this save. This is NOT the name of the actual save file.
*/
void saveGame(uint slot, const Common::String &saveName);
+ void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream);
+ void saveGameBuffered(uint slot, const Common::String &saveName);
/**
* Loads the state data from the save file that slot references. Uses
* ZVision::generateSaveFileName(slot) to get the save file name.
@@ -80,10 +89,16 @@ public:
* @param slot The save slot to load. Must be [1, 20]
*/
Common::Error loadGame(uint slot);
+ Common::Error loadGame(const Common::String &saveName);
+
+ Common::SeekableReadStream *getSlotFile(uint slot);
+ bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header);
+ void prepareSaveBuffer();
+ void flushSaveBuffer();
+ bool scummVMSaveLoadDialog(bool isSave);
private:
- void writeSaveGameData(Common::OutSaveFile *file);
- bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header);
+ void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName);
};
} // End of namespace ZVision
diff --git a/engines/zvision/core/search_manager.cpp b/engines/zvision/core/search_manager.cpp
new file mode 100644
index 0000000000..9c5d8fb323
--- /dev/null
+++ b/engines/zvision/core/search_manager.cpp
@@ -0,0 +1,273 @@
+/* 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/debug.h"
+#include "common/fs.h"
+#include "common/stream.h"
+
+#include "zvision/core/search_manager.h"
+#include "zvision/utility/zfs_archive.h"
+
+namespace ZVision {
+
+SearchManager::SearchManager(const Common::String &rootPath, int depth) {
+ _root = rootPath;
+ if (_root[_root.size() - 1] == '\\' || _root[_root.size() - 1] == '/')
+ _root.deleteLastChar();
+
+ Common::FSNode fsNode(_root);
+
+ listDirRecursive(dirList, fsNode, depth);
+
+ for (Common::List<Common::String>::iterator it = dirList.begin(); it != dirList.end();)
+ if (it->size() == _root.size())
+ it = dirList.erase(it);
+ else if (it->size() > _root.size()) {
+ *it = Common::String(it->c_str() + _root.size() + 1);
+ it++;
+ } else
+ it++;
+}
+
+SearchManager::~SearchManager() {
+ Common::List<Common::Archive *>::iterator it = archList.begin();
+ while (it != archList.end()) {
+ delete *it;
+ it++;
+ }
+
+ archList.clear();
+}
+
+void SearchManager::addPatch(const Common::String &src, const Common::String &dst) {
+ Common::String lowerCaseName = dst;
+ lowerCaseName.toLowercase();
+
+ SearchManager::MatchList::iterator it = files.find(lowerCaseName);
+
+ if (it != files.end()) {
+ lowerCaseName = src;
+ lowerCaseName.toLowercase();
+ files[lowerCaseName] = it->_value;
+ }
+}
+
+void SearchManager::addFile(const Common::String &name, Common::Archive *arch) {
+ bool addArch = true;
+ Common::List<Common::Archive *>::iterator it = archList.begin();
+ while (it != archList.end()) {
+ if (*it == arch) {
+ addArch = false;
+ break;
+ }
+ it++;
+ }
+ if (addArch)
+ archList.push_back(arch);
+
+ Common::String lowerCaseName = name;
+ lowerCaseName.toLowercase();
+
+ SearchManager::Node nod;
+ nod.name = lowerCaseName;
+ nod.arch = arch;
+
+ SearchManager::MatchList::iterator fit = files.find(lowerCaseName);
+
+ if (fit == files.end()) {
+ files[lowerCaseName] = nod;
+ } else {
+ Common::SeekableReadStream *stream = fit->_value.arch->createReadStreamForMember(fit->_value.name);
+ if (stream) {
+ if (stream->size() < 10)
+ fit->_value.arch = arch;
+ delete stream;
+ } else {
+ files[lowerCaseName] = nod;
+ }
+ }
+}
+
+Common::File *SearchManager::openFile(const Common::String &name) {
+ Common::String lowerCaseName = name;
+ lowerCaseName.toLowercase();
+
+ SearchManager::MatchList::iterator fit = files.find(lowerCaseName);
+
+ if (fit != files.end()) {
+ Common::File *tmp = new Common::File();
+ tmp->open(fit->_value.name, *fit->_value.arch);
+ return tmp;
+ }
+ return NULL;
+}
+
+bool SearchManager::openFile(Common::File &file, const Common::String &name) {
+ Common::String lowerCaseName = name;
+ lowerCaseName.toLowercase();
+
+ SearchManager::MatchList::iterator fit = files.find(lowerCaseName);
+
+ if (fit != files.end())
+ return file.open(fit->_value.name, *fit->_value.arch);
+ return false;
+}
+
+bool SearchManager::hasFile(const Common::String &name) {
+ Common::String lowerCaseName = name;
+ lowerCaseName.toLowercase();
+
+ SearchManager::MatchList::iterator fit = files.find(lowerCaseName);
+
+ if (fit != files.end())
+ return true;
+ return false;
+}
+
+void SearchManager::loadZix(const Common::String &name) {
+ Common::File file;
+ file.open(name);
+
+ Common::String line;
+
+ while (!file.eos()) {
+ line = file.readLine();
+ if (line.matchString("----------*", true))
+ break;
+ }
+
+ if (file.eos())
+ return;
+
+ Common::Array<Common::Archive *> archives;
+
+ while (!file.eos()) {
+ line = file.readLine();
+ line.trim();
+ if (line.matchString("----------*", true))
+ break;
+ else if (line.matchString("DIR:*", true)) {
+ Common::String path(line.c_str() + 5);
+ Common::Archive *arc;
+ char tempPath[128];
+ strcpy(tempPath, path.c_str());
+ for (uint i = 0; i < path.size(); i++)
+ if (tempPath[i] == '\\')
+ tempPath[i] = '/';
+
+ path = Common::String(tempPath);
+ if (path.size() && path[0] == '.')
+ path.deleteChar(0);
+ if (path.size() && path[0] == '/')
+ path.deleteChar(0);
+
+ if (path.matchString("*.zfs", true))
+ arc = new ZfsArchive(path);
+ else {
+ if (path.size()) {
+ if (path[path.size() - 1] == '\\' || path[path.size() - 1] == '/')
+ path.deleteLastChar();
+ if (path.size())
+ for (Common::List<Common::String>::iterator it = dirList.begin(); it != dirList.end(); ++it)
+ if (path.equalsIgnoreCase(*it)) {
+ path = *it;
+ break;
+ }
+ }
+
+ path = Common::String::format("%s/%s", _root.c_str(), path.c_str());
+
+ arc = new Common::FSDirectory(path);
+ }
+ archives.push_back(arc);
+ }
+ }
+
+ if (file.eos())
+ return;
+
+ while (!file.eos()) {
+ line = file.readLine();
+ line.trim();
+ uint dr = 0;
+ char buf[32];
+ if (sscanf(line.c_str(), "%u %s", &dr, buf) == 2) {
+ if (dr <= archives.size() && dr > 0) {
+ addFile(Common::String(buf), archives[dr - 1]);
+ }
+ }
+ }
+}
+
+void SearchManager::addDir(const Common::String &name) {
+ Common::String path;
+ for (Common::List<Common::String>::iterator it = dirList.begin(); it != dirList.end(); ++it)
+ if (name.equalsIgnoreCase(*it)) {
+ path = *it;
+ break;
+ }
+
+ if (path.size() == 0)
+ return;
+
+ path = Common::String::format("%s/%s", _root.c_str(), path.c_str());
+
+ Common::FSDirectory *dir = new Common::FSDirectory(path);
+
+ Common::ArchiveMemberList list;
+ dir->listMatchingMembers(list, "*.zfs");
+
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ Common::String flname = (*iter)->getName();
+
+ ZfsArchive *zfs = new ZfsArchive(Common::String::format("%s/%s", name.c_str(), flname.c_str()));
+
+ Common::ArchiveMemberList zfslist;
+ zfs->listMembers(zfslist);
+
+ for (Common::ArchiveMemberList::iterator ziter = zfslist.begin(); ziter != zfslist.end(); ++ziter) {
+ Common::String zfsFileName = (*ziter)->getName();
+ addFile(zfsFileName, zfs);
+ }
+ }
+
+ list.clear();
+ dir->listMembers(list);
+
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ Common::String flname = (*iter)->getName();
+ addFile(flname, dir);
+ }
+}
+
+void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const Common::FSNode &fsNode, int depth) {
+ Common::FSList fsList;
+ fsNode.getChildren(fsList);
+
+ _list.push_back(fsNode.getPath());
+
+ if (depth > 1)
+ for (Common::FSList::const_iterator it = fsList.begin(); it != fsList.end(); ++it)
+ listDirRecursive(_list, *it, depth - 1);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/core/search_manager.h b/engines/zvision/core/search_manager.h
new file mode 100644
index 0000000000..180102eac6
--- /dev/null
+++ b/engines/zvision/core/search_manager.h
@@ -0,0 +1,73 @@
+/* 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 ZVISION_SEARCH_MANAGER_H
+#define ZVISION_SEARCH_MANAGER_H
+
+#include "common/str.h"
+#include "common/hash-str.h"
+#include "common/hashmap.h"
+#include "common/archive.h"
+#include "common/file.h"
+#include "common/list.h"
+
+namespace ZVision {
+
+class SearchManager {
+public:
+ SearchManager(const Common::String &rootPath, int depth);
+ ~SearchManager();
+
+ void addFile(const Common::String &name, Common::Archive *arch);
+ void addDir(const Common::String &name);
+ void addPatch(const Common::String &src, const Common::String &dst);
+
+ Common::File *openFile(const Common::String &name);
+ bool openFile(Common::File &file, const Common::String &name);
+ bool hasFile(const Common::String &name);
+
+ void loadZix(const Common::String &name);
+
+private:
+
+ void listDirRecursive(Common::List<Common::String> &dirList, const Common::FSNode &fsNode, int depth);
+
+ struct Node {
+ Common::String name;
+ Common::Archive *arch;
+ };
+
+ Common::List<Common::String> dirList;
+
+ typedef Common::HashMap<Common::String, Node, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MatchList;
+
+ Common::List<Common::Archive *> archList;
+ MatchList files;
+
+ Common::String _root;
+
+private:
+};
+
+}
+
+#endif // ZVISION_SEARCH_MANAGER_H
diff --git a/engines/zvision/cursors/cursor.cpp b/engines/zvision/cursors/cursor.cpp
index 9b9b9a3f71..b07220df92 100644
--- a/engines/zvision/cursors/cursor.cpp
+++ b/engines/zvision/cursors/cursor.cpp
@@ -1,24 +1,24 @@
/* 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.
- *
- */
+*
+* 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"
@@ -27,7 +27,6 @@
#include "common/str.h"
#include "common/file.h"
-
namespace ZVision {
ZorkCursor::ZorkCursor()
@@ -38,10 +37,10 @@ ZorkCursor::ZorkCursor()
}
ZorkCursor::ZorkCursor(const Common::String &fileName)
- : _width(0),
- _height(0),
- _hotspotX(0),
- _hotspotY(0) {
+ : _width(0),
+ _height(0),
+ _hotspotX(0),
+ _hotspotY(0) {
Common::File file;
if (!file.open(fileName))
return;
@@ -66,6 +65,35 @@ ZorkCursor::ZorkCursor(const Common::String &fileName)
_surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
}
+ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName)
+ : _width(0),
+ _height(0),
+ _hotspotX(0),
+ _hotspotY(0) {
+ Common::File file;
+ if (!engine->getSearchManager()->openFile(file, fileName))
+ return;
+
+ uint32 magic = file.readUint32BE();
+ if (magic != MKTAG('Z', 'C', 'R', '1')) {
+ warning("%s is not a Zork Cursor file", fileName.c_str());
+ return;
+ }
+
+ _hotspotX = file.readUint16LE();
+ _hotspotY = file.readUint16LE();
+ _width = file.readUint16LE();
+ _height = file.readUint16LE();
+
+ uint dataSize = _width * _height * sizeof(uint16);
+ _surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
+ uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
+ assert(bytesRead == dataSize);
+
+ // Convert to RGB 565
+ _surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+}
+
ZorkCursor::ZorkCursor(const ZorkCursor &other) {
_width = other._width;
_height = other._height;
diff --git a/engines/zvision/cursors/cursor.h b/engines/zvision/cursors/cursor.h
index be9fae64da..0c1e99411f 100644
--- a/engines/zvision/cursors/cursor.h
+++ b/engines/zvision/cursors/cursor.h
@@ -24,7 +24,7 @@
#define ZVISION_CURSOR_H
#include "graphics/surface.h"
-
+#include "zvision/zvision.h"
namespace Common {
class String;
@@ -40,6 +40,7 @@ class ZorkCursor {
public:
ZorkCursor();
ZorkCursor(const Common::String &fileName);
+ ZorkCursor(ZVision *engine, const Common::String &fileName);
ZorkCursor(const ZorkCursor &other);
~ZorkCursor();
@@ -53,12 +54,24 @@ private:
public:
ZorkCursor &operator=(const ZorkCursor &other);
- uint16 getWidth() const { return _width; }
- uint16 getHeight() const { return _height; }
- uint16 getHotspotX() const { return _hotspotX; }
- uint16 getHotspotY() const { return _hotspotY; }
- byte getKeyColor() const { return 0; }
- const byte *getSurface() const { return (const byte *)_surface.getPixels(); }
+ uint16 getWidth() const {
+ return _width;
+ }
+ uint16 getHeight() const {
+ return _height;
+ }
+ uint16 getHotspotX() const {
+ return _hotspotX;
+ }
+ uint16 getHotspotY() const {
+ return _hotspotY;
+ }
+ byte getKeyColor() const {
+ return 0;
+ }
+ const byte *getSurface() const {
+ return (const byte *)_surface.getPixels();
+ }
};
} // End of namespace ZVision
diff --git a/engines/zvision/cursors/cursor_manager.cpp b/engines/zvision/cursors/cursor_manager.cpp
index 7f70c8b4e3..33fb55515b 100644
--- a/engines/zvision/cursors/cursor_manager.cpp
+++ b/engines/zvision/cursors/cursor_manager.cpp
@@ -1,24 +1,24 @@
/* 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.
- *
- */
+*
+* 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"
@@ -31,86 +31,76 @@
#include "graphics/pixelformat.h"
#include "graphics/cursorman.h"
-
namespace ZVision {
const char *CursorManager::_cursorNames[NUM_CURSORS] = { "active", "arrow", "backward", "downarrow", "forward", "handpt", "handpu", "hdown", "hleft",
- "hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow" };
+ "hright", "hup", "idle", "leftarrow", "rightarrow", "suggest_surround", "suggest_tilt", "turnaround", "zuparrow"
+ };
const char *CursorManager::_zgiCursorFileNames[NUM_CURSORS] = { "g0gbc011.zcr", "g0gac001.zcr", "g0gac021.zcr", "g0gac031.zcr", "g0gac041.zcr", "g0gac051.zcr", "g0gac061.zcr", "g0gac071.zcr", "g0gac081.zcr",
- "g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr" };
+ "g0gac091.zcr", "g0gac101.zcr", "g0gac011.zcr", "g0gac111.zcr", "g0gac121.zcr", "g0gac131.zcr", "g0gac141.zcr", "g0gac151.zcr", "g0gac161.zcr"
+ };
const char *CursorManager::_zNemCursorFileNames[NUM_CURSORS] = { "00act", "arrow", "back", "down", "forw", "handpt", "handpu", "hdown", "hleft",
- "hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up" };
-
+ "hright", "hup", "00idle", "left", "right", "ssurr", "stilt", "turn", "up"
+ };
CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat)
- : _engine(engine),
- _pixelFormat(pixelFormat),
- _cursorIsPushed(false) {
- // WARNING: The index IDLE_CURSOR_INDEX is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
- if (_engine->getGameId() == GID_NEMESIS) {
- Common::String name(Common::String::format("%sa.zcr", _zNemCursorFileNames[IDLE_CURSOR_INDEX]));
- _idleCursor = ZorkCursor(name);
- } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
- _idleCursor = ZorkCursor(_zgiCursorFileNames[IDLE_CURSOR_INDEX]);
+ : _engine(engine),
+ _pixelFormat(pixelFormat),
+ _cursorIsPushed(false),
+ _item(0),
+ _lastitem(0) {
+ for (int i = 0; i < NUM_CURSORS; i++) {
+ if (_engine->getGameId() == GID_NEMESIS) {
+ Common::String name;
+ name = Common::String::format("%sa.zcr", _zNemCursorFileNames[i]);
+ _cursors[i][0] = ZorkCursor(_engine, name); // Up cursor
+ name = Common::String::format("%sb.zcr", _zNemCursorFileNames[i]);
+ _cursors[i][1] = ZorkCursor(_engine, name); // Down cursor
+ } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ _cursors[i][0] = ZorkCursor(_engine, _zgiCursorFileNames[i]); // Up cursor
+ char buffer[25];
+ strcpy(buffer, _zgiCursorFileNames[i]);
+ buffer[3] += 2;
+ _cursors[i][1] = ZorkCursor(_engine, buffer); // Down cursor
+ }
}
}
-void CursorManager::initialize() {
- revertToIdle();
- CursorMan.showMouse(true);
-}
-
-void CursorManager::changeCursor(const Common::String &cursorName) {
- changeCursor(cursorName, _cursorIsPushed);
-}
-
-void CursorManager::changeCursor(const Common::String &cursorName, bool pushed) {
- if (_currentCursor.equals(cursorName) && _cursorIsPushed == pushed)
- return;
-
- if (_cursorIsPushed != pushed)
- _cursorIsPushed = pushed;
-
- if (cursorName == "idle" && !pushed) {
- CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
- return;
- }
-
- for (int i = 0; i < NUM_CURSORS; ++i) {
- if (_engine->getGameId() == GID_NEMESIS) {
- if (cursorName.equals(_cursorNames[i])) {
- _currentCursor = cursorName;
-
- // ZNem uses a/b at the end of the file to signify not pushed/pushed respectively
- Common::String pushedFlag = pushed ? "b" : "a";
- Common::String name = Common::String::format("%s%s.zcr", _zNemCursorFileNames[i], pushedFlag.c_str());
-
- changeCursor(ZorkCursor(name));
+void CursorManager::setItemID(int id) {
+ if (id != _item) {
+ if (id) {
+ Common::String file;
+ if (_engine->getGameId() == GID_NEMESIS) {
+ file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'a');
+ _cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
+ file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b');
+ _cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
+ file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'a');
+ _cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+ file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'b');
+ _cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+ } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ file = Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id);
+ _cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
+ file = Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id);
+ _cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
+ file = Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id);
+ _cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
+ file = Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id);
+ _cursors[NUM_CURSORS + 1][1] = ZorkCursor(_engine, file);
+ } else
return;
- }
- } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
- if (cursorName.equals(_cursorNames[i])) {
- _currentCursor = cursorName;
-
- if (!pushed) {
- changeCursor(ZorkCursor(_zgiCursorFileNames[i]));
- } else {
- // ZGI flips not pushed/pushed between a/c and b/d
- // It flips the 4th character of the name
- char buffer[25];
- strcpy(buffer, _zgiCursorFileNames[i]);
- buffer[3] += 2;
- changeCursor(ZorkCursor(buffer));
- }
- return;
- }
}
+ _item = id;
+ changeCursor(CursorIndex_Idle);
}
+}
- // If we get here, something went wrong
- warning("No cursor found for identifier %s", cursorName.c_str());
+void CursorManager::initialize() {
+ changeCursor(_cursors[CursorIndex_Idle][_cursorIsPushed]);
+ showMouse(true);
}
void CursorManager::changeCursor(const ZorkCursor &cursor) {
@@ -122,31 +112,41 @@ void CursorManager::cursorDown(bool pushed) {
return;
_cursorIsPushed = pushed;
- changeCursor(_currentCursor, pushed);
-}
-void CursorManager::setLeftCursor() {
- changeCursor("leftarrow");
+ changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
}
-void CursorManager::setRightCursor() {
- changeCursor("rightarrow");
-}
+void CursorManager::changeCursor(int id) {
+ int _id = id;
+
+ if (_item &&
+ (_id == CursorIndex_Active ||
+ _id == CursorIndex_Idle ||
+ _id == CursorIndex_HandPu)) {
-void CursorManager::setUpCursor() {
- changeCursor("zuparrow");
+ if (_id == CursorIndex_Idle)
+ _id = CursorIndex_ItemIdle;
+ else
+ _id = CursorIndex_ItemAct;
+ }
+
+ if (_currentCursor != _id ||
+ ((_id == CursorIndex_ItemAct || _id == CursorIndex_ItemIdle) && _lastitem != _item)) {
+ _currentCursor = _id;
+ _lastitem = _item;
+ changeCursor(_cursors[_currentCursor][_cursorIsPushed]);
+ }
}
-void CursorManager::setDownCursor() {
- changeCursor("downarrow");
+int CursorManager::getCursorId(const Common::String &name) {
+ for (int i = 0; i < NUM_CURSORS; i++)
+ if (name.equals(_cursorNames[i]))
+ return i;
+ return CursorIndex_Idle;
}
-void CursorManager::revertToIdle() {
- _currentCursor = "idle";
- if (!_cursorIsPushed)
- CursorMan.replaceCursor(_idleCursor.getSurface(), _idleCursor.getWidth(), _idleCursor.getHeight(), _idleCursor.getHotspotX(), _idleCursor.getHotspotY(), _idleCursor.getKeyColor(), false, _pixelFormat);
- else
- changeCursor(_currentCursor, _cursorIsPushed);
+void CursorManager::showMouse(bool vis) {
+ CursorMan.showMouse(vis);
}
} // End of namespace ZVision
diff --git a/engines/zvision/cursors/cursor_manager.h b/engines/zvision/cursors/cursor_manager.h
index 0576517f58..460f6fade6 100644
--- a/engines/zvision/cursors/cursor_manager.h
+++ b/engines/zvision/cursors/cursor_manager.h
@@ -8,12 +8,12 @@
* 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.
@@ -27,7 +27,6 @@
#include "common/str.h"
-
namespace Graphics {
struct PixelFormat;
}
@@ -37,6 +36,21 @@ namespace ZVision {
class ZVision;
/**
+ * Mostly usable cursors
+ */
+enum CursorIndex {
+ CursorIndex_Active = 0,
+ CursorIndex_DownArr = 3,
+ CursorIndex_HandPu = 6,
+ CursorIndex_Idle = 11,
+ CursorIndex_Left = 12,
+ CursorIndex_Right = 13,
+ CursorIndex_UpArr = 17,
+ CursorIndex_ItemIdle = 18,
+ CursorIndex_ItemAct = 19
+};
+
+/**
* Class to manage cursor changes. The actual changes have to be done
* through CursorMan. Otherwise the cursor will disappear after GMM
* or debug console.
@@ -47,17 +61,17 @@ public:
CursorManager(ZVision *engine, const Graphics::PixelFormat *pixelFormat);
private:
- enum {
- NUM_CURSORS = 18,
- // WARNING: The index 11 is hardcoded. If you change the order of _cursorNames/_zgiCursorFileNames/_zNemCursorFileNames, you HAVE to change the index accordingly
- IDLE_CURSOR_INDEX = 11
- };
+ static const int NUM_CURSORS = 18;
+
+ // 18 default cursors in up/down states, +2 for items idle/act cursors
+ ZorkCursor _cursors[NUM_CURSORS + 2][2];
ZVision *_engine;
const Graphics::PixelFormat *_pixelFormat;
- ZorkCursor _idleCursor;
- Common::String _currentCursor;
bool _cursorIsPushed;
+ int _item;
+ int _lastitem;
+ int _currentCursor;
static const char *_cursorNames[];
static const char *_zgiCursorFileNames[];
@@ -68,19 +82,30 @@ public:
void initialize();
/**
- * Parses a cursor name into a cursor file then creates and shows that cursor.
- * It will use the current _isCursorPushed state to choose the correct cursor
+ * Change cursor to specified cursor ID. If item setted to not 0 and cursor id idle/acrive/handpu change cursor to item.
+ *
+ * @param id Wanted cursor id.
+ */
+
+ void changeCursor(int id);
+
+ /**
+ * Return founded id for string contains cursor name
*
- * @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
+ * @param name Cursor name
+ * @return Id of cursor or idle cursor id if not found
*/
- void changeCursor(const Common::String &cursorName);
+
+ int getCursorId(const Common::String &name);
+
/**
- * Parses a cursor name into a cursor file then creates and shows that cursor.
+ * Load cursor for item by id, and try to change cursor to item cursor if it's not 0
*
- * @param cursorName The name of a cursor. This *HAS* to correspond to one of the entries in _cursorNames[]
- * @param pushed Should the cursor be pushed (true) or not pushed (false) (Another way to say it: down or up)
+ * @param id Item id or 0 for no item cursor
*/
- void changeCursor(const Common::String &cursorName, bool pushed);
+
+ void setItemID(int id);
+
/**
* Change the cursor to a certain push state. If the cursor is already in the specified push state, nothing will happen.
*
@@ -88,17 +113,12 @@ public:
*/
void cursorDown(bool pushed);
- /** Set the cursor to 'Left Arrow'. It will retain the current _isCursorPushed state */
- void setLeftCursor();
- /** Set the cursor to 'Right Arrow'. It will retain the current _isCursorPushed state */
- void setRightCursor();
- /** Set the cursor to 'Up Arrow'. It will retain the current _isCursorPushed state */
- void setUpCursor();
- /** Set the cursor to 'Down Arrow'. It will retain the current _isCursorPushed state */
- void setDownCursor();
-
- /** Set the cursor to 'Idle'. It will retain the current _isCursorPushed state */
- void revertToIdle();
+ /**
+ * Show or hide mouse cursor.
+ *
+ * @param vis Should the cursor be showed (true) or hide (false)
+ */
+ void showMouse(bool vis);
private:
/**
diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp
index 9961db1215..ebf5bdcfdd 100644
--- a/engines/zvision/detection.cpp
+++ b/engines/zvision/detection.cpp
@@ -26,13 +26,14 @@
#include "zvision/zvision.h"
#include "zvision/detection.h"
+#include "zvision/core/save_manager.h"
+#include "zvision/scripting/script_manager.h"
#include "common/translation.h"
#include "common/savefile.h"
#include "common/str-array.h"
#include "common/system.h"
-
namespace ZVision {
uint32 ZVision::getFeatures() const {
@@ -45,7 +46,6 @@ Common::Language ZVision::getLanguage() const {
} // End of namespace ZVision
-
static const PlainGameDescriptor zVisionGames[] = {
{"zvision", "ZVision Game"},
{"znemesis", "Zork Nemesis: The Forbidden Lands"},
@@ -53,7 +53,6 @@ static const PlainGameDescriptor zVisionGames[] = {
{0, 0}
};
-
namespace ZVision {
static const ZVisionGameDescription gameDescriptions[] = {
@@ -73,10 +72,24 @@ static const ZVisionGameDescription gameDescriptions[] = {
},
{
- // Zork Grand Inquisitor English version
+ // Zork Nemesis English demo version
+ {
+ "znemesis",
+ "Demo",
+ AD_ENTRY1s("SCRIPTS.ZFS", "64f1e881394e9462305104f99513c833", 380539),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
+ GID_NEMESIS
+ },
+
+ {
+ // Zork Grand Inquisitor English CD version
{
"zgi",
- 0,
+ "CD",
AD_ENTRY1s("SCRIPTS.ZFS", "81efd40ecc3d22531e211368b779f17f", 8336944),
Common::EN_ANY,
Common::kPlatformWindows,
@@ -87,6 +100,34 @@ static const ZVisionGameDescription gameDescriptions[] = {
},
{
+ // Zork Grand Inquisitor English demo version
+ {
+ "zgi",
+ "Demo",
+ AD_ENTRY1s("SCRIPTS.ZFS", "71a2494fd2fb999347deb13401e9b998", 304239),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
+ GID_GRANDINQUISITOR
+ },
+
+ {
+ // Zork Grand Inquisitor English DVD version
+ {
+ "zgi",
+ "DVD",
+ AD_ENTRY1s("SCRIPTS.ZFS", "03157a3399513bfaaf8dc6d5ab798b36", 8433326),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ GID_GRANDINQUISITOR
+ },
+
+ {
AD_TABLE_END_MARKER,
GID_NONE
}
@@ -106,6 +147,13 @@ static const ExtraGuiOption ZVisionExtraGuiOption = {
false
};
+static const ExtraGuiOption ZVisionExtraGuiOption2 = {
+ _s("Double FPS"),
+ _s("Halve the update delay"),
+ "doublefps",
+ false
+};
+
class ZVisionMetaEngine : public AdvancedMetaEngine {
public:
ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), zVisionGames) {
@@ -132,24 +180,40 @@ public:
};
bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const {
- return false;
- /*
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportThumbnail) ||
- (f == kSavesSupportCreationDate) ||
- (f == kSavesSupportPlayTime);
- */
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate);
+ //(f == kSavesSupportPlayTime);
}
-/*bool ZVision::ZVision::hasFeature(EngineFeature f) const {
- return
- (f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
-}*/
+bool ZVision::ZVision::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+Common::Error ZVision::ZVision::loadGameState(int slot) {
+ return _saveManager->loadGame(slot);
+}
+
+Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &desc) {
+ _saveManager->saveGame(slot, desc);
+ return Common::kNoError;
+}
+
+bool ZVision::ZVision::canLoadGameStateCurrently() {
+ return !_videoIsPlaying;
+}
+
+bool ZVision::ZVision::canSaveGameStateCurrently() {
+ Location currentLocation = _scriptManager->getCurrentLocation();
+ return !_videoIsPlaying && currentLocation.world != 'g' && !(currentLocation.room == 'j' || currentLocation.room == 'a');
+}
bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc;
@@ -162,34 +226,40 @@ bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADG
const ExtraGuiOptions ZVisionMetaEngine::getExtraGuiOptions(const Common::String &target) const {
ExtraGuiOptions options;
options.push_back(ZVisionExtraGuiOption);
+ options.push_back(ZVisionExtraGuiOption2);
return options;
}
SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
- //Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- /*ZVision::ZVision::SaveHeader header;
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ ZVision::SaveGameHeader header;
Common::String pattern = target;
pattern += ".???";
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
SaveStateList saveList;
-/* for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
- // Obtain the last 3 digits of the filename, since they correspond to the save slot
- int slotNum = atoi(file->c_str() + file->size() - 3);
-
- if (slotNum >= 0 && slotNum <= 999) {
- Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
- if (in) {
- if (ZVision::ZVision::readSaveHeader(in, false, header) == ZVision::ZVision::kRSHENoError) {
- saveList.push_back(SaveStateDescriptor(slotNum, header.description));
- }
- delete in;
- }
- }
- }*/
+ // We only use readSaveGameHeader() here, which doesn't need an engine callback
+ ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
+
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ if (zvisionSaveMan->readSaveGameHeader(in, header)) {
+ saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
+ }
+ delete in;
+ }
+ }
+ }
+
+ delete zvisionSaveMan;
return saveList;
}
@@ -199,9 +269,8 @@ int ZVisionMetaEngine::getMaximumSaveSlot() const {
}
void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
- /*
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot);
+ Common::String filename = Common::String::format("%s.%03u", target, slot);
saveFileMan->removeSavefile(filename.c_str());
@@ -209,63 +278,62 @@ void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
Common::String pattern = target;
pattern += ".???";
filenames = saveFileMan->listSavefiles(pattern.c_str());
- Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
- // Obtain the last 3 digits of the filename, since they correspond to the save slot
- int slotNum = atoi(file->c_str() + file->size() - 3);
-
- // Rename every slot greater than the deleted slot,
- if (slotNum > slot) {
- saveFileMan->renameSavefile(file->c_str(), filename.c_str());
- filename = ZVision::ZVision::getSavegameFilename(target, ++slot);
- }
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ // Rename every slot greater than the deleted slot,
+ if (slotNum > slot) {
+ saveFileMan->renameSavefile(file->c_str(), filename.c_str());
+ filename = Common::String::format("%s.%03u", target, ++slot);
+ }
}
- */
}
SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- /*
- Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot);
+ Common::String filename = Common::String::format("%s.%03u", target, slot);
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
if (in) {
- ZVision::ZVision::SaveHeader header;
- ZVision::ZVision::kReadSaveHeaderError error;
+ ZVision::SaveGameHeader header;
- error = ZVision::ZVision::readSaveHeader(in, true, header);
- delete in;
+ // We only use readSaveGameHeader() here, which doesn't need an engine callback
+ ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
+ bool successfulRead = zvisionSaveMan->readSaveGameHeader(in, header);
+ delete zvisionSaveMan;
+ delete in;
- if (error == ZVision::ZVision::kRSHENoError) {
- SaveStateDescriptor desc(slot, header.description);
+ if (successfulRead) {
+ SaveStateDescriptor desc(slot, header.saveName);
- desc.setThumbnail(header.thumbnail);
+ desc.setThumbnail(header.thumbnail);
- if (header.version > 0) {
- int day = (header.saveDate >> 24) & 0xFF;
- int month = (header.saveDate >> 16) & 0xFF;
- int year = header.saveDate & 0xFFFF;
+ if (header.version > 0) {
+ int day = header.saveDay;
+ int month = header.saveMonth;
+ int year = header.saveYear;
- desc.setSaveDate(year, month, day);
+ desc.setSaveDate(year, month, day);
- int hour = (header.saveTime >> 16) & 0xFF;
- int minutes = (header.saveTime >> 8) & 0xFF;
+ int hour = header.saveHour;
+ int minutes = header.saveMinutes;
- desc.setSaveTime(hour, minutes);
+ desc.setSaveTime(hour, minutes);
- desc.setPlayTime(header.playTime * 1000);
- }
+ //desc.setPlayTime(header.playTime * 1000);
+ }
- return desc;
- }
+ return desc;
+ }
}
- */
return SaveStateDescriptor();
}
#if PLUGIN_ENABLED_DYNAMIC(ZVISION)
- REGISTER_PLUGIN_DYNAMIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
#else
- REGISTER_PLUGIN_STATIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
+REGISTER_PLUGIN_STATIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
#endif
diff --git a/engines/zvision/detection.h b/engines/zvision/detection.h
index a788e710b7..f80cac79ec 100644
--- a/engines/zvision/detection.h
+++ b/engines/zvision/detection.h
@@ -25,7 +25,6 @@
#include "engines/advancedDetector.h"
-
namespace ZVision {
enum ZVisionGameId {
diff --git a/engines/zvision/fonts/truetype_font.cpp b/engines/zvision/fonts/truetype_font.cpp
deleted file mode 100644
index ba4d72bde8..0000000000
--- a/engines/zvision/fonts/truetype_font.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/scummsys.h"
-
-#include "zvision/fonts/truetype_font.h"
-
-#include "zvision/zvision.h"
-#include "zvision/graphics/render_manager.h"
-
-#include "common/debug.h"
-#include "common/file.h"
-#include "common/system.h"
-
-#include "graphics/font.h"
-#include "graphics/fonts/ttf.h"
-#include "graphics/surface.h"
-
-
-namespace ZVision {
-
-TruetypeFont::TruetypeFont(ZVision *engine, int32 fontHeight)
- : _fontHeight(fontHeight),
- _font(0),
- _lineHeight(0) {
-}
-
-TruetypeFont::~TruetypeFont(void) {
- delete _font;
-}
-
-bool TruetypeFont::loadFile(const Common::String &filename) {
- Common::File file;
-
- bool fileOpened = false;
- if (!Common::File::exists(filename)) {
- debug("TTF font file %s was not found. Reverting to arial.ttf", filename.c_str());
- fileOpened = file.open("arial.ttf");
- } else {
- fileOpened = file.open(filename);
- }
-
- if (!fileOpened) {
- debug("TTF file could not be opened");
- return false;
- }
-
- _font = Graphics::loadTTFFont(file, _fontHeight);
- _lineHeight = _font->getFontHeight();
-
- return true;
-}
-
-Graphics::Surface *TruetypeFont::drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
- if (text.equals("")) {
- return nullptr;
- }
-
- Graphics::Surface *surface = new Graphics::Surface();
-
- if (!wrap) {
- int width = MIN(_font->getStringWidth(text), maxWidth);
- surface->create(width, _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- // TODO: Add better alpha support by getting the pixels from the backbuffer.
- // However doing that requires some kind of caching system so future text doesn't try to use this text as it's alpha background.
- surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
-
- _font->drawString(surface, text, 0, 0, maxWidth, textColor, align);
- return surface;
- }
-
- Common::Array<Common::String> lines;
- _font->wordWrapText(text, maxWidth, lines);
-
- while (maxHeight > 0 && (int)lines.size() * _lineHeight > maxHeight) {
- lines.pop_back();
- }
- if (lines.size() == 0) {
- return nullptr;
- }
-
- surface->create(maxWidth, lines.size() * _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
-
- int heightOffset = 0;
- for (Common::Array<Common::String>::iterator it = lines.begin(); it != lines.end(); it++) {
- _font->drawString(surface, *it, 0, 0 + heightOffset, maxWidth, textColor, align);
- heightOffset += _lineHeight;
- }
-
- return surface;
-}
-
-} // End of namespace ZVision
diff --git a/engines/zvision/graphics/effect.h b/engines/zvision/graphics/effect.h
new file mode 100644
index 0000000000..c6653c6037
--- /dev/null
+++ b/engines/zvision/graphics/effect.h
@@ -0,0 +1,83 @@
+/* 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 EFFECT_H_INCLUDED
+#define EFFECT_H_INCLUDED
+
+#include "common/rect.h"
+#include "common/list.h"
+#include "graphics/surface.h"
+
+#include "zvision/zvision.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class Effect {
+public:
+
+ Effect(ZVision *engine, uint32 key, Common::Rect region, bool ported) : _engine(engine), _key(key), _region(region), _ported(ported) {
+ _surface.create(_region.width(), _region.height(), _engine->_pixelFormat);
+ }
+ virtual ~Effect() {}
+
+ uint32 getKey() {
+ return _key;
+ }
+
+ Common::Rect getRegion() {
+ return _region;
+ }
+
+ bool isPort() {
+ return _ported;
+ }
+
+ virtual const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) {
+ return &_surface;
+ }
+
+ virtual void update() {}
+
+protected:
+ ZVision *_engine;
+ uint32 _key;
+ Common::Rect _region;
+ bool _ported;
+ Graphics::Surface _surface;
+
+// Static member functions
+public:
+
+};
+
+struct EffectMapUnit {
+ uint32 count;
+ bool inEffect;
+};
+
+typedef Common::List<EffectMapUnit> EffectMap;
+
+} // End of namespace ZVision
+
+#endif // EFFECT_H_INCLUDED
diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp
new file mode 100644
index 0000000000..f59e82a4a0
--- /dev/null
+++ b/engines/zvision/graphics/effects/fog.cpp
@@ -0,0 +1,173 @@
+/* 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 "zvision/graphics/effects/fog.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+
+namespace ZVision {
+
+FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds):
+ Effect(engine, key, region, ported) {
+
+ _map = Map;
+
+ _r = 0;
+ _g = 0;
+ _b = 0;
+
+ _pos = 0;
+
+ if (_engine->getSearchManager()->hasFile(clouds))
+ _engine->getRenderManager()->readImageToSurface(clouds, _fog);
+ else
+ _engine->getRenderManager()->readImageToSurface("cloud.tga", _fog);
+
+ _mp.resize(_fog.h);
+ for (int16 i = 0; i < _fog.h; i++) {
+ _mp[i].resize(_fog.w);
+ for (int16 j = 0; j < _fog.w; j++)
+ _mp[i][j] = true;
+ }
+
+ for (uint8 i = 0; i < 32; i++)
+ _colorMap[i] = 0;
+}
+
+FogFx::~FogFx() {
+ if (_map)
+ delete _map;
+
+ for (uint16 i = 0; i < _mp.size(); i++)
+ _mp[i].clear();
+ _mp.clear();
+}
+
+const Graphics::Surface *FogFx::draw(const Graphics::Surface &srcSubRect) {
+ _surface.copyFrom(srcSubRect);
+ EffectMap::iterator it = _map->begin();
+
+ uint32 cnt = 0;
+
+ for (uint16 j = 0; j < _surface.h; j++) {
+ uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j);
+
+ for (uint16 i = 0; i < _surface.w; i++) {
+ if (it->inEffect) {
+ // Not 100% equivalent, but looks nice and not buggy
+ uint8 sr, sg, sb;
+ _engine->_pixelFormat.colorToRGB(lineBuf[i], sr, sg, sb);
+ uint16 fogColor = *(uint16 *)_fog.getBasePtr((i + _pos) % _fog.w, j);
+ uint8 dr, dg, db;
+ _engine->_pixelFormat.colorToRGB(_colorMap[fogColor & 0x1F], dr, dg, db);
+ uint16 fr = dr + sr;
+ if (fr > 255)
+ fr = 255;
+ uint16 fg = dg + sg;
+ if (fg > 255)
+ fg = 255;
+ uint16 fb = db + sb;
+ if (fb > 255)
+ fb = 255;
+ lineBuf[i] = _engine->_pixelFormat.RGBToColor(fr, fg, fb);
+ }
+ cnt++;
+ if (cnt >= it->count) {
+ it++;
+ cnt = 0;
+ }
+ if (it == _map->end())
+ break;
+ }
+ if (it == _map->end())
+ break;
+ }
+
+ return &_surface;
+}
+
+void FogFx::update() {
+ _pos += _engine->getScriptManager()->getStateValue(StateKey_EF9_Speed);
+ _pos %= _fog.w;
+
+ uint8 dr = _engine->getScriptManager()->getStateValue(StateKey_EF9_R);
+ uint8 dg = _engine->getScriptManager()->getStateValue(StateKey_EF9_G);
+ uint8 db = _engine->getScriptManager()->getStateValue(StateKey_EF9_B);
+ dr = CLIP((int)dr, 0, 31);
+ dg = CLIP((int)dg, 0, 31);
+ db = CLIP((int)db, 0, 31);
+
+ if (dr != _r || dg != _g || db != _b) {
+ if (_r > dr)
+ _r--;
+ else if (_r < dr)
+ _r++;
+
+ if (_g > dg)
+ _g--;
+ else if (_g < dg)
+ _g++;
+
+ if (_b > db)
+ _b--;
+ else if (_b < db)
+ _b++;
+
+ // Not 100% equivalent, but looks nice and not buggy
+
+ _colorMap[31] = _engine->_pixelFormat.RGBToColor(_r << 3, _g << 3, _b << 3);
+
+ for (uint8 i = 0; i < 31; i++) {
+ float perc = (float)i / 31.0;
+ uint8 cr = (float)_r * perc;
+ uint8 cg = (float)_g * perc;
+ uint8 cb = (float)_b * perc;
+ _colorMap[i] = _engine->_pixelFormat.RGBToColor(cr << 3, cg << 3, cb << 3);
+ }
+ }
+
+ for (uint16 j = 0; j < _fog.h; j++) {
+ uint16 *pix = (uint16 *)_fog.getBasePtr(0, j);
+
+ for (uint16 i = 0; i < _fog.w; i++) {
+ if (_mp[j][i]) {
+ if ((pix[i] & 0x1F) == 0x1F) {
+ pix[i]--;
+ _mp[j][i] = false;
+ } else
+ pix[i]++;
+ } else {
+ if ((pix[i] & 0x1F) == 0) {
+ pix[i]++;
+ _mp[j][i] = true;
+ } else
+ pix[i]--;
+ }
+ }
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/effects/fog.h b/engines/zvision/graphics/effects/fog.h
new file mode 100644
index 0000000000..45d6f9596d
--- /dev/null
+++ b/engines/zvision/graphics/effects/fog.h
@@ -0,0 +1,52 @@
+/* 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 ZVISION_FOG_H
+#define ZVISION_FOG_H
+
+#include "zvision/graphics/effect.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class FogFx : public Effect {
+public:
+
+ FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds);
+ ~FogFx();
+
+ const Graphics::Surface *draw(const Graphics::Surface &srcSubRect);
+
+ void update();
+
+private:
+ EffectMap *_map;
+ Graphics::Surface _fog;
+ uint8 _r, _g, _b;
+ int32 _pos;
+ Common::Array< Common::Array< bool > > _mp;
+ uint16 _colorMap[32];
+};
+} // End of namespace ZVision
+
+#endif // ZVISION_FOG_H
diff --git a/engines/zvision/graphics/effects/light.cpp b/engines/zvision/graphics/effects/light.cpp
new file mode 100644
index 0000000000..00b3811d65
--- /dev/null
+++ b/engines/zvision/graphics/effects/light.cpp
@@ -0,0 +1,109 @@
+/* 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 "zvision/graphics/effects/light.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+
+namespace ZVision {
+
+LightFx::LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD, int8 maxD):
+ Effect(engine, key, region, ported) {
+ _map = Map;
+ _delta = delta;
+ _up = true;
+ _pos = 0;
+
+ _minD = minD;
+ if (_minD < -delta)
+ _minD = -delta;
+
+ _maxD = maxD;
+ if (_maxD > delta)
+ _maxD = delta;
+}
+
+LightFx::~LightFx() {
+ if (_map)
+ delete _map;
+}
+
+const Graphics::Surface *LightFx::draw(const Graphics::Surface &srcSubRect) {
+ _surface.copyFrom(srcSubRect);
+ EffectMap::iterator it = _map->begin();
+ uint32 cnt = 0;
+
+ uint32 dcolor = 0;
+
+ if (_pos < 0) {
+ uint8 cc = ((-_pos) & 0x1F) << 3;
+ dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc);
+ } else {
+ uint8 cc = (_pos & 0x1F) << 3;
+ dcolor = _engine->_pixelFormat.RGBToColor(cc, cc, cc);
+ }
+
+ for (uint16 j = 0; j < _surface.h; j++) {
+ uint16 *lineBuf = (uint16 *)_surface.getBasePtr(0, j);
+
+ for (uint16 i = 0; i < _surface.w; i++) {
+ if (it->inEffect) {
+ if (_pos < 0) {
+ lineBuf[i] -= dcolor;
+ } else {
+ lineBuf[i] += dcolor;
+ }
+ }
+ cnt++;
+ if (cnt >= it->count) {
+ it++;
+ cnt = 0;
+ }
+ if (it == _map->end())
+ break;
+ }
+ if (it == _map->end())
+ break;
+ }
+
+ return &_surface;
+}
+
+void LightFx::update() {
+ if (_up)
+ _pos++;
+ else
+ _pos--;
+
+ if (_pos <= _minD) {
+ _up = !_up;
+ _pos = _minD;
+ } else if (_pos >= _maxD) {
+ _up = !_up;
+ _pos = _maxD;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/effects/light.h b/engines/zvision/graphics/effects/light.h
new file mode 100644
index 0000000000..ae87d66cb3
--- /dev/null
+++ b/engines/zvision/graphics/effects/light.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LIGHTFX_H_INCLUDED
+#define LIGHTFX_H_INCLUDED
+
+#include "zvision/graphics/effect.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class LightFx : public Effect {
+public:
+
+ LightFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, int8 delta, int8 minD = -127, int8 maxD = 127);
+ ~LightFx();
+
+ const Graphics::Surface *draw(const Graphics::Surface &srcSubRect);
+
+ void update();
+
+private:
+ EffectMap *_map;
+ int32 _delta;
+ bool _up;
+ int32 _pos;
+
+ int8 _minD;
+ int8 _maxD;
+};
+} // End of namespace ZVision
+
+#endif // LIGHTFX_H_INCLUDED
diff --git a/engines/zvision/graphics/effects/wave.cpp b/engines/zvision/graphics/effects/wave.cpp
new file mode 100644
index 0000000000..1b3aa040e8
--- /dev/null
+++ b/engines/zvision/graphics/effects/wave.cpp
@@ -0,0 +1,145 @@
+/* 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 "zvision/graphics/effects/wave.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+
+namespace ZVision {
+
+WaveFx::WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd):
+ Effect(engine, key, region, ported) {
+
+ _frame = 0;
+ _frameCount = frames;
+
+ _ampls.resize(_frameCount);
+ _halfWidth = _region.width() / 2;
+ _halfHeight = _region.height() / 2;
+
+ int32 frmsize = _halfWidth * _halfHeight;
+
+ float phase = 0;
+
+ int16 quarterWidth = _halfWidth / 2;
+ int16 quarterHeight = _halfHeight / 2;
+
+ for (int16 i = 0; i < _frameCount; i++) {
+ _ampls[i].resize(frmsize);
+
+ for (int16 y = 0; y < _halfHeight; y++)
+ for (int16 x = 0; x < _halfWidth; x++) {
+ int16 dx = (x - quarterWidth);
+ int16 dy = (y - quarterHeight);
+
+ _ampls[i][x + y * _halfWidth] = ampl * sin(sqrt(dx * dx / (float)centerX + dy * dy / (float)centerY) / (-waveln * 3.1415926) + phase);
+ }
+ phase += spd;
+ }
+}
+
+WaveFx::~WaveFx() {
+ for (uint16 i = 0; i < _ampls.size(); i++)
+ _ampls[i].clear();
+ _ampls.clear();
+}
+
+const Graphics::Surface *WaveFx::draw(const Graphics::Surface &srcSubRect) {
+ for (int16 y = 0; y < _halfHeight; y++) {
+ uint16 *abc = (uint16 *)_surface.getBasePtr(0, y);
+ uint16 *abc2 = (uint16 *)_surface.getBasePtr(0, _halfHeight + y);
+ uint16 *abc3 = (uint16 *)_surface.getBasePtr(_halfWidth, y);
+ uint16 *abc4 = (uint16 *)_surface.getBasePtr(_halfWidth, _halfHeight + y);
+
+ for (int16 x = 0; x < _halfWidth; x++) {
+ int8 amnt = _ampls[_frame][x + _halfWidth * y];
+
+ int16 nX = x + amnt;
+ int16 nY = y + amnt;
+
+ if (nX < 0)
+ nX = 0;
+ if (nX >= _region.width())
+ nX = _region.width() - 1;
+ if (nY < 0)
+ nY = 0;
+ if (nY >= _region.height())
+ nY = _region.height() - 1;
+ *abc = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
+
+ nX = x + amnt + _halfWidth;
+ nY = y + amnt;
+
+ if (nX < 0)
+ nX = 0;
+ if (nX >= _region.width())
+ nX = _region.width() - 1;
+ if (nY < 0)
+ nY = 0;
+ if (nY >= _region.height())
+ nY = _region.height() - 1;
+ *abc3 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
+
+ nX = x + amnt;
+ nY = y + amnt + _halfHeight;
+
+ if (nX < 0)
+ nX = 0;
+ if (nX >= _region.width())
+ nX = _region.width() - 1;
+ if (nY < 0)
+ nY = 0;
+ if (nY >= _region.height())
+ nY = _region.height() - 1;
+ *abc2 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
+
+ nX = x + amnt + _halfWidth;
+ nY = y + amnt + _halfHeight;
+
+ if (nX < 0)
+ nX = 0;
+ if (nX >= _region.width())
+ nX = _region.width() - 1;
+ if (nY < 0)
+ nY = 0;
+ if (nY >= _region.height())
+ nY = _region.height() - 1;
+ *abc4 = *(const uint16 *)srcSubRect.getBasePtr(nX, nY);
+
+ abc++;
+ abc2++;
+ abc3++;
+ abc4++;
+ }
+ }
+
+ return &_surface;
+}
+
+void WaveFx::update() {
+ _frame = (_frame + 1) % _frameCount;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/graphics/effects/wave.h b/engines/zvision/graphics/effects/wave.h
new file mode 100644
index 0000000000..2e813ed5b6
--- /dev/null
+++ b/engines/zvision/graphics/effects/wave.h
@@ -0,0 +1,51 @@
+/* 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 WAVEFX_H_INCLUDED
+#define WAVEFX_H_INCLUDED
+
+#include "common/array.h"
+#include "zvision/graphics/effect.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class WaveFx : public Effect {
+public:
+
+ WaveFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, int16 frames, int16 centerX, int16 centerY, float ampl, float waveln, float spd);
+ ~WaveFx();
+
+ const Graphics::Surface *draw(const Graphics::Surface &srcSubRect);
+
+ void update();
+
+private:
+ int16 _frame;
+ int16 _frameCount;
+ int16 _halfWidth, _halfHeight;
+ Common::Array< Common::Array< int8 > > _ampls;
+};
+} // End of namespace ZVision
+
+#endif // WAVEFX_H_INCLUDED
diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp
index aed30ea12c..97d47e3920 100644
--- a/engines/zvision/graphics/render_manager.cpp
+++ b/engines/zvision/graphics/render_manager.cpp
@@ -1,28 +1,31 @@
/* 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.
- *
- */
+*
+* 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 "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/text/text.h"
#include "zvision/utility/lzss_read_stream.h"
@@ -34,200 +37,223 @@
#include "image/tga.h"
-
namespace ZVision {
-RenderManager::RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat)
- : _system(system),
- _workingWidth(workingWindow.width()),
- _workingHeight(workingWindow.height()),
- _screenCenterX(_workingWidth / 2),
- _screenCenterY(_workingHeight / 2),
- _workingWindow(workingWindow),
- _pixelFormat(pixelFormat),
- _backgroundWidth(0),
- _backgroundHeight(0),
- _backgroundInverseVelocity(0),
- _backgroundOffset(0, 0),
- _accumulatedVelocityMilliseconds(0),
- _renderTable(_workingWidth, _workingHeight) {
-
- _workingWindowBuffer.create(_workingWidth, _workingHeight, _pixelFormat);
- _backBuffer.create(windowWidth, windowHeight, pixelFormat);
+RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat)
+ : _engine(engine),
+ _system(engine->_system),
+ _wrkWidth(workingWindow.width()),
+ _wrkHeight(workingWindow.height()),
+ _screenCenterX(_wrkWidth / 2),
+ _screenCenterY(_wrkHeight / 2),
+ _workingWindow(workingWindow),
+ _pixelFormat(pixelFormat),
+ _bkgWidth(0),
+ _bkgHeight(0),
+ _bkgOff(0),
+ _renderTable(_wrkWidth, _wrkHeight) {
+
+ _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _effectWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat);
+ _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat);
+
+ _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top);
+ _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight);
+
+ _subid = 0;
}
RenderManager::~RenderManager() {
- _workingWindowBuffer.free();
- _currentBackground.free();
- _backBuffer.free();
-
- for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
- iter->_value.data->free();
- delete iter->_value.data;
- }
-}
-
-void RenderManager::update(uint deltaTimeInMillis) {
- // An inverse velocity of 0 would be infinitely fast, so we'll let 0 mean no velocity.
- if (_backgroundInverseVelocity != 0) {
- _accumulatedVelocityMilliseconds += deltaTimeInMillis;
-
- uint absVelocity = uint(abs(_backgroundInverseVelocity));
-
- int numberOfSteps = 0;
- while (_accumulatedVelocityMilliseconds >= absVelocity) {
- _accumulatedVelocityMilliseconds -= absVelocity;
- numberOfSteps++;
- }
-
- // Choose the direction of movement using the sign of the velocity
- moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps);
- }
+ _curBkg.free();
+ _wrkWnd.free();
+ _effectWnd.free();
+ _outWnd.free();
+ _menuWnd.free();
+ _subWnd.free();
}
void RenderManager::renderBackbufferToScreen() {
- if (!_workingWindowDirtyRect.isEmpty()) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- _renderTable.mutateImage((uint16 *)_workingWindowBuffer.getPixels(), (uint16 *)_backBuffer.getBasePtr(_workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top), _backBuffer.w, _workingWindowDirtyRect);
- } else {
- _backBuffer.copyRectToSurface(_workingWindowBuffer.getBasePtr(_workingWindowDirtyRect.left, _workingWindowDirtyRect.top), _workingWindowBuffer.pitch, _workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top, _workingWindowDirtyRect.width(), _workingWindowDirtyRect.height());
+ Graphics::Surface *out = &_outWnd;
+ Graphics::Surface *in = &_wrkWnd;
+ Common::Rect outWndDirtyRect;
+
+ if (!_effects.empty()) {
+ bool copied = false;
+ Common::Rect windRect(_wrkWidth, _wrkHeight);
+ for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) {
+ Common::Rect rect = (*it)->getRegion();
+ Common::Rect scrPlace = rect;
+ if ((*it)->isPort())
+ scrPlace = bkgRectToScreen(scrPlace);
+ if (windRect.intersects(scrPlace)) {
+ if (!copied) {
+ copied = true;
+ _effectWnd.copyFrom(_wrkWnd);
+ in = &_effectWnd;
+ }
+ const Graphics::Surface *post;
+ if ((*it)->isPort())
+ post = (*it)->draw(_curBkg.getSubArea(rect));
+ else
+ post = (*it)->draw(_effectWnd.getSubArea(rect));
+ blitSurfaceToSurface(*post, _effectWnd, scrPlace.left, scrPlace.top);
+ scrPlace.clip(windRect);
+ if (_wrkWndDirtyRect .isEmpty()) {
+ _wrkWndDirtyRect = scrPlace;
+ } else {
+ _wrkWndDirtyRect.extend(scrPlace);
+ }
+ }
}
+ }
- // Translate the working window dirty rect to screen coords
- _workingWindowDirtyRect.translate(_workingWindow.left, _workingWindow.top);
- // Then extend the backbuffer dirty rect to contain it
- if (_backBufferDirtyRect.isEmpty()) {
- _backBufferDirtyRect = _workingWindowDirtyRect;
- } else {
- _backBufferDirtyRect.extend(_workingWindowDirtyRect);
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (!_wrkWndDirtyRect.isEmpty()) {
+ _renderTable.mutateImage(&_outWnd, in);
+ out = &_outWnd;
+ outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight);
}
-
- // Clear the dirty rect
- _workingWindowDirtyRect = Common::Rect();
+ } else {
+ out = in;
+ outWndDirtyRect = _wrkWndDirtyRect;
}
- // TODO: Add menu rendering
+ if (!outWndDirtyRect.isEmpty()) {
+ _system->copyRectToScreen(out->getBasePtr(outWndDirtyRect.left, outWndDirtyRect.top), out->pitch,
+ outWndDirtyRect.left + _workingWindow.left,
+ outWndDirtyRect.top + _workingWindow.top,
+ outWndDirtyRect.width(),
+ outWndDirtyRect.height());
+ }
+}
- // Render alpha entries
- processAlphaEntries();
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- if (!_backBufferDirtyRect.isEmpty()) {
- _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height());
- _backBufferDirtyRect = Common::Rect();
- }
+ blitSurfaceToBkg(surface, destX, destY);
+ surface.free();
}
-void RenderManager::processAlphaEntries() {
- // TODO: Add dirty rectangling support. AKA only draw an entry if the _backbufferDirtyRect intersects/contains the entry Rect
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 keycolor) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
- uint32 destOffset = 0;
- uint32 sourceOffset = 0;
- uint16 *backbufferPtr = (uint16 *)_backBuffer.getBasePtr(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top);
- uint16 *entryPtr = (uint16 *)iter->_value.data->getPixels();
+ blitSurfaceToBkg(surface, destX, destY, keycolor);
+ surface.free();
+}
- for (int32 y = 0; y < iter->_value.height; ++y) {
- for (int32 x = 0; x < iter->_value.width; ++x) {
- uint16 color = entryPtr[sourceOffset + x];
- if (color != iter->_value.alphaColor) {
- backbufferPtr[destOffset + x] = color;
- }
- }
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- destOffset += _backBuffer.w;
- sourceOffset += iter->_value.width;
- }
+ uint16 keycolor = *(uint16 *)surface.getBasePtr(keyX, keyY);
- if (_backBufferDirtyRect.isEmpty()) {
- _backBufferDirtyRect = Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height);
- } else {
- _backBufferDirtyRect.extend(Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height));
- }
- }
+ blitSurfaceToBkg(surface, destX, destY, keycolor);
+ surface.free();
}
-void RenderManager::clearWorkingWindowTo555Color(uint16 color) {
- uint32 workingWindowSize = _workingWidth * _workingHeight;
- byte r, g, b;
- Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b);
- uint16 colorIn565 = _pixelFormat.RGBToColor(r, g, b);
- uint16 *bufferPtr = (uint16 *)_workingWindowBuffer.getPixels();
+void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+ Common::File file;
- for (uint32 i = 0; i < workingWindowSize; ++i) {
- bufferPtr[i] = colorIn565;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("Could not open file %s", fileName.c_str());
+ return;
}
-}
-void RenderManager::renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
- int16 subRectX = 0;
- int16 subRectY = 0;
+ // Read the magic number
+ // Some files are true TGA, while others are TGZ
+ uint32 fileType = file.readUint32BE();
- // Take care of negative destinations
- if (destinationX < 0) {
- subRectX = -destinationX;
- destinationX = 0;
- } else if (destinationX >= surface.w) {
- // Take care of extreme positive destinations
- destinationX -= surface.w;
- }
+ uint32 imageWidth;
+ uint32 imageHeight;
+ Image::TGADecoder tga;
+ uint16 *buffer;
+ bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
+ // All ZVision images are in RGB 555
+ Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ destination.format = pixelFormat555;
- // Take care of negative destinations
- if (destinationY < 0) {
- subRectY = -destinationY;
- destinationY = 0;
- } else if (destinationY >= surface.h) {
- // Take care of extreme positive destinations
- destinationY -= surface.h;
- }
+ bool isTGZ;
+
+ // Check for TGZ files
+ if (fileType == MKTAG('T', 'G', 'Z', '\0')) {
+ isTGZ = true;
- if (wrap) {
- _backgroundWidth = surface.w;
- _backgroundHeight = surface.h;
+ // TGZ files have a header and then Bitmap data that is compressed with LZSS
+ uint32 decompressedSize = file.readSint32LE();
+ imageWidth = file.readSint32LE();
+ imageHeight = file.readSint32LE();
- if (destinationX > 0) {
- // Move destinationX to 0
- subRectX = surface.w - destinationX;
- destinationX = 0;
- }
+ LzssReadStream lzssStream(&file);
+ buffer = (uint16 *)(new uint16[decompressedSize]);
+ lzssStream.read(buffer, decompressedSize);
+ } else {
+ isTGZ = false;
- if (destinationY > 0) {
- // Move destinationY to 0
- subRectY = surface.h - destinationY;
- destinationY = 0;
+ // Reset the cursor
+ file.seek(0);
+
+ // Decode
+ if (!tga.loadStream(file)) {
+ warning("Error while reading TGA image");
+ return;
}
+
+ Graphics::Surface tgaSurface = *(tga.getSurface());
+ imageWidth = tgaSurface.w;
+ imageHeight = tgaSurface.h;
+
+ buffer = (uint16 *)tgaSurface.getPixels();
}
- // Clip subRect to working window bounds
- Common::Rect subRect(subRectX, subRectY, subRectX + _workingWidth, subRectY + _workingHeight);
+ // Flip the width and height if transposed
+ if (isTransposed) {
+ uint16 temp = imageHeight;
+ imageHeight = imageWidth;
+ imageWidth = temp;
+ }
- if (!wrap) {
- // Clip to image bounds
- subRect.clip(surface.w, surface.h);
+ // If the destination internal buffer is the same size as what we're copying into it,
+ // there is no need to free() and re-create
+ if (imageWidth != destination.w || imageHeight != destination.h) {
+ destination.create(imageWidth, imageHeight, pixelFormat555);
}
- // Check destRect for validity
- if (!subRect.isValidRect() || subRect.isEmpty())
- return;
+ // If transposed, 'un-transpose' the data while copying it to the destination
+ // Otherwise, just do a simple copy
+ if (isTransposed) {
+ uint16 *dest = (uint16 *)destination.getPixels();
- copyRectToWorkingWindow((const uint16 *)surface.getBasePtr(subRect.left, subRect.top), destinationX, destinationY, surface.w, subRect.width(), subRect.height());
-}
+ for (uint32 y = 0; y < imageHeight; ++y) {
+ uint32 columnIndex = y * imageWidth;
-void RenderManager::renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap) {
- Graphics::Surface surface;
- readImageToSurface(fileName, surface);
+ for (uint32 x = 0; x < imageWidth; ++x) {
+ dest[columnIndex + x] = buffer[x * imageHeight + y];
+ }
+ }
+ } else {
+ memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel);
+ }
- renderSubRectToScreen(surface, destinationX, destinationY, wrap);
-}
+ // Cleanup
+ if (isTGZ) {
+ delete[] buffer;
+ } else {
+ tga.destroy();
+ }
-void RenderManager::renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
- renderSubRectToScreen(surface, destinationX, destinationY, wrap);
+ // Convert in place to RGB 565 from RGB 555
+ destination.convertToInPlace(_pixelFormat);
}
-void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) {
Common::File file;
- if (!file.open(fileName)) {
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
warning("Could not open file %s", fileName.c_str());
return;
}
@@ -240,7 +266,6 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
uint32 imageHeight;
Image::TGADecoder tga;
uint16 *buffer;
- bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
// All ZVision images are in RGB 555
Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
destination.format = pixelFormat555;
@@ -279,7 +304,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
}
// Flip the width and height if transposed
- if (isTransposed) {
+ if (transposed) {
uint16 temp = imageHeight;
imageHeight = imageWidth;
imageWidth = temp;
@@ -293,7 +318,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
// If transposed, 'un-transpose' the data while copying it to the destination
// Otherwise, just do a simple copy
- if (isTransposed) {
+ if (transposed) {
uint16 *dest = (uint16 *)destination.getPixels();
for (uint32 y = 0; y < imageHeight; ++y) {
@@ -318,209 +343,724 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
destination.convertToInPlace(_pixelFormat);
}
-void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height) {
- uint32 destOffset = 0;
- uint32 sourceOffset = 0;
- uint16 *workingWindowBufferPtr = (uint16 *)_workingWindowBuffer.getBasePtr(destX, destY);
+const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) {
+ if (_workingWindow.contains(point)) {
+ // Convert from screen space to working window space
+ Common::Point newPoint(point - Common::Point(_workingWindow.left, _workingWindow.top));
+
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ newPoint = _renderTable.convertWarpedCoordToFlatCoord(newPoint);
+ }
- for (int32 y = 0; y < height; ++y) {
- for (int32 x = 0; x < width; ++x) {
- workingWindowBufferPtr[destOffset + x] = buffer[sourceOffset + x];
+ if (state == RenderTable::PANORAMA) {
+ newPoint += (Common::Point(_bkgOff - _screenCenterX, 0));
+ } else if (state == RenderTable::TILT) {
+ newPoint += (Common::Point(0, _bkgOff - _screenCenterY));
}
- destOffset += _workingWidth;
- sourceOffset += imageWidth;
- }
+ if (_bkgWidth)
+ newPoint.x %= _bkgWidth;
+ if (_bkgHeight)
+ newPoint.y %= _bkgHeight;
- if (_workingWindowDirtyRect.isEmpty()) {
- _workingWindowDirtyRect = Common::Rect(destX, destY, destX + width, destY + height);
+ if (newPoint.x < 0)
+ newPoint.x += _bkgWidth;
+ if (newPoint.y < 0)
+ newPoint.y += _bkgHeight;
+
+ return newPoint;
} else {
- _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height));
+ return Common::Point(0, 0);
}
+}
+
+RenderTable *RenderManager::getRenderTable() {
+ return &_renderTable;
+}
+
+void RenderManager::setBackgroundImage(const Common::String &fileName) {
+ readImageToSurface(fileName, _curBkg);
+ _bkgWidth = _curBkg.w;
+ _bkgHeight = _curBkg.h;
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+}
+
+void RenderManager::setBackgroundPosition(int offset) {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::TILT || state == RenderTable::PANORAMA)
+ if (_bkgOff != offset)
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+ _bkgOff = offset;
+
+ _engine->getScriptManager()->setStateValue(StateKey_ViewPos, offset);
+}
+
+uint32 RenderManager::getCurrentBackgroundOffset() {
+ RenderTable::RenderState state = _renderTable.getRenderState();
- // TODO: Remove this from release. It's here to make sure code that uses this function clips their destinations correctly
- assert(_workingWindowDirtyRect.width() <= _workingWidth && _workingWindowDirtyRect.height() <= _workingHeight);
+ if (state == RenderTable::PANORAMA) {
+ return _bkgOff;
+ } else if (state == RenderTable::TILT) {
+ return _bkgOff;
+ } else {
+ return 0;
+ }
}
-void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber) {
- AlphaDataEntry entry;
- entry.alphaColor = alphaColor;
- entry.data = new Graphics::Surface();
- entry.data->create(width, height, _pixelFormat);
- entry.destX = destX;
- entry.destY = destY;
- entry.width = width;
- entry.height = height;
+Graphics::Surface *RenderManager::tranposeSurface(const Graphics::Surface *surface) {
+ Graphics::Surface *tranposedSurface = new Graphics::Surface();
+ tranposedSurface->create(surface->h, surface->w, surface->format);
+
+ const uint16 *source = (const uint16 *)surface->getPixels();
+ uint16 *dest = (uint16 *)tranposedSurface->getPixels();
- uint32 sourceOffset = 0;
- uint32 destOffset = 0;
- uint16 *surfacePtr = (uint16 *)entry.data->getPixels();
+ for (uint32 y = 0; y < tranposedSurface->h; ++y) {
+ uint32 columnIndex = y * tranposedSurface->w;
- for (int32 y = 0; y < height; ++y) {
- for (int32 x = 0; x < width; ++x) {
- surfacePtr[destOffset + x] = buffer[sourceOffset + x];
+ for (uint32 x = 0; x < tranposedSurface->w; ++x) {
+ dest[columnIndex + x] = source[x * surface->w + y];
}
+ }
+
+ return tranposedSurface;
+}
+
+void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint32 dstWidth, uint32 dstHeight) {
+ assert(bytesPerPixel == 1 || bytesPerPixel == 2);
+
+ const float xscale = (float)srcWidth / (float)dstWidth;
+ const float yscale = (float)srcHeight / (float)dstHeight;
- destOffset += width;
- sourceOffset += imageWidth;
+ if (bytesPerPixel == 1) {
+ const byte *srcPtr = (const byte *)src;
+ byte *dstPtr = (byte *)dst;
+ for (uint32 y = 0; y < dstHeight; ++y) {
+ for (uint32 x = 0; x < dstWidth; ++x) {
+ *dstPtr = srcPtr[(int)(x * xscale) + (int)(y * yscale) * srcWidth];
+ dstPtr++;
+ }
+ }
+ } else if (bytesPerPixel == 2) {
+ const uint16 *srcPtr = (const uint16 *)src;
+ uint16 *dstPtr = (uint16 *)dst;
+ for (uint32 y = 0; y < dstHeight; ++y) {
+ for (uint32 x = 0; x < dstWidth; ++x) {
+ *dstPtr = srcPtr[(int)(x * xscale) + (int)(y * yscale) * srcWidth];
+ dstPtr++;
+ }
+ }
}
+}
+
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) {
+
+ if (src.format != dst.format)
+ return;
+
+ Common::Rect srcRect = _srcRect;
+ if (srcRect.isEmpty())
+ srcRect = Common::Rect(src.w, src.h);
+ srcRect.clip(src.w, src.h);
+ Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
+ srcRect.clip(dstRect);
+
+ if (srcRect.isEmpty() || !srcRect.isValidRect())
+ return;
+
+ // Copy srcRect from src surface to dst surface
+ const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top);
- _alphaDataEntries[idNumber] = entry;
+ int xx = _x;
+ int yy = _y;
+
+ if (xx < 0)
+ xx = 0;
+ if (yy < 0)
+ yy = 0;
+
+ if (_x >= dst.w || _y >= dst.h)
+ return;
+
+ byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);
+
+ int32 w = srcRect.width();
+ int32 h = srcRect.height();
+
+ for (int32 y = 0; y < h; y++) {
+ memcpy(dstBuffer, srcBuffer, w * src.format.bytesPerPixel);
+ srcBuffer += src.pitch;
+ dstBuffer += dst.pitch;
+ }
}
-Common::Rect RenderManager::renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
- AlphaDataEntry entry;
- entry.alphaColor = 0;
- entry.destX = destX;
- entry.destY = destY;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) {
+
+ if (src.format != dst.format)
+ return;
+
+ Common::Rect srcRect = _srcRect;
+ if (srcRect.isEmpty())
+ srcRect = Common::Rect(src.w, src.h);
+ srcRect.clip(src.w, src.h);
+ Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
+ srcRect.clip(dstRect);
+
+ if (srcRect.isEmpty() || !srcRect.isValidRect())
+ return;
+
+ uint32 _keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1);
+
+ // Copy srcRect from src surface to dst surface
+ const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top);
+
+ int xx = _x;
+ int yy = _y;
+
+ if (xx < 0)
+ xx = 0;
+ if (yy < 0)
+ yy = 0;
+
+ if (_x >= dst.w || _y >= dst.h)
+ return;
+
+ byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);
+
+ int32 w = srcRect.width();
+ int32 h = srcRect.height();
+
+ for (int32 y = 0; y < h; y++) {
+ switch (src.format.bytesPerPixel) {
+ case 1: {
+ const uint *srcTemp = (const uint *)srcBuffer;
+ uint *dstTemp = (uint *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ case 2: {
+ const uint16 *srcTemp = (const uint16 *)srcBuffer;
+ uint16 *dstTemp = (uint16 *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ case 4: {
+ const uint32 *srcTemp = (const uint32 *)srcBuffer;
+ uint32 *dstTemp = (uint32 *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ srcBuffer += src.pitch;
+ dstBuffer += dst.pitch;
+ }
+}
- // Draw the text to the working window
- entry.data = font->drawTextToSurface(text, textColor, maxWidth, maxHeight, align, wrap);
- entry.width = entry.data->w;
- entry.height = entry.data->h;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, dst, x, y);
+}
- _alphaDataEntries[idNumber] = entry;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, dst, x, y, colorkey);
+}
- return Common::Rect(destX, destY, destX + entry.width, destY + entry.height);
+void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _curBkg, x, y);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_bkgDirtyRect.isEmpty())
+ _bkgDirtyRect = dirty;
+ else
+ _bkgDirtyRect.extend(dirty);
}
-const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) {
- // Convert from screen space to working window space
- Common::Point newPoint(point - Common::Point(_workingWindow.left, _workingWindow.top));
+void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _curBkg, x, y, colorkey);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_bkgDirtyRect.isEmpty())
+ _bkgDirtyRect = dirty;
+ else
+ _bkgDirtyRect.extend(dirty);
+}
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- newPoint = _renderTable.convertWarpedCoordToFlatCoord(newPoint);
+void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect) {
+ if (src.w == _dstRect.width() && src.h == _dstRect.height())
+ blitSurfaceToBkg(src, _dstRect.left, _dstRect.top);
+ else {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ tmp->create(_dstRect.width(), _dstRect.height(), src.format);
+ scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height());
+ blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top);
+ tmp->free();
+ delete tmp;
}
+}
- if (state == RenderTable::PANORAMA) {
- newPoint -= (Common::Point(_screenCenterX, 0) - _backgroundOffset);
- } else if (state == RenderTable::TILT) {
- newPoint -= (Common::Point(0, _screenCenterY) - _backgroundOffset);
+void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey) {
+ if (src.w == _dstRect.width() && src.h == _dstRect.height())
+ blitSurfaceToBkg(src, _dstRect.left, _dstRect.top, colorkey);
+ else {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ tmp->create(_dstRect.width(), _dstRect.height(), src.format);
+ scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height());
+ blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top, colorkey);
+ tmp->free();
+ delete tmp;
}
+}
+
+void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _menuWnd, x, y);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = dirty;
+ else
+ _menuWndDirtyRect.extend(dirty);
+}
+
+void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _menuWnd, x, y, colorkey);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = dirty;
+ else
+ _menuWndDirtyRect.extend(dirty);
+}
+
+Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) {
+ Common::Rect dst = rect;
+ dst.clip(_bkgWidth, _bkgHeight);
+
+ if (dst.isEmpty() || !dst.isValidRect())
+ return NULL;
+
+ Graphics::Surface *srf = new Graphics::Surface;
+ srf->create(dst.width(), dst.height(), _curBkg.format);
+
+ srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst));
+
+ return srf;
+}
+
+Graphics::Surface *RenderManager::loadImage(Common::String &file) {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ readImageToSurface(file, *tmp);
+ return tmp;
+}
- if (newPoint.x < 0)
- newPoint.x += _backgroundWidth;
- else if (newPoint.x >= _backgroundWidth)
- newPoint.x -= _backgroundWidth;
- if (newPoint.y < 0)
- newPoint.y += _backgroundHeight;
- else if (newPoint.y >= _backgroundHeight)
- newPoint.y -= _backgroundHeight;
+Graphics::Surface *RenderManager::loadImage(const char *file) {
+ Common::String str = Common::String(file);
+ return loadImage(str);
+}
- return newPoint;
+Graphics::Surface *RenderManager::loadImage(Common::String &file, bool transposed) {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ readImageToSurface(file, *tmp, transposed);
+ return tmp;
}
-const Common::Point RenderManager::imageSpaceToWorkingWindowSpace(const Common::Point &point) {
- Common::Point newPoint(point);
+Graphics::Surface *RenderManager::loadImage(const char *file, bool transposed) {
+ Common::String str = Common::String(file);
+ return loadImage(str, transposed);
+}
+void RenderManager::prepareBkg() {
+ _bkgDirtyRect.clip(_bkgWidth, _bkgHeight);
RenderTable::RenderState state = _renderTable.getRenderState();
+
if (state == RenderTable::PANORAMA) {
- newPoint += (Common::Point(_screenCenterX, 0) - _backgroundOffset);
+ Common::Rect viewPort(_wrkWidth, _wrkHeight);
+ viewPort.translate(-(_screenCenterX - _bkgOff), 0);
+ Common::Rect drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - _bkgOff + drawRect.left, drawRect.top);
+
+ _wrkWndDirtyRect = _bkgDirtyRect;
+ _wrkWndDirtyRect.translate(_screenCenterX - _bkgOff, 0);
+
+ if (_bkgOff < _screenCenterX) {
+ viewPort.moveTo(-(_screenCenterX - (_bkgOff + _bkgWidth)), 0);
+ drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - (_bkgOff + _bkgWidth) + drawRect.left, drawRect.top);
+
+ Common::Rect tmp = _bkgDirtyRect;
+ tmp.translate(_screenCenterX - (_bkgOff + _bkgWidth), 0);
+ if (!tmp.isEmpty())
+ _wrkWndDirtyRect.extend(tmp);
+
+ } else if (_bkgWidth - _bkgOff < _screenCenterX) {
+ viewPort.moveTo(-(_screenCenterX + _bkgWidth - _bkgOff), 0);
+ drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX + _bkgWidth - _bkgOff + drawRect.left, drawRect.top);
+
+ Common::Rect tmp = _bkgDirtyRect;
+ tmp.translate(_screenCenterX + _bkgWidth - _bkgOff, 0);
+ if (!tmp.isEmpty())
+ _wrkWndDirtyRect.extend(tmp);
+
+ }
} else if (state == RenderTable::TILT) {
- newPoint += (Common::Point(0, _screenCenterY) - _backgroundOffset);
+ Common::Rect viewPort(_wrkWidth, _wrkHeight);
+ viewPort.translate(0, -(_screenCenterY - _bkgOff));
+ Common::Rect drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, drawRect.left, _screenCenterY - _bkgOff + drawRect.top);
+
+ _wrkWndDirtyRect = _bkgDirtyRect;
+ _wrkWndDirtyRect.translate(0, _screenCenterY - _bkgOff);
+
+ } else {
+ if (!_bkgDirtyRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, _bkgDirtyRect, _wrkWnd, _bkgDirtyRect.left, _bkgDirtyRect.top);
+ _wrkWndDirtyRect = _bkgDirtyRect;
}
- return newPoint;
+ _bkgDirtyRect = Common::Rect();
+
+ _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight);
+}
+
+void RenderManager::clearMenuSurface() {
+ _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h);
+ _menuWnd.fillRect(_menuWndDirtyRect, 0);
}
-bool RenderManager::clipRectToWorkingWindow(Common::Rect &rect) {
- if (!_workingWindow.contains(rect)) {
- return false;
+void RenderManager::clearMenuSurface(const Common::Rect &r) {
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = r;
+ else
+ _menuWndDirtyRect.extend(r);
+ _menuWnd.fillRect(r, 0);
+}
+
+void RenderManager::renderMenuToScreen() {
+ if (!_menuWndDirtyRect.isEmpty()) {
+ _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h));
+ if (!_menuWndDirtyRect.isEmpty())
+ _system->copyRectToScreen(_menuWnd.getBasePtr(_menuWndDirtyRect.left, _menuWndDirtyRect.top), _menuWnd.pitch,
+ _menuWndDirtyRect.left + _menuWndRect.left,
+ _menuWndDirtyRect.top + _menuWndRect.top,
+ _menuWndDirtyRect.width(),
+ _menuWndDirtyRect.height());
+ _menuWndDirtyRect = Common::Rect();
}
+}
+
+uint16 RenderManager::createSubArea(const Common::Rect &area) {
+ _subid++;
+
+ oneSub sub;
+ sub.redraw = false;
+ sub.timer = -1;
+ sub.todelete = false;
+ sub.r = area;
- // We can't clip against the actual working window rect because it's in screen space
- // But rect is in working window space
- rect.clip(_workingWidth, _workingHeight);
- return true;
+ _subsList[_subid] = sub;
+
+ return _subid;
}
-RenderTable *RenderManager::getRenderTable() {
- return &_renderTable;
+uint16 RenderManager::createSubArea() {
+ _subid++;
+
+ oneSub sub;
+ sub.redraw = false;
+ sub.timer = -1;
+ sub.todelete = false;
+ sub.r = Common::Rect(_subWndRect.left, _subWndRect.top, _subWndRect.right, _subWndRect.bottom);
+ sub.r.translate(-_workingWindow.left, -_workingWindow.top);
+
+ _subsList[_subid] = sub;
+
+ return _subid;
}
-void RenderManager::setBackgroundImage(const Common::String &fileName) {
- readImageToSurface(fileName, _currentBackground);
+void RenderManager::deleteSubArea(uint16 id) {
+ if (_subsList.contains(id))
+ _subsList[id].todelete = true;
+}
- moveBackground(0);
+void RenderManager::deleteSubArea(uint16 id, int16 delay) {
+ if (_subsList.contains(id))
+ _subsList[id].timer = delay;
}
-void RenderManager::setBackgroundPosition(int offset) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::TILT) {
- _backgroundOffset.x = 0;
- _backgroundOffset.y = offset;
- } else if (state == RenderTable::PANORAMA) {
- _backgroundOffset.x = offset;
- _backgroundOffset.y = 0;
- } else {
- _backgroundOffset.x = 0;
- _backgroundOffset.y = 0;
+void RenderManager::updateSubArea(uint16 id, const Common::String &txt) {
+ if (_subsList.contains(id)) {
+ oneSub *sub = &_subsList[id];
+ sub->txt = txt;
+ sub->redraw = true;
}
}
-void RenderManager::setBackgroundVelocity(int velocity) {
- // setBackgroundVelocity(0) will be called quite often, so make sure
- // _backgroundInverseVelocity isn't already 0 to prevent an extraneous assignment
- if (velocity == 0) {
- if (_backgroundInverseVelocity != 0) {
- _backgroundInverseVelocity = 0;
+void RenderManager::processSubs(uint16 deltatime) {
+ bool redraw = false;
+ for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
+ if (it->_value.timer != -1) {
+ it->_value.timer -= deltatime;
+ if (it->_value.timer <= 0)
+ it->_value.todelete = true;
+ }
+ if (it->_value.todelete) {
+ _subsList.erase(it);
+ redraw = true;
+ } else if (it->_value.redraw) {
+ redraw = true;
}
- } else {
- _backgroundInverseVelocity = 1000 / velocity;
}
-}
-void RenderManager::moveBackground(int offset) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::TILT) {
- _backgroundOffset += Common::Point(0, offset);
+ if (redraw) {
+ _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0);
+
+ for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
+ oneSub *sub = &it->_value;
+ if (sub->txt.size()) {
+ Graphics::Surface *rndr = new Graphics::Surface();
+ rndr->create(sub->r.width(), sub->r.height(), _pixelFormat);
+ _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr);
+ blitSurfaceToSurface(*rndr, _subWnd, sub->r.left - _subWndRect.left + _workingWindow.left, sub->r.top - _subWndRect.top + _workingWindow.top);
+ rndr->free();
+ delete rndr;
+ }
+ sub->redraw = false;
+ }
- _backgroundOffset.y = CLIP<int16>(_backgroundOffset.y, _screenCenterY, (int16)_backgroundHeight - _screenCenterY);
+ _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch,
+ _subWndRect.left,
+ _subWndRect.top,
+ _subWnd.w,
+ _subWnd.h);
+ }
+}
- renderImageToScreen(_currentBackground, 0, _screenCenterY - _backgroundOffset.y, true);
- } else if (state == RenderTable::PANORAMA) {
- _backgroundOffset += Common::Point(offset, 0);
+Common::Point RenderManager::getBkgSize() {
+ return Common::Point(_bkgWidth, _bkgHeight);
+}
- if (_backgroundOffset.x <= -_backgroundWidth)
- _backgroundOffset.x += _backgroundWidth;
- else if (_backgroundOffset.x >= _backgroundWidth)
- _backgroundOffset.x -= _backgroundWidth;
+void RenderManager::addEffect(Effect *_effect) {
+ _effects.push_back(_effect);
+}
- renderImageToScreen(_currentBackground, _screenCenterX - _backgroundOffset.x, 0, true);
- } else {
- renderImageToScreen(_currentBackground, 0, 0);
+void RenderManager::deleteEffect(uint32 ID) {
+ for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) {
+ if ((*it)->getKey() == ID) {
+ delete *it;
+ it = _effects.erase(it);
+ }
}
}
-uint32 RenderManager::getCurrentBackgroundOffset() {
+Common::Rect RenderManager::bkgRectToScreen(const Common::Rect &src) {
+ Common::Rect tmp = src;
RenderTable::RenderState state = _renderTable.getRenderState();
if (state == RenderTable::PANORAMA) {
- return _backgroundOffset.x;
+ if (_bkgOff < _screenCenterX) {
+ Common::Rect rScreen(_screenCenterX + _bkgOff, _wrkHeight);
+ Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight);
+ lScreen.translate(_bkgWidth - lScreen.width(), 0);
+ lScreen.clip(src);
+ rScreen.clip(src);
+ if (rScreen.width() < lScreen.width()) {
+ tmp.translate(_screenCenterX - _bkgOff - _bkgWidth, 0);
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
+ } else if (_bkgWidth - _bkgOff < _screenCenterX) {
+ Common::Rect rScreen(_screenCenterX - (_bkgWidth - _bkgOff), _wrkHeight);
+ Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight);
+ lScreen.translate(_bkgWidth - lScreen.width(), 0);
+ lScreen.clip(src);
+ rScreen.clip(src);
+ if (lScreen.width() < rScreen.width()) {
+ tmp.translate(_screenCenterX + (_bkgWidth - _bkgOff), 0);
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
} else if (state == RenderTable::TILT) {
- return _backgroundOffset.y;
- } else {
- return 0;
+ tmp.translate(0, (_screenCenterY - _bkgOff));
}
+
+ return tmp;
}
-Graphics::Surface *RenderManager::tranposeSurface(const Graphics::Surface *surface) {
- Graphics::Surface *tranposedSurface = new Graphics::Surface();
- tranposedSurface->create(surface->h, surface->w, surface->format);
+EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *_minComp, int8 *_maxComp) {
+ Common::Rect bkgRect(_bkgWidth, _bkgHeight);
+ if (!bkgRect.contains(xy))
+ return NULL;
+
+ if (!bkgRect.intersects(rect))
+ return NULL;
+
+ uint16 color = *(uint16 *)_curBkg.getBasePtr(xy.x, xy.y);
+ uint8 stC1, stC2, stC3;
+ _curBkg.format.colorToRGB(color, stC1, stC2, stC3);
+ EffectMap *newMap = new EffectMap;
+
+ EffectMapUnit unit;
+ unit.count = 0;
+ unit.inEffect = false;
+
+ int16 w = rect.width();
+ int16 h = rect.height();
+
+ bool first = true;
+
+ uint8 minComp = MIN(MIN(stC1, stC2), stC3);
+ uint8 maxComp = MAX(MAX(stC1, stC2), stC3);
+
+ uint8 depth8 = depth << 3;
+
+ for (int16 j = 0; j < h; j++) {
+ uint16 *pix = (uint16 *)_curBkg.getBasePtr(rect.left, rect.top + j);
+ for (int16 i = 0; i < w; i++) {
+ uint16 curClr = pix[i];
+ uint8 cC1, cC2, cC3;
+ _curBkg.format.colorToRGB(curClr, cC1, cC2, cC3);
+
+ bool use = false;
+
+ if (curClr == color)
+ use = true;
+ else if (curClr > color) {
+ if ((cC1 - stC1 < depth8) &&
+ (cC2 - stC2 < depth8) &&
+ (cC3 - stC3 < depth8))
+ use = true;
+ } else { /* if (curClr < color) */
+ if ((stC1 - cC1 < depth8) &&
+ (stC2 - cC2 < depth8) &&
+ (stC3 - cC3 < depth8))
+ use = true;
+ }
- const uint16 *source = (const uint16 *)surface->getPixels();
- uint16 *dest = (uint16 *)tranposedSurface->getPixels();
+ if (first) {
+ unit.inEffect = use;
+ first = false;
+ }
- for (uint32 y = 0; y < tranposedSurface->h; ++y) {
- uint32 columnIndex = y * tranposedSurface->w;
+ if (use) {
+ uint8 cMinComp = MIN(MIN(cC1, cC2), cC3);
+ uint8 cMaxComp = MAX(MAX(cC1, cC2), cC3);
+ if (cMinComp < minComp)
+ minComp = cMinComp;
+ if (cMaxComp > maxComp)
+ maxComp = cMaxComp;
+ }
- for (uint32 x = 0; x < tranposedSurface->w; ++x) {
- dest[columnIndex + x] = source[x * surface->w + y];
+ if (unit.inEffect == use)
+ unit.count++;
+ else {
+ newMap->push_back(unit);
+ unit.count = 1;
+ unit.inEffect = use;
+ }
}
}
+ newMap->push_back(unit);
- return tranposedSurface;
+ if (_minComp) {
+ if (minComp - depth8 < 0)
+ *_minComp = -(minComp >> 3);
+ else
+ *_minComp = -depth;
+ }
+ if (_maxComp) {
+ if ((int16)maxComp + (int16)depth8 > 255)
+ *_maxComp = (255 - maxComp) >> 3;
+ else
+ *_maxComp = depth;
+ }
+
+ return newMap;
+}
+
+EffectMap *RenderManager::makeEffectMap(const Graphics::Surface &surf, uint16 transp) {
+ EffectMapUnit unit;
+ unit.count = 0;
+ unit.inEffect = false;
+
+ int16 w = surf.w;
+ int16 h = surf.h;
+
+ EffectMap *newMap = new EffectMap;
+
+ bool first = true;
+
+ for (int16 j = 0; j < h; j++) {
+ const uint16 *pix = (const uint16 *)surf.getBasePtr(0, j);
+ for (int16 i = 0; i < w; i++) {
+ bool use = false;
+ if (pix[i] != transp)
+ use = true;
+
+ if (first) {
+ unit.inEffect = use;
+ first = false;
+ }
+
+ if (unit.inEffect == use)
+ unit.count++;
+ else {
+ newMap->push_back(unit);
+ unit.count = 1;
+ unit.inEffect = use;
+ }
+ }
+ }
+ newMap->push_back(unit);
+
+ return newMap;
+}
+
+void RenderManager::markDirty() {
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+}
+
+void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) {
+ _curBkg.fillRect(Common::Rect(_curBkg.w, _curBkg.h), _curBkg.format.RGBToColor(r, g, b));
+ markDirty();
}
} // End of namespace ZVision
diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h
index 9feff4c030..879a8643ce 100644
--- a/engines/zvision/graphics/render_manager.h
+++ b/engines/zvision/graphics/render_manager.h
@@ -8,12 +8,12 @@
* 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.
@@ -24,13 +24,14 @@
#define ZVISION_RENDER_MANAGER_H
#include "zvision/graphics/render_table.h"
-#include "zvision/fonts/truetype_font.h"
+#include "zvision/graphics/truetype_font.h"
#include "common/rect.h"
#include "common/hashmap.h"
#include "graphics/surface.h"
+#include "effect.h"
class OSystem;
@@ -47,43 +48,53 @@ namespace ZVision {
class RenderManager {
public:
- RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat);
+ RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat);
~RenderManager();
private:
- struct AlphaDataEntry {
- Graphics::Surface *data;
- uint16 alphaColor;
- uint16 destX;
- uint16 destY;
- uint16 width;
- uint16 height;
+ struct oneSub {
+ Common::Rect r;
+ Common::String txt;
+ int16 timer;
+ bool todelete;
+ bool redraw;
};
- typedef Common::HashMap<uint32, AlphaDataEntry> AlphaEntryMap;
+ typedef Common::HashMap<uint16, oneSub> subMap;
+ typedef Common::List<Effect *> effectsList;
private:
+ ZVision *_engine;
OSystem *_system;
const Graphics::PixelFormat _pixelFormat;
- // A buffer the exact same size as the workingWindow
- // This buffer stores everything un-warped, then does a warp at the end of the frame
- Graphics::Surface _workingWindowBuffer;
- // A buffer representing the entire screen. Any graphical updates are first done with this buffer
- // before actually being blitted to the screen
- Graphics::Surface _backBuffer;
- // A list of Alpha Entries that need to be blitted to the backbuffer
- AlphaEntryMap _alphaDataEntries;
+ // A buffer for blitting background image to working window
+ Graphics::Surface _wrkWnd;
+
+ Common::Rect _wrkWndDirtyRect;
+
+ // A buffer for mutate image by tilt or panorama renderers
+ Graphics::Surface _outWnd;
- // A rectangle representing the portion of the working window where the pixels have been changed since last frame
- Common::Rect _workingWindowDirtyRect;
- // A rectangle representing the portion of the backbuffer where the pixels have been changed since last frame
- Common::Rect _backBufferDirtyRect;
+ Common::Rect _bkgDirtyRect;
+
+ // A buffer for subtitles
+ Graphics::Surface _subWnd;
+
+ Common::Rect _subWndDirtyRect;
+
+ // A buffer for menu drawing
+ Graphics::Surface _menuWnd;
+
+ Common::Rect _menuWndDirtyRect;
+
+ // A buffer used for apply graphics effects
+ Graphics::Surface _effectWnd;
/** Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() */
- const int _workingWidth;
+ const int _wrkWidth;
/** Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() */
- const int _workingHeight;
+ const int _wrkHeight;
/** Center of the screen in the x direction */
const int _screenCenterX;
/** Center of the screen in the y direction */
@@ -95,33 +106,36 @@ private:
* edges of this Rectangle
*/
const Common::Rect _workingWindow;
+
+ // Recatangle for subtitles area
+ Common::Rect _subWndRect;
+
+ // Recatangle for menu area
+ Common::Rect _menuWndRect;
+
/** Used to warp the background image */
RenderTable _renderTable;
- Graphics::Surface _currentBackground;
+ // A buffer for background image
+ Graphics::Surface _curBkg;
/** The (x1,y1) coordinates of the subRectangle of the background that is currently displayed on the screen */
- Common::Point _backgroundOffset;
+ int16 _bkgOff;
/** The width of the current background image */
- uint16 _backgroundWidth;
+ uint16 _bkgWidth;
/** The height of the current background image */
- uint16 _backgroundHeight;
+ uint16 _bkgHeight;
- /**
- * The "velocity" at which the background image is panning. We actually store the inverse of velocity (ms/pixel instead of pixels/ms)
- * because it allows you to accumulate whole pixels 'steps' instead of rounding pixels every frame
- */
- int _backgroundInverseVelocity;
- /** Holds any 'leftover' milliseconds between frames */
- uint _accumulatedVelocityMilliseconds;
+ // Internal subtitles counter
+ uint16 _subid;
+
+ // Subtitle list
+ subMap _subsList;
+
+ // Visual effects list
+ effectsList _effects;
public:
void initialize();
- /**
- * Rotates the background image in accordance to the current _backgroundInverseVelocity
- *
- * @param deltaTimeInMillis The amount of time that has passed since the last frame
- */
- void update(uint deltaTimeInMillis);
/**
* Renders the current state of the backbuffer to the screen
@@ -129,89 +143,34 @@ public:
void renderBackbufferToScreen();
/**
- * Renders all AlphaEntries to the backbuffer
- */
- void processAlphaEntries();
- /**
- * Clears the AlphaEntry list
- */
- void clearAlphaEntries() { _alphaDataEntries.clear(); }
- /**
- * Removes a specific AlphaEntry from the list
- *
- * @param idNumber The id number identifing the AlphaEntry
- */
- void removeAlphaEntry(uint32 idNumber) { _alphaDataEntries.erase(idNumber); }
-
- /**
- * Copies a sub-rectangle of a buffer to the working window
- *
- * @param buffer The pixel data to copy to the working window
- * @param destX The X destination in the working window where the subRect of data should be put
- * @param destY The Y destination in the working window where the subRect of data should be put
- * @param imageWidth The width of the source image
- * @param width The width of the sub rectangle
- * @param height The height of the sub rectangle
- */
- void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height);
- /**
- * Copies a sub-rectangle of a buffer to the working window with binary alpha support.
- *
- * @param buffer The pixel data to copy to the working window
- * @param destX The X destination in the working window where the subRect of data should be put
- * @param destY The Y destination in the working window where the subRect of data should be put
- * @param imageWidth The width of the source image
- * @param width The width of the sub rectangle
- * @param height The height of the sub rectangle
- * @param alphaColor The color to interpret as meaning 'transparent'
- * @param idNumber A unique identifier for the data being copied over.
- */
- void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber);
-
- /**
- * Renders the supplied text to the working window
+ * Blits the image or a portion of the image to the background.
*
- * @param idNumber A unique identifier for the text
- * @param text The text to be rendered
- * @param font The font to use to render the text
- * @param destX The X destination in the working window where the text should be rendered
- * @param destY The Y destination in the working window where the text should be rendered
- * @param textColor The color to render the text with (in RBG 565)
- * @param maxWidth The max width the text should take up.
- * @param maxHeight The max height the text should take up.
- * @param align The alignment of the text within the bounds of maxWidth
- * @param wrap If true, any words extending past maxWidth will wrap to a new line. If false, ellipses will be rendered to show that the text didn't fit
- * @return A rectangle representing where the text was drawn in the working window
- */
- Common::Rect renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight = -1, Graphics::TextAlign align = Graphics::kTextAlignLeft, bool wrap = true);
-
- /**
- * Fills the entire workingWindow with the specified color. Internally, the color
- * will be converted to RGB 565 and then blitted.
- *
- * @param color The color to fill the working window with. (In RGB 555)
+ * @param fileName Name of the image file
+ * @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
+ * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
*/
- void clearWorkingWindowTo555Color(uint16 color);
+ void renderImageToBackground(const Common::String &fileName, int16 destinationX, int16 destinationY);
/**
- * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame.
- * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space!
+ * Blits the image or a portion of the image to the background.
*
- * @param fileName Name of the image file
- * @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
- * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
+ * @param fileName Name of the image file
+ * @param destX X position where the image should be put. Coords are in working window space, not screen space!
+ * @param destY Y position where the image should be put. Coords are in working window space, not screen space!
+ * @param colorkey Transparent color
*/
- void renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap = false);
+ void renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 colorkey);
/**
- * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame.
- * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space!
+ * Blits the image or a portion of the image to the background.
*
- * @param stream Surface to read the image data from
- * @param destinationX X position where the image should be put. Coords are in working window space, not screen space!
- * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space!
+ * @param fileName Name of the image file
+ * @param destX X position where the image should be put. Coords are in working window space, not screen space!
+ * @param destY Y position where the image should be put. Coords are in working window space, not screen space!
+ * @param keyX X position of transparent color
+ * @param keyY Y position of transparent color
*/
- void renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap = false);
+ void renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY);
/**
* Sets the current background image to be used by the RenderManager and immediately
@@ -234,41 +193,18 @@ public:
void setBackgroundPosition(int offset);
/**
- * Set the background scroll velocity. Negative velocities correspond to left / up scrolling and
- * positive velocities correspond to right / down scrolling
- *
- * @param velocity Velocity
- */
- void setBackgroundVelocity(int velocity);
-
- /**
* Converts a point in screen coordinate space to image coordinate space
*
* @param point Point in screen coordinate space
* @return Point in image coordinate space
*/
const Common::Point screenSpaceToImageSpace(const Common::Point &point);
- /**
- * Converts a point in image coordinate space to ***PRE-WARP***
- * working window coordinate space
- *
- * @param point Point in image coordinate space
- * @return Point in PRE-WARP working window coordinate space
- */
- const Common::Point imageSpaceToWorkingWindowSpace(const Common::Point &point);
-
- /**
- * Clip a rectangle to the working window. If it returns false, the original rect
- * is not inside the working window.
- *
- * @param rect The rectangle to clip against the working window
- * @return Is rect at least partially inside the working window (true) or completely outside (false)
- */
- bool clipRectToWorkingWindow(Common::Rect &rect);
+ // Return pointer of RenderTable object
RenderTable *getRenderTable();
+
+ // Return current background offset
uint32 getCurrentBackgroundOffset();
- const Graphics::Surface *getBackBuffer() { return &_backBuffer; }
/**
* Creates a copy of surface and transposes the data.
@@ -281,21 +217,64 @@ public:
*/
static Graphics::Surface *tranposeSurface(const Graphics::Surface *surface);
-private:
- /**
- * Renders a subRectangle of an image to the backbuffer. The destinationRect and SubRect
- * will be clipped to image bound and to working window bounds
- *
- * @param buffer Pointer to (0, 0) of the image data
- * @param imageWidth The width of the original image (not of the subRectangle)
- * @param imageHeight The width of the original image (not of the subRectangle)
- * @param horizontalPitch The horizontal pitch of the original image
- * @param destinationX The x coordinate (in working window space) of where to put the final image
- * @param destinationY The y coordinate (in working window space) of where to put the final image
- * @param subRectangle A rectangle representing the part of the image that should be rendered
- * @param wrap Should the image wrap (tile) if it doesn't completely fill the screen?
- */
- void renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap);
+ // Scale buffer (nearest)
+ void scaleBuffer(const void *src, void *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint32 dstWidth, uint32 dstHeight);
+
+ // Blitting surface-to-surface methods
+ void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int x, int y);
+ void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey);
+ void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y);
+ void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey);
+
+ // Blitting surface-to-background methods
+ void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y);
+ void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey);
+
+ // Blitting surface-to-background methods with scale
+ void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect);
+ void blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey);
+
+ // Blitting surface-to-menu methods
+ void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y);
+ void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey);
+
+ // Subtitles methods
+
+ // Create subtitle area and return ID
+ uint16 createSubArea(const Common::Rect &area);
+ uint16 createSubArea();
+
+ // Delete subtitle by ID
+ void deleteSubArea(uint16 id);
+ void deleteSubArea(uint16 id, int16 delay);
+
+ // Update subtitle area
+ void updateSubArea(uint16 id, const Common::String &txt);
+
+ // Processing subtitles
+ void processSubs(uint16 deltatime);
+
+ // Return background size
+ Common::Point getBkgSize();
+
+ // Return portion of background as new surface
+ Graphics::Surface *getBkgRect(Common::Rect &rect);
+
+ // Load image into new surface
+ Graphics::Surface *loadImage(const char *file);
+ Graphics::Surface *loadImage(Common::String &file);
+ Graphics::Surface *loadImage(const char *file, bool transposed);
+ Graphics::Surface *loadImage(Common::String &file, bool transposed);
+
+ // Clear whole/area of menu surface
+ void clearMenuSurface();
+ void clearMenuSurface(const Common::Rect &r);
+
+ // Copy menu buffer to screen
+ void renderMenuToScreen();
+
+ // Copy needed portion of background surface to workingWindow surface
+ void prepareBkg();
/**
* Reads an image file pixel data into a Surface buffer. In the process
@@ -310,17 +289,43 @@ private:
void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination);
/**
- * Move the background image by an offset. If we are currently in Panorama mode,
- * the offset will correspond to a horizontal motion. If we are currently in Tilt mode,
- * the offset will correspond to a vertical motion. This function should not be called
- * if we are in Flat mode.
- *
- * The RenderManager will take care of wrapping the image.
- * Ex: If the image has width 1400px, it is legal to offset 1500px.
+ * Reads an image file pixel data into a Surface buffer. In the process
+ * it converts the pixel data from RGB 555 to RGB 565. Also, if the image
+ * is transposed, it will un-transpose the pixel data. The function will
+ * call destination::create() if the dimensions of destination do not match
+ * up with the dimensions of the image.
*
- * @param offset The amount to move the background
+ * @param fileName The name of a .tga file
+ * @param destination A reference to the Surface to store the pixel data in
+ * @param transposed Transpose flag
*/
- void moveBackground(int offset);
+ void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed);
+
+ // Add visual effect to effects list
+ void addEffect(Effect *_effect);
+
+ // Delete effect(s) by ID (ID equal to slot of action:region that create this effect)
+ void deleteEffect(uint32 ID);
+
+ // Create "mask" for effects - (color +/- depth) will be selected as not transparent. Like color selection
+ // xy - base color
+ // depth - +/- of base color
+ // rect - rectangle where select pixels
+ // minD - if not NULL will recieve real bottom border of depth
+ // maxD - if not NULL will recieve real top border of depth
+ EffectMap *makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *minD, int8 *maxD);
+
+ // Create "mask" for effects by simple transparent color
+ EffectMap *makeEffectMap(const Graphics::Surface &surf, uint16 transp);
+
+ // Return background rectangle in screen coordinates
+ Common::Rect bkgRectToScreen(const Common::Rect &src);
+
+ // Mark whole background surface as dirty
+ void markDirty();
+
+ // Fille background surface by color
+ void bkgFill(uint8 r, uint8 g, uint8 b);
};
} // End of namespace ZVision
diff --git a/engines/zvision/graphics/render_table.cpp b/engines/zvision/graphics/render_table.cpp
index 49b934dc37..54faecfa8b 100644
--- a/engines/zvision/graphics/render_table.cpp
+++ b/engines/zvision/graphics/render_table.cpp
@@ -21,20 +21,16 @@
*/
#include "common/scummsys.h"
-
#include "zvision/graphics/render_table.h"
-
#include "common/rect.h"
-
#include "graphics/colormasks.h"
-
namespace ZVision {
RenderTable::RenderTable(uint numColumns, uint numRows)
- : _numRows(numRows),
- _numColumns(numColumns),
- _renderState(FLAT) {
+ : _numRows(numRows),
+ _numColumns(numColumns),
+ _renderState(FLAT) {
assert(numRows != 0 && numColumns != 0);
_internalBuffer = new Common::Point[numRows * numColumns];
@@ -52,10 +48,11 @@ void RenderTable::setRenderState(RenderState newState) {
_panoramaOptions.fieldOfView = 27.0f;
_panoramaOptions.linearScale = 0.55f;
_panoramaOptions.reverse = false;
+ _panoramaOptions.zeroPoint = 0;
break;
case TILT:
_tiltOptions.fieldOfView = 27.0f;
- _tiltOptions.linearScale = 0.55f;
+ _tiltOptions.linearScale = 0.65f;
_tiltOptions.reverse = false;
break;
case FLAT:
@@ -97,12 +94,12 @@ uint16 mixTwoRGB(uint16 colorOne, uint16 colorTwo, float percentColorOne) {
uint16 returnColor = (byte(rFinal + 0.5f) << Graphics::ColorMasks<555>::kRedShift) |
(byte(gFinal + 0.5f) << Graphics::ColorMasks<555>::kGreenShift) |
- (byte(bFinal + 0.5f) << Graphics::ColorMasks<555>::kBlueShift);
+ (byte(bFinal + 0.5f) << Graphics::ColorMasks<555>::kBlueShift);
return returnColor;
}
-void RenderTable::mutateImage(uint16 *sourceBuffer, uint16* destBuffer, uint32 destWidth, const Common::Rect &subRect) {
+void RenderTable::mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect) {
uint32 destOffset = 0;
for (int16 y = subRect.top; y < subRect.bottom; ++y) {
@@ -123,6 +120,28 @@ void RenderTable::mutateImage(uint16 *sourceBuffer, uint16* destBuffer, uint32 d
}
}
+void RenderTable::mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf) {
+ uint32 destOffset = 0;
+
+ uint16 *sourceBuffer = (uint16 *)srcBuf->getPixels();
+ uint16 *destBuffer = (uint16 *)dstBuf->getPixels();
+
+ for (int16 y = 0; y < srcBuf->h; ++y) {
+ uint32 sourceOffset = y * _numColumns;
+
+ for (int16 x = 0; x < srcBuf->w; ++x) {
+ uint32 index = sourceOffset + x;
+
+ // RenderTable only stores offsets from the original coordinates
+ uint32 sourceYIndex = y + _internalBuffer[index].y;
+ uint32 sourceXIndex = x + _internalBuffer[index].x;
+
+ destBuffer[destOffset] = sourceBuffer[sourceYIndex * _numColumns + sourceXIndex];
+ destOffset++;
+ }
+ }
+}
+
void RenderTable::generateRenderTable() {
switch (_renderState) {
case ZVision::RenderTable::PANORAMA:
@@ -177,6 +196,7 @@ void RenderTable::generateTiltLookupTable() {
float fovInRadians = (_tiltOptions.fieldOfView * M_PI / 180.0f);
float cylinderRadius = halfWidth / tan(fovInRadians);
+ _tiltOptions.gap = cylinderRadius * atan2((float)(halfHeight / cylinderRadius), 1.0f) * _tiltOptions.linearScale;
for (uint y = 0; y < _numRows; ++y) {
@@ -221,6 +241,18 @@ void RenderTable::setPanoramaReverse(bool reverse) {
_panoramaOptions.reverse = reverse;
}
+bool RenderTable::getPanoramaReverse() {
+ return _panoramaOptions.reverse;
+}
+
+void RenderTable::setPanoramaZeroPoint(uint16 point) {
+ _panoramaOptions.zeroPoint = point;
+}
+
+uint16 RenderTable::getPanoramaZeroPoint() {
+ return _panoramaOptions.zeroPoint;
+}
+
void RenderTable::setTiltFoV(float fov) {
assert(fov > 0.0f);
@@ -237,4 +269,26 @@ void RenderTable::setTiltReverse(bool reverse) {
_tiltOptions.reverse = reverse;
}
+float RenderTable::getTiltGap() {
+ return _tiltOptions.gap;
+}
+
+float RenderTable::getAngle() {
+ if (_renderState == TILT)
+ return _tiltOptions.fieldOfView;
+ else if (_renderState == PANORAMA)
+ return _panoramaOptions.fieldOfView;
+ else
+ return 1.0;
+}
+
+float RenderTable::getLinscale() {
+ if (_renderState == TILT)
+ return _tiltOptions.linearScale;
+ else if (_renderState == PANORAMA)
+ return _panoramaOptions.linearScale;
+ else
+ return 1.0;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/graphics/render_table.h b/engines/zvision/graphics/render_table.h
index f066187ad1..7455d9ba39 100644
--- a/engines/zvision/graphics/render_table.h
+++ b/engines/zvision/graphics/render_table.h
@@ -24,7 +24,7 @@
#define ZVISION_RENDER_TABLE_H
#include "common/rect.h"
-
+#include "graphics/surface.h"
namespace ZVision {
@@ -49,6 +49,7 @@ private:
float fieldOfView;
float linearScale;
bool reverse;
+ uint16 zeroPoint;
} _panoramaOptions;
// TODO: See if tilt and panorama need to have separate options
@@ -56,25 +57,36 @@ private:
float fieldOfView;
float linearScale;
bool reverse;
+ float gap;
} _tiltOptions;
public:
- RenderState getRenderState() { return _renderState; }
+ RenderState getRenderState() {
+ return _renderState;
+ }
void setRenderState(RenderState newState);
const Common::Point convertWarpedCoordToFlatCoord(const Common::Point &point);
- void mutateImage(uint16 *sourceBuffer, uint16* destBuffer, uint32 destWidth, const Common::Rect &subRect);
+ void mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect);
+ void mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf);
void generateRenderTable();
void setPanoramaFoV(float fov);
void setPanoramaScale(float scale);
void setPanoramaReverse(bool reverse);
+ void setPanoramaZeroPoint(uint16 point);
+ uint16 getPanoramaZeroPoint();
+ bool getPanoramaReverse();
void setTiltFoV(float fov);
void setTiltScale(float scale);
void setTiltReverse(bool reverse);
+ float getTiltGap();
+ float getAngle();
+ float getLinscale();
+
private:
void generatePanoramaLookupTable();
void generateTiltLookupTable();
diff --git a/engines/zvision/graphics/subtitles.cpp b/engines/zvision/graphics/subtitles.cpp
new file mode 100644
index 0000000000..784721562a
--- /dev/null
+++ b/engines/zvision/graphics/subtitles.cpp
@@ -0,0 +1,108 @@
+/* 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 "zvision/graphics/render_manager.h"
+#include "zvision/graphics/subtitles.h"
+#include "zvision/core/search_manager.h"
+#include "zvision/text/text.h"
+
+namespace ZVision {
+
+Subtitle::Subtitle(ZVision *engine, const Common::String &subname) :
+ _engine(engine),
+ _areaId(-1),
+ _subId(-1) {
+ Common::File file;
+ if (_engine->getSearchManager()->openFile(file, subname)) {
+ while (!file.eos()) {
+ Common::String str = file.readLine();
+ if (str.lastChar() == '~')
+ str.deleteLastChar();
+
+ if (str.matchString("*Initialization*", true)) {
+ // Not used
+ } else if (str.matchString("*Rectangle*", true)) {
+ int32 x1, y1, x2, y2;
+ sscanf(str.c_str(), "%*[^:]:%d %d %d %d", &x1, &y1, &x2, &y2);
+ Common::Rect rct = Common::Rect(x1, y1, x2, y2);
+ _areaId = _engine->getRenderManager()->createSubArea(rct);
+ } else if (str.matchString("*TextFile*", true)) {
+ char filename[64];
+ sscanf(str.c_str(), "%*[^:]:%s", filename);
+ Common::File txt;
+ if (_engine->getSearchManager()->openFile(txt, filename)) {
+ while (!txt.eos()) {
+ Common::String txtline = readWideLine(txt);
+ sub curSubtitle;
+ curSubtitle.start = -1;
+ curSubtitle.stop = -1;
+ curSubtitle.subStr = txtline;
+
+ _subs.push_back(curSubtitle);
+ }
+ txt.close();
+ }
+ } else {
+ int32 st;
+ int32 en;
+ int32 sb;
+ if (sscanf(str.c_str(), "%*[^:]:(%d,%d)=%d", &st, &en, &sb) == 3) {
+ if (sb <= (int32)_subs.size()) {
+ _subs[sb].start = st;
+ _subs[sb].stop = en;
+ }
+ }
+ }
+ }
+ }
+}
+
+Subtitle::~Subtitle() {
+ if (_areaId != -1)
+ _engine->getRenderManager()->deleteSubArea(_areaId);
+
+ _subs.clear();
+}
+
+void Subtitle::process(int32 time) {
+ int16 j = -1;
+ for (uint16 i = 0; i < _subs.size(); i++)
+ if (time >= _subs[i].start && time <= _subs[i].stop) {
+ j = i;
+ break;
+ }
+
+ if (j == -1 && _subId != -1) {
+ if (_areaId != -1)
+ _engine->getRenderManager()->updateSubArea(_areaId, "");
+ _subId = -1;
+ }
+
+ if (j != -1 && j != _subId) {
+ if (_subs[j].subStr.size())
+ if (_areaId != -1)
+ _engine->getRenderManager()->updateSubArea(_areaId, _subs[j].subStr);
+ _subId = j;
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/subtitles/subtitles.h b/engines/zvision/graphics/subtitles.h
index 776ddd3a97..c3da6583a4 100644
--- a/engines/zvision/subtitles/subtitles.h
+++ b/engines/zvision/graphics/subtitles.h
@@ -23,6 +23,32 @@
#ifndef ZVISION_SUBTITLES_H
#define ZVISION_SUBTITLES_H
-// TODO: Implement Subtitles
+#include "zvision/zvision.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class Subtitle {
+public:
+ Subtitle(ZVision *engine, const Common::String &subname);
+ ~Subtitle();
+
+ void process(int32 time);
+private:
+ ZVision *_engine;
+ int32 _areaId;
+ int16 _subId;
+
+ struct sub {
+ int start;
+ int stop;
+ Common::String subStr;
+ };
+
+ Common::Array<sub> _subs;
+};
+
+}
#endif
diff --git a/engines/zvision/graphics/truetype_font.cpp b/engines/zvision/graphics/truetype_font.cpp
new file mode 100644
index 0000000000..1a0e92087c
--- /dev/null
+++ b/engines/zvision/graphics/truetype_font.cpp
@@ -0,0 +1,341 @@
+/* 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/file.h"
+#include "common/system.h"
+#include "common/unzip.h"
+#include "graphics/font.h"
+#include "graphics/fonts/ttf.h"
+#include "graphics/surface.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/graphics/truetype_font.h"
+
+namespace ZVision {
+
+TruetypeFont::TruetypeFont(ZVision *engine, int32 fontHeight)
+ : _engine(engine),
+ _fontHeight(fontHeight),
+ _font(0),
+ _lineHeight(0),
+ _maxCharWidth(0),
+ _maxCharHeight(0) {
+}
+
+TruetypeFont::~TruetypeFont(void) {
+ delete _font;
+}
+
+bool TruetypeFont::loadFile(const Common::String &filename) {
+ Common::File file;
+
+ bool fileOpened = false;
+ if (!Common::File::exists(filename)) {
+ debug("TTF font file %s was not found. Reverting to arial.ttf", filename.c_str());
+ fileOpened = file.open("arial.ttf");
+ } else {
+ fileOpened = file.open(filename);
+ }
+
+ if (!fileOpened) {
+ debug("TTF file could not be opened");
+ return false;
+ }
+
+ _font = Graphics::loadTTFFont(file, _fontHeight);
+ _lineHeight = _font->getFontHeight();
+
+ return true;
+}
+
+Graphics::Surface *TruetypeFont::drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
+ if (text.equals("")) {
+ return nullptr;
+ }
+
+ Graphics::Surface *surface = new Graphics::Surface();
+
+ if (!wrap) {
+ int width = MIN(_font->getStringWidth(text), maxWidth);
+ surface->create(width, _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ // TODO: Add better alpha support by getting the pixels from the backbuffer.
+ // However doing that requires some kind of caching system so future text doesn't try to use this text as it's alpha background.
+ surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
+
+ _font->drawString(surface, text, 0, 0, maxWidth, textColor, align);
+ return surface;
+ }
+
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text, maxWidth, lines);
+
+ while (maxHeight > 0 && (int)lines.size() * _lineHeight > maxHeight) {
+ lines.pop_back();
+ }
+ if (lines.size() == 0) {
+ delete surface;
+ return nullptr;
+ }
+
+ surface->create(maxWidth, lines.size() * _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0);
+
+ int heightOffset = 0;
+ for (Common::Array<Common::String>::iterator it = lines.begin(); it != lines.end(); it++) {
+ _font->drawString(surface, *it, 0, 0 + heightOffset, maxWidth, textColor, align);
+ heightOffset += _lineHeight;
+ }
+
+ return surface;
+}
+
+StyledTTFont::StyledTTFont(ZVision *engine) {
+ _engine = engine;
+ _style = 0;
+ _font = NULL;
+ _lineHeight = 0;
+}
+
+StyledTTFont::~StyledTTFont() {
+ if (_font)
+ delete _font;
+}
+
+bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint style) {
+ _style = style;
+ return loadFont(fontName, point);
+}
+
+bool StyledTTFont::loadFont(const Common::String &fontName, int32 point) {
+ Common::String newFontName;
+ if (fontName.matchString("*times new roman*", true) || fontName.matchString("*times*", true)) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC))
+ newFontName = "timesbi.ttf";
+ else if (_style & STTF_BOLD)
+ newFontName = "timesbd.ttf";
+ else if (_style & STTF_ITALIC)
+ newFontName = "timesi.ttf";
+ else
+ newFontName = "times.ttf";
+
+ } else if (fontName.matchString("*courier new*", true) || fontName.matchString("*courier*", true) || fontName.matchString("*ZorkDeath*", true)) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC))
+ newFontName = "courbi.ttf";
+ else if (_style & STTF_BOLD)
+ newFontName = "courbd.ttf";
+ else if (_style & STTF_ITALIC)
+ newFontName = "couri.ttf";
+ else
+ newFontName = "cour.ttf";
+
+ } else if (fontName.matchString("*century schoolbook*", true)) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC))
+ newFontName = "censcbkbi.ttf";
+ else if (_style & STTF_BOLD)
+ newFontName = "censcbkbd.ttf";
+ else if (_style & STTF_ITALIC)
+ newFontName = "censcbki.ttf";
+ else
+ newFontName = "censcbk.ttf";
+
+ } else if (fontName.matchString("*garamond*", true)) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC))
+ newFontName = "garabi.ttf";
+ else if (_style & STTF_BOLD)
+ newFontName = "garabd.ttf";
+ else if (_style & STTF_ITALIC)
+ newFontName = "garai.ttf";
+ else
+ newFontName = "gara.ttf";
+
+ } else if (fontName.matchString("*arial*", true) || fontName.matchString("*ZorkNormal*", true)) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC)) == (STTF_BOLD | STTF_ITALIC))
+ newFontName = "arialbi.ttf";
+ else if (_style & STTF_BOLD)
+ newFontName = "arialbd.ttf";
+ else if (_style & STTF_ITALIC)
+ newFontName = "ariali.ttf";
+ else
+ newFontName = "arial.ttf";
+
+ } else {
+ debug("Could not identify font: %s. Reverting to Arial", fontName.c_str());
+ newFontName = "arial.ttf";
+ }
+
+ bool sharp = (_style & STTF_SHARP) == STTF_SHARP;
+
+ Common::File *file = _engine->getSearchManager()->openFile(newFontName);
+
+ if (!file) {
+ Common::SeekableReadStream *themeFile = nullptr;
+ if (ConfMan.hasKey("themepath")) {
+ Common::FSNode themePath(ConfMan.get("themepath"));
+ if (themePath.exists()) {
+ Common::FSNode scummModern = themePath.getChild("scummmodern.zip");
+ if (scummModern.exists()) {
+ themeFile = scummModern.createReadStream();
+ }
+ }
+ }
+ if (!themeFile) { // Fallback : Search for ScummModern.zip in SearchMan.
+ themeFile = SearchMan.createReadStreamForMember("scummmodern.zip");
+ }
+ if (themeFile) {
+ Common::Archive *themeArchive = Common::makeZipArchive(themeFile);
+ if (themeArchive->hasFile("FreeSans.ttf")) {
+ Common::SeekableReadStream *stream = nullptr;
+ stream = themeArchive->createReadStreamForMember("FreeSans.ttf");
+ Graphics::Font *_newFont = Graphics::loadTTFFont(*stream, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display
+ if (_newFont) {
+ if (!_font)
+ delete _font;
+ _font = _newFont;
+ }
+ if (stream)
+ delete stream;
+ }
+ delete themeArchive;
+ themeArchive = nullptr;
+ }
+ } else {
+ Graphics::Font *_newFont = Graphics::loadTTFFont(*file, point, 60, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal)); // 66 dpi for 640 x 480 on 14" display
+ if (_newFont) {
+ if (!_font)
+ delete _font;
+ _font = _newFont;
+ }
+ delete file;
+ }
+
+ _fntName = fontName;
+ _lineHeight = point;
+
+ if (_font)
+ return true;
+ return false;
+}
+
+void StyledTTFont::setStyle(uint newStyle) {
+ if ((_style & (STTF_BOLD | STTF_ITALIC | STTF_SHARP)) != (newStyle & (STTF_BOLD | STTF_ITALIC | STTF_SHARP))) {
+ _style = newStyle;
+ loadFont(_fntName, _lineHeight);
+ } else {
+ _style = newStyle;
+ }
+}
+
+int StyledTTFont::getFontHeight() {
+ if (_font)
+ return _font->getFontHeight();
+ return 0;
+}
+
+int StyledTTFont::getMaxCharWidth() {
+ if (_font)
+ return _font->getMaxCharWidth();
+ return 0;
+}
+
+int StyledTTFont::getCharWidth(byte chr) {
+ if (_font)
+ return _font->getCharWidth(chr);
+ return 0;
+}
+
+int StyledTTFont::getKerningOffset(byte left, byte right) {
+ if (_font)
+ return _font->getKerningOffset(left, right);
+ return 0;
+}
+
+void StyledTTFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) {
+ if (_font) {
+ _font->drawChar(dst, chr, x, y, color);
+ if (_style & STTF_UNDERLINE) {
+ int16 pos = floor(_font->getFontHeight() * 0.87);
+ int thk = MAX((int)(_font->getFontHeight() * 0.05), 1);
+ dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color);
+ }
+ if (_style & STTF_STRIKEOUT) {
+ int16 pos = floor(_font->getFontHeight() * 0.60);
+ int thk = MAX((int)(_font->getFontHeight() * 0.05), 1);
+ dst->fillRect(Common::Rect(x, y + pos, x + _font->getCharWidth(chr), y + pos + thk), color);
+ }
+ }
+}
+
+void StyledTTFont::drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align) {
+ if (_font) {
+ _font->drawString(dst, str, x, y, w, color, align);
+ if (_style & STTF_UNDERLINE) {
+ int16 pos = floor(_font->getFontHeight() * 0.87);
+ int16 wd = MIN(_font->getStringWidth(str), w);
+ int16 stX = x;
+ if (align == Graphics::kTextAlignCenter)
+ stX += (w - wd) / 2;
+ else if (align == Graphics::kTextAlignRight)
+ stX += (w - wd);
+
+ int thk = MAX((int)(_font->getFontHeight() * 0.05), 1);
+
+ dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color);
+ }
+ if (_style & STTF_STRIKEOUT) {
+ int16 pos = floor(_font->getFontHeight() * 0.60);
+ int16 wd = MIN(_font->getStringWidth(str), w);
+ int16 stX = x;
+ if (align == Graphics::kTextAlignCenter)
+ stX += (w - wd) / 2;
+ else if (align == Graphics::kTextAlignRight)
+ stX += (w - wd);
+
+ int thk = MAX((int)(_font->getFontHeight() * 0.05), 1);
+
+ dst->fillRect(Common::Rect(stX, y + pos, stX + wd, y + pos + thk), color);
+ }
+ }
+}
+
+int StyledTTFont::getStringWidth(const Common::String &str) {
+ if (_font)
+ return _font->getStringWidth(str);
+ return 0;
+}
+
+Graphics::Surface *StyledTTFont::renderSolidText(const Common::String &str, uint32 color) {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ if (_font) {
+ int16 w = _font->getStringWidth(str);
+ if (w && w < 1024) {
+ tmp->create(w, _font->getFontHeight(), _engine->_pixelFormat);
+ drawString(tmp, str, 0, 0, w, color);
+ }
+ }
+ return tmp;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/fonts/truetype_font.h b/engines/zvision/graphics/truetype_font.h
index 64f53a2c3b..30ef1c73a3 100644
--- a/engines/zvision/fonts/truetype_font.h
+++ b/engines/zvision/graphics/truetype_font.h
@@ -28,7 +28,6 @@
#include "graphics/font.h"
#include "graphics/pixelformat.h"
-
namespace Graphics {
struct Surface;
}
@@ -43,12 +42,12 @@ public:
~TruetypeFont();
private:
-// ZVision *_engine;
+ ZVision *_engine;
Graphics::Font *_font;
int _lineHeight;
-// size_t _maxCharWidth;
-// size_t _maxCharHeight;
+ size_t _maxCharWidth;
+ size_t _maxCharHeight;
public:
int32 _fontHeight;
@@ -76,6 +75,49 @@ public:
Graphics::Surface *drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap);
};
+// Styled TTF
+class StyledTTFont {
+public:
+ StyledTTFont(ZVision *engine);
+ ~StyledTTFont();
+
+ enum {
+ STTF_BOLD = 1,
+ STTF_ITALIC = 2,
+ STTF_UNDERLINE = 4,
+ STTF_STRIKEOUT = 8,
+ STTF_SHARP = 16
+ };
+
+private:
+ ZVision *_engine;
+ Graphics::Font *_font;
+ int _lineHeight;
+ uint _style;
+ Common::String _fntName;
+
+public:
+ bool loadFont(const Common::String &fontName, int32 point);
+ bool loadFont(const Common::String &fontName, int32 point, uint style);
+ void setStyle(uint newStyle);
+
+ int getFontHeight();
+ int getMaxCharWidth();
+ int getCharWidth(byte chr);
+ int getKerningOffset(byte left, byte right);
+
+ void drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color);
+
+ void drawString(Graphics::Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+ int getStringWidth(const Common::String &str);
+
+ Graphics::Surface *renderSolidText(const Common::String &str, uint32 color);
+
+ bool isLoaded() {
+ return _font != NULL;
+ };
+};
+
} // End of namespace ZVision
#endif
diff --git a/engines/zvision/module.mk b/engines/zvision/module.mk
index 2e298f24c6..045eb5264a 100644
--- a/engines/zvision/module.mk
+++ b/engines/zvision/module.mk
@@ -1,32 +1,53 @@
MODULE := engines/zvision
MODULE_OBJS := \
+ animation/meta_animation.o \
animation/rlf_animation.o \
- archives/zfs_archive.o \
core/console.o \
core/events.o \
+ core/menu.o \
+ core/midi.o \
core/save_manager.o \
- cursors/cursor.o \
+ core/search_manager.o \
cursors/cursor_manager.o \
+ cursors/cursor.o \
detection.o \
- fonts/truetype_font.o \
+ graphics/effects/fog.o \
+ graphics/effects/light.o \
+ graphics/effects/wave.o \
graphics/render_manager.o \
graphics/render_table.o \
+ graphics/subtitles.o \
+ graphics/truetype_font.o \
scripting/actions.o \
scripting/control.o \
- scripting/controls/animation_control.o \
+ scripting/controls/fist_control.o \
+ scripting/controls/hotmov_control.o \
scripting/controls/input_control.o \
scripting/controls/lever_control.o \
+ scripting/controls/paint_control.o \
scripting/controls/push_toggle_control.o \
- scripting/controls/timer_node.o \
+ scripting/controls/safe_control.o \
+ scripting/controls/save_control.o \
+ scripting/controls/slot_control.o \
+ scripting/controls/titler_control.o \
+ scripting/inventory.o \
scripting/scr_file_handling.o \
scripting/script_manager.o \
+ scripting/sidefx/animation_node.o \
+ scripting/sidefx/distort_node.o \
+ scripting/sidefx/music_node.o \
+ scripting/sidefx/region_node.o \
+ scripting/sidefx/syncsound_node.o \
+ scripting/sidefx/timer_node.o \
+ scripting/sidefx/ttytext_node.o \
sound/zork_raw.o \
- strings/string_manager.o \
+ text/string_manager.o \
+ text/text.o \
utility/clock.o \
utility/lzss_read_stream.o \
- utility/single_value_container.o \
utility/utility.o \
+ utility/zfs_archive.o \
video/video.o \
video/zork_avi_decoder.o \
zvision.o
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index 517278e155..c8c82063f7 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -29,372 +29,972 @@
#include "zvision/graphics/render_manager.h"
#include "zvision/sound/zork_raw.h"
#include "zvision/video/zork_avi_decoder.h"
-#include "zvision/scripting/controls/timer_node.h"
-#include "zvision/scripting/controls/animation_control.h"
+#include "zvision/scripting/sidefx/timer_node.h"
+#include "zvision/scripting/sidefx/music_node.h"
+#include "zvision/scripting/sidefx/syncsound_node.h"
+#include "zvision/scripting/sidefx/animation_node.h"
+#include "zvision/scripting/sidefx/distort_node.h"
+#include "zvision/scripting/sidefx/ttytext_node.h"
+#include "zvision/scripting/sidefx/region_node.h"
+#include "zvision/scripting/controls/titler_control.h"
+#include "zvision/graphics/render_table.h"
+#include "zvision/graphics/effect.h"
+#include "zvision/graphics/effects/fog.h"
+#include "zvision/graphics/effects/light.h"
+#include "zvision/graphics/effects/wave.h"
+#include "zvision/core/save_manager.h"
+#include "zvision/cursors/cursor_manager.h"
#include "common/file.h"
#include "audio/decoders/wave.h"
-
namespace ZVision {
//////////////////////////////////////////////////////////////////////////////
// ActionAdd
//////////////////////////////////////////////////////////////////////////////
-ActionAdd::ActionAdd(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%u,%u)", &_key, &_value);
+ActionAdd::ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%u,%d", &_key, &_value);
}
-bool ActionAdd::execute(ZVision *engine) {
- engine->getScriptManager()->addToStateValue(_key, _value);
+bool ActionAdd::execute() {
+ _engine->getScriptManager()->setStateValue(_key, _engine->getScriptManager()->getStateValue(_key) + _value);
return true;
}
-
//////////////////////////////////////////////////////////////////////////////
// ActionAssign
//////////////////////////////////////////////////////////////////////////////
-ActionAssign::ActionAssign(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%u, %u)", &_key, &_value);
+ActionAssign::ActionAssign(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char buf[64];
+ memset(buf, 0, 64);
+ sscanf(line.c_str(), "%u, %s", &_key, buf);
+ _value = new ValueSlot(_engine->getScriptManager(), buf);
}
-bool ActionAssign::execute(ZVision *engine) {
- engine->getScriptManager()->setStateValue(_key, _value);
- return true;
+ActionAssign::~ActionAssign() {
+ if (_value)
+ delete _value;
}
+bool ActionAssign::execute() {
+ _engine->getScriptManager()->setStateValue(_key, _value->getValue());
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionAttenuate
//////////////////////////////////////////////////////////////////////////////
-ActionAttenuate::ActionAttenuate(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%u, %d)", &_key, &_attenuation);
+ActionAttenuate::ActionAttenuate(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%u, %d", &_key, &_attenuation);
}
-bool ActionAttenuate::execute(ZVision *engine) {
- // TODO: Implement
+bool ActionAttenuate::execute() {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_key);
+ if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) {
+ MusicNode *mus = (MusicNode *)fx;
+ mus->setVolume(255 - (abs(_attenuation) >> 7));
+ }
return true;
}
-
//////////////////////////////////////////////////////////////////////////////
// ActionChangeLocation
//////////////////////////////////////////////////////////////////////////////
-ActionChangeLocation::ActionChangeLocation(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%c,%c,%c%c,%u)", &_world, &_room, &_node, &_view, &_offset);
+ActionChangeLocation::ActionChangeLocation(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%c, %c, %c%c, %u", &_world, &_room, &_node, &_view, &_offset);
}
-bool ActionChangeLocation::execute(ZVision *engine) {
+bool ActionChangeLocation::execute() {
// We can't directly call ScriptManager::ChangeLocationIntern() because doing so clears all the Puzzles, and thus would corrupt the current puzzle checking
- engine->getScriptManager()->changeLocation(_world, _room, _node, _view, _offset);
+ _engine->getScriptManager()->changeLocation(_world, _room, _node, _view, _offset);
// Tell the puzzle system to stop checking any more puzzles
return false;
}
-
//////////////////////////////////////////////////////////////////////////////
// ActionCrossfade
//////////////////////////////////////////////////////////////////////////////
-ActionCrossfade::ActionCrossfade(const Common::String &line) {
+ActionCrossfade::ActionCrossfade(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
sscanf(line.c_str(),
- "%*[^(](%u %u %u %u %u %u %u)",
- &_keyOne, &_keyTwo, &_oneStartVolume, &_twoStartVolume, &_oneEndVolume, &_twoEndVolume, &_timeInMillis);
+ "%u %u %d %d %d %d %d",
+ &_keyOne, &_keyTwo, &_oneStartVolume, &_twoStartVolume, &_oneEndVolume, &_twoEndVolume, &_timeInMillis);
}
-bool ActionCrossfade::execute(ZVision *engine) {
- // TODO: Implement
+bool ActionCrossfade::execute() {
+ if (_keyOne) {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_keyOne);
+ if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) {
+ MusicNode *mus = (MusicNode *)fx;
+ if (_oneStartVolume >= 0)
+ mus->setVolume((_oneStartVolume * 255) / 100);
+
+ mus->setFade(_timeInMillis, (_oneEndVolume * 255) / 100);
+ }
+ }
+
+ if (_keyTwo) {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_keyTwo);
+ if (fx && fx->getType() == SideFX::SIDEFX_AUDIO) {
+ MusicNode *mus = (MusicNode *)fx;
+ if (_twoStartVolume >= 0)
+ mus->setVolume((_twoStartVolume * 255) / 100);
+
+ mus->setFade(_timeInMillis, (_twoEndVolume * 255) / 100);
+ }
+ }
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionCursor
+//////////////////////////////////////////////////////////////////////////////
+
+ActionCursor::ActionCursor(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ Common::String up = line;
+ up.toUppercase();
+ _action = 0;
+
+ if (up[0] == 'B')
+ _action = 2;
+ else if (up[0] == 'I')
+ _action = 3;
+ else if (up[0] == 'U')
+ _action = 0;
+ else if (up[0] == 'H')
+ _action = 1;
+}
+
+bool ActionCursor::execute() {
+ switch (_action) {
+ case 1:
+ _engine->getCursorManager()->showMouse(false);
+ break;
+ default:
+ _engine->getCursorManager()->showMouse(true);
+ break;
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionDelayRender
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDelayRender::ActionDelayRender(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%u", &_framesToDelay);
+}
+
+bool ActionDelayRender::execute() {
+ _engine->setRenderDelay(_framesToDelay);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionDisableControl
//////////////////////////////////////////////////////////////////////////////
-ActionDisableControl::ActionDisableControl(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%u)", &_key);
+ActionDisableControl::ActionDisableControl(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%u", &_key);
+}
+
+bool ActionDisableControl::execute() {
+ _engine->getScriptManager()->setStateFlag(_key, Puzzle::DISABLED);
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionDisableVenus
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDisableVenus::ActionDisableVenus(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%d", &_key);
+}
+
+bool ActionDisableVenus::execute() {
+ _engine->getScriptManager()->setStateValue(_key, 0);
+
+ return true;
}
-bool ActionDisableControl::execute(ZVision *engine) {
- debug("Disabling control %u", _key);
-
- ScriptManager *scriptManager = engine->getScriptManager();
- scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) | ScriptManager::DISABLED);
+//////////////////////////////////////////////////////////////////////////////
+// ActionDisplayMessage
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDisplayMessage::ActionDisplayMessage(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%hd %hd", &_control, &_msgid);
+}
+bool ActionDisplayMessage::execute() {
+ Control *ctrl = _engine->getScriptManager()->getControl(_control);
+ if (ctrl && ctrl->getType() == Control::CONTROL_TITLER) {
+ TitlerControl *titler = (TitlerControl *)ctrl;
+ titler->setString(_msgid);
+ }
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionDissolve
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDissolve::ActionDissolve(ZVision *engine) :
+ ResultAction(engine, 0) {
+}
+
+bool ActionDissolve::execute() {
+ // Cause black screen flick
+ // _engine->getRenderManager()->bkgFill(0, 0, 0);
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionDistort
+//////////////////////////////////////////////////////////////////////////////
+
+ActionDistort::ActionDistort(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%hd %hd %f %f %f %f", &_distSlot, &_speed, &_startAngle, &_endAngle, &_startLineScale, &_endLineScale);
+}
+
+ActionDistort::~ActionDistort() {
+ _engine->getScriptManager()->killSideFx(_distSlot);
+}
+
+bool ActionDistort::execute() {
+ if (_engine->getScriptManager()->getSideFX(_distSlot))
+ return true;
+
+ _engine->getScriptManager()->addSideFX(new DistortNode(_engine, _distSlot, _speed, _startAngle, _endAngle, _startLineScale, _endLineScale));
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionEnableControl
//////////////////////////////////////////////////////////////////////////////
-ActionEnableControl::ActionEnableControl(const Common::String &line) {
- sscanf(line.c_str(), "%*[^(](%u)", &_key);
+ActionEnableControl::ActionEnableControl(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%u", &_key);
+}
+
+bool ActionEnableControl::execute() {
+ _engine->getScriptManager()->unsetStateFlag(_key, Puzzle::DISABLED);
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionFlushMouseEvents
+//////////////////////////////////////////////////////////////////////////////
+
+ActionFlushMouseEvents::ActionFlushMouseEvents(ZVision *engine, int32 slotkey) :
+ ResultAction(engine, slotkey) {
}
-bool ActionEnableControl::execute(ZVision *engine) {
- debug("Enabling control %u", _key);
+bool ActionFlushMouseEvents::execute() {
+ _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONUP);
+ _engine->getScriptManager()->flushEvent(Common::EVENT_LBUTTONDOWN);
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionInventory
+//////////////////////////////////////////////////////////////////////////////
+
+ActionInventory::ActionInventory(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char buf[25];
+ sscanf(line.c_str(), "%25s %d", buf, &_key);
+
+ if (strcmp(buf, "add") == 0) {
+ _type = 0;
+ } else if (strcmp(buf, "addi") == 0) {
+ _type = 1;
+ } else if (strcmp(buf, "drop") == 0) {
+ _type = 2;
+ } else if (strcmp(buf, "dropi") == 0) {
+ _type = 3;
+ } else if (strcmp(buf, "cycle") == 0) {
+ _type = 4;
+ }
- ScriptManager *scriptManager = engine->getScriptManager();
- scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) & ~ScriptManager::DISABLED);
+}
+
+bool ActionInventory::execute() {
+ switch (_type) {
+ case 0: // add
+ _engine->getScriptManager()->inventoryAdd(_key);
+ break;
+ case 1: // addi
+ _engine->getScriptManager()->inventoryAdd(_engine->getScriptManager()->getStateValue(_key));
+ break;
+ case 2: // drop
+ if (_key >= 0)
+ _engine->getScriptManager()->inventoryDrop(_key);
+ else
+ _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(StateKey_InventoryItem));
+ break;
+ case 3: // dropi
+ _engine->getScriptManager()->inventoryDrop(_engine->getScriptManager()->getStateValue(_key));
+ break;
+ case 4: // cycle
+ _engine->getScriptManager()->inventoryCycle();
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+//////////////////////////////////////////////////////////////////////////////
+// ActionKill
+//////////////////////////////////////////////////////////////////////////////
+
+ActionKill::ActionKill(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ _key = 0;
+ _type = 0;
+ char keytype[25];
+ sscanf(line.c_str(), "%25s", keytype);
+ if (keytype[0] == '"') {
+ if (!scumm_stricmp(keytype, "\"ANIM\""))
+ _type = SideFX::SIDEFX_ANIM;
+ else if (!scumm_stricmp(keytype, "\"AUDIO\""))
+ _type = SideFX::SIDEFX_AUDIO;
+ else if (!scumm_stricmp(keytype, "\"DISTORT\""))
+ _type = SideFX::SIDEFX_DISTORT;
+ else if (!scumm_stricmp(keytype, "\"PANTRACK\""))
+ _type = SideFX::SIDEFX_PANTRACK;
+ else if (!scumm_stricmp(keytype, "\"REGION\""))
+ _type = SideFX::SIDEFX_REGION;
+ else if (!scumm_stricmp(keytype, "\"TIMER\""))
+ _type = SideFX::SIDEFX_TIMER;
+ else if (!scumm_stricmp(keytype, "\"TTYTEXT\""))
+ _type = SideFX::SIDEFX_TTYTXT;
+ else if (!scumm_stricmp(keytype, "\"ALL\""))
+ _type = SideFX::SIDEFX_ALL;
+ } else
+ _key = atoi(keytype);
+}
+
+bool ActionKill::execute() {
+ if (_type)
+ _engine->getScriptManager()->killSideFxType((SideFX::SideFXType)_type);
+ else
+ _engine->getScriptManager()->killSideFx(_key);
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionMenuBarEnable
+//////////////////////////////////////////////////////////////////////////////
+
+ActionMenuBarEnable::ActionMenuBarEnable(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%hu", &_menus);
+}
+
+bool ActionMenuBarEnable::execute() {
+ _engine->menuBarEnable(_menus);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionMusic
//////////////////////////////////////////////////////////////////////////////
-ActionMusic::ActionMusic(const Common::String &line) : _volume(255) {
+ActionMusic::ActionMusic(ZVision *engine, int32 slotkey, const Common::String &line, bool global) :
+ ResultAction(engine, slotkey),
+ _volume(255),
+ _universe(global) {
uint type;
- char fileNameBuffer[26];
+ char fileNameBuffer[25];
uint loop;
uint volume = 255;
- sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%u %25s %u %u)", &_key, &type, fileNameBuffer, &loop, &volume);
+ sscanf(line.c_str(), "%u %25s %u %u", &type, fileNameBuffer, &loop, &volume);
// type 4 are midi sound effect files
if (type == 4) {
- _soundType = Audio::Mixer::kSFXSoundType;
- _fileName = Common::String::format("midi/%s/%u.wav", fileNameBuffer, loop);
- _loop = false;
+ _midi = true;
+ int note;
+ int prog;
+ sscanf(line.c_str(), "%u %d %d %u", &type, &prog, &note, &volume);
+ _volume = volume;
+ _note = note;
+ _prog = prog;
} else {
- // TODO: See what the other types are so we can specify the correct Mixer::SoundType. In the meantime use kPlainSoundType
- _soundType = Audio::Mixer::kPlainSoundType;
+ _midi = false;
_fileName = Common::String(fileNameBuffer);
_loop = loop == 1 ? true : false;
- }
- // Volume is optional. If it doesn't appear, assume full volume
- if (volume != 255) {
- // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255]
- _volume = volume * 255 / 100;
+ // Volume is optional. If it doesn't appear, assume full volume
+ if (volume != 255) {
+ // Volume in the script files is mapped to [0, 100], but the ScummVM mixer uses [0, 255]
+ _volume = volume * 255 / 100;
+ }
}
}
-bool ActionMusic::execute(ZVision *engine) {
- Audio::RewindableAudioStream *audioStream;
+ActionMusic::~ActionMusic() {
+ if (!_universe)
+ _engine->getScriptManager()->killSideFx(_slotKey);
+}
+
+bool ActionMusic::execute() {
+ if (_engine->getScriptManager()->getSideFX(_slotKey))
+ return true;
- if (_fileName.contains(".wav")) {
- Common::File *file = new Common::File();
- if (file->open(_fileName)) {
- audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
- } else {
- warning("Unable to open %s", _fileName.c_str());
- return false;
- }
- } else {
- audioStream = makeRawZorkStream(_fileName, engine);
- }
-
- if (_loop) {
- Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
- engine->_mixer->playStream(_soundType, 0, loopingAudioStream, -1, _volume);
+ if (_midi) {
+ _engine->getScriptManager()->addSideFX(new MusicMidiNode(_engine, _slotKey, _prog, _note, _volume));
} else {
- engine->_mixer->playStream(_soundType, 0, audioStream, -1, _volume);
+ if (!_engine->getSearchManager()->hasFile(_fileName))
+ return true;
+
+ _engine->getScriptManager()->addSideFX(new MusicNode(_engine, _slotKey, _fileName, _loop, _volume));
}
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionPanTrack
+//////////////////////////////////////////////////////////////////////////////
+
+ActionPanTrack::ActionPanTrack(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey),
+ _pos(0),
+ _musicSlot(0) {
+
+ sscanf(line.c_str(), "%u %d", &_musicSlot, &_pos);
+}
+
+ActionPanTrack::~ActionPanTrack() {
+ _engine->getScriptManager()->killSideFx(_slotKey);
+}
+
+bool ActionPanTrack::execute() {
+ if (_engine->getScriptManager()->getSideFX(_slotKey))
+ return true;
+
+ _engine->getScriptManager()->addSideFX(new PanTrackNode(_engine, _slotKey, _musicSlot, _pos));
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionPreferences
+//////////////////////////////////////////////////////////////////////////////
+
+ActionPreferences::ActionPreferences(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ if (line.compareToIgnoreCase("save") == 0)
+ _save = true;
+ else
+ _save = false;
+}
+
+bool ActionPreferences::execute() {
+ if (_save)
+ _engine->saveSettings();
+ else
+ _engine->loadSettings();
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionPreloadAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPreloadAnimation::ActionPreloadAnimation(const Common::String &line) {
- char fileName[26];
+ActionPreloadAnimation::ActionPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
// The two %*u are always 0 and dont seem to have a use
- sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%25s %*u %*u %u %u)", &_key, fileName, &_mask, &_framerate);
+ sscanf(line.c_str(), "%25s %*u %*u %d %d", fileName, &_mask, &_framerate);
+
+ if (_mask > 0) {
+ byte r, g, b;
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b);
+ _mask = _engine->_pixelFormat.RGBToColor(r, g, b);
+ }
_fileName = Common::String(fileName);
}
-bool ActionPreloadAnimation::execute(ZVision *engine) {
- // TODO: We ignore the mask and framerate atm. Mask refers to a key color used for binary alpha. We assume the framerate is the default framerate embedded in the videos
-
- // TODO: Check if the Control already exists
+ActionPreloadAnimation::~ActionPreloadAnimation() {
+ _engine->getScriptManager()->deleteSideFx(_slotKey);
+}
- // Create the control, but disable it until PlayPreload is called
- ScriptManager *scriptManager = engine->getScriptManager();
- scriptManager->addControl(new AnimationControl(engine, _key, _fileName));
- scriptManager->setStateFlags(_key, scriptManager->getStateFlags(_key) | ScriptManager::DISABLED);
+bool ActionPreloadAnimation::execute() {
+ AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey);
+ if (!nod) {
+ nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate, false);
+ _engine->getScriptManager()->addSideFX(nod);
+ } else
+ nod->stop();
+ _engine->getScriptManager()->setStateValue(_slotKey, 2);
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionUnloadAnimation
+//////////////////////////////////////////////////////////////////////////////
+
+ActionUnloadAnimation::ActionUnloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+
+ sscanf(line.c_str(), "%u", &_key);
+}
+
+bool ActionUnloadAnimation::execute() {
+ AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_key);
+
+ if (nod && nod->getType() == SideFX::SIDEFX_ANIM)
+ _engine->getScriptManager()->deleteSideFx(_key);
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionPlayAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPlayAnimation::ActionPlayAnimation(const Common::String &line) {
- char fileName[26];
+ActionPlayAnimation::ActionPlayAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
// The two %*u are always 0 and dont seem to have a use
sscanf(line.c_str(),
- "%*[^:]:%*[^:]:%u(%25s %u %u %u %u %u %u %u %*u %*u %u %u)",
- &_key, fileName, &_x, &_y, &_width, &_height, &_start, &_end, &_loopCount, &_mask, &_framerate);
+ "%25s %u %u %u %u %u %u %d %*u %*u %d %d",
+ fileName, &_x, &_y, &_x2, &_y2, &_start, &_end, &_loopCount, &_mask, &_framerate);
+
+ if (_mask > 0) {
+ byte r, g, b;
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(_mask, r, g, b);
+ _mask = _engine->_pixelFormat.RGBToColor(r, g, b);
+ }
_fileName = Common::String(fileName);
}
-bool ActionPlayAnimation::execute(ZVision *engine) {
- // TODO: Implement
- return true;
+ActionPlayAnimation::~ActionPlayAnimation() {
+ _engine->getScriptManager()->deleteSideFx(_slotKey);
}
+bool ActionPlayAnimation::execute() {
+ AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_slotKey);
+
+ if (!nod) {
+ nod = new AnimationNode(_engine, _slotKey, _fileName, _mask, _framerate);
+ _engine->getScriptManager()->addSideFX(nod);
+ } else
+ nod->stop();
+
+ if (nod)
+ nod->addPlayNode(_slotKey, _x, _y, _x2, _y2, _start, _end, _loopCount);
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionPlayPreloadAnimation
//////////////////////////////////////////////////////////////////////////////
-ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(const Common::String &line) {
+ActionPlayPreloadAnimation::ActionPlayPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
sscanf(line.c_str(),
- "%*[^:]:%*[^:]:%u(%u %u %u %u %u %u %u %u)",
- &_animationKey, &_controlKey, &_x1, &_y1, &_x2, &_y2, &_startFrame, &_endFrame, &_loopCount);
+ "%u %u %u %u %u %u %u %u",
+ &_controlKey, &_x1, &_y1, &_x2, &_y2, &_startFrame, &_endFrame, &_loopCount);
}
-bool ActionPlayPreloadAnimation::execute(ZVision *engine) {
- // Find the control
- AnimationControl *control = (AnimationControl *)engine->getScriptManager()->getControl(_controlKey);
-
- // Set the needed values within the control
- control->setAnimationKey(_animationKey);
- control->setLoopCount(_loopCount);
- control->setXPos(_x1);
- control->setYPost(_y1);
+bool ActionPlayPreloadAnimation::execute() {
+ AnimationNode *nod = (AnimationNode *)_engine->getScriptManager()->getSideFX(_controlKey);
- // Enable the control. ScriptManager will take care of the rest
- control->enable();
+ if (nod)
+ nod->addPlayNode(_slotKey, _x1, _y1, _x2, _y2, _startFrame, _endFrame, _loopCount);
return true;
}
-
//////////////////////////////////////////////////////////////////////////////
// ActionQuit
//////////////////////////////////////////////////////////////////////////////
-bool ActionQuit::execute(ZVision *engine) {
- engine->quitGame();
+bool ActionQuit::execute() {
+ _engine->quitGame();
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionRegion
+//////////////////////////////////////////////////////////////////////////////
+
+ActionRegion::ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+
+ char art[64];
+ char custom[64];
+
+ int32 x1, x2, y1, y2;
+
+ sscanf(line.c_str(), "%s %d %d %d %d %hu %hu %hu %hu %s", art, &x1, &y1, &x2, &y2, &_delay, &_type, &_unk1, &_unk2, custom);
+ _art = Common::String(art);
+ _custom = Common::String(custom);
+ _rect = Common::Rect(x1, y1, x2 + 1, y2 + 1);
+}
+
+ActionRegion::~ActionRegion() {
+ _engine->getScriptManager()->killSideFx(_slotKey);
+}
+
+bool ActionRegion::execute() {
+ if (_engine->getScriptManager()->getSideFX(_slotKey))
+ return true;
+
+ Effect *effct = NULL;
+ switch (_type) {
+ case 0: {
+ uint16 centerX, centerY, frames;
+ double amplitude, waveln, speed;
+ sscanf(_custom.c_str(), "%hu,%hu,%hu,%lf,%lf,%lf,", &centerX, &centerY, &frames, &amplitude, &waveln, &speed);
+ effct = new WaveFx(_engine, _slotKey, _rect, _unk1, frames, centerX, centerY, amplitude, waveln, speed);
+ }
+ break;
+ case 1: {
+ uint16 aX, aY, aD;
+ if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA)
+ sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aY, &aX, &aD);
+ else
+ sscanf(_art.c_str(), "useart[%hu,%hu,%hu]", &aX, &aY, &aD);
+ int8 minD;
+ int8 maxD;
+ EffectMap *_map = _engine->getRenderManager()->makeEffectMap(Common::Point(aX, aY), aD, _rect, &minD, &maxD);
+ effct = new LightFx(_engine, _slotKey, _rect, _unk1, _map, atoi(_custom.c_str()), minD, maxD);
+ }
+ break;
+ case 9: {
+ int16 dum1;
+ int32 dum2;
+ char buf[64];
+ sscanf(_custom.c_str(), "%hd,%d,%s", &dum1, &dum2, buf);
+ Graphics::Surface tempMask;
+ _engine->getRenderManager()->readImageToSurface(_art, tempMask);
+ if (_rect.width() != tempMask.w)
+ _rect.setWidth(tempMask.w);
+ if (_rect.height() != tempMask.h)
+ _rect.setHeight(tempMask.h);
+
+ EffectMap *_map = _engine->getRenderManager()->makeEffectMap(tempMask, 0);
+ effct = new FogFx(_engine, _slotKey, _rect, _unk1, _map, Common::String(buf));
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (effct) {
+ _engine->getScriptManager()->addSideFX(new RegionNode(_engine, _slotKey, effct, _delay));
+ _engine->getRenderManager()->addEffect(effct);
+ }
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionRandom
//////////////////////////////////////////////////////////////////////////////
-ActionRandom::ActionRandom(const Common::String &line) {
- sscanf(line.c_str(), "%*[^:]:%*[^:]:%u, %u)", &_key, &_max);
+ActionRandom::ActionRandom(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char maxBuffer[64];
+ memset(maxBuffer, 0, 64);
+ sscanf(line.c_str(), "%s", maxBuffer);
+ _max = new ValueSlot(_engine->getScriptManager(), maxBuffer);
}
-bool ActionRandom::execute(ZVision *engine) {
- uint randNumber = engine->getRandomSource()->getRandomNumber(_max);
- engine->getScriptManager()->setStateValue(_key, randNumber);
+ActionRandom::~ActionRandom() {
+ if (_max)
+ delete _max;
+}
+
+bool ActionRandom::execute() {
+ uint randNumber = _engine->getRandomSource()->getRandomNumber(_max->getValue());
+ _engine->getScriptManager()->setStateValue(_slotKey, randNumber);
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionRestoreGame
+//////////////////////////////////////////////////////////////////////////////
+
+ActionRestoreGame::ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char buf[128];
+ sscanf(line.c_str(), "%s", buf);
+ _fileName = Common::String(buf);
+}
+
+bool ActionRestoreGame::execute() {
+ _engine->getSaveManager()->loadGame(_fileName);
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionRotateTo
+//////////////////////////////////////////////////////////////////////////////
+
+ActionRotateTo::ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%d, %d", &_toPos, &_time);
+}
+
+bool ActionRotateTo::execute() {
+ _engine->rotateTo(_toPos, _time);
+
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionSetPartialScreen
//////////////////////////////////////////////////////////////////////////////
-ActionSetPartialScreen::ActionSetPartialScreen(const Common::String &line) {
- char fileName[26];
- uint color;
+ActionSetPartialScreen::ActionSetPartialScreen(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
+ int color;
- sscanf(line.c_str(), "%*[^(](%u %u %25s %*u %u)", &_x, &_y, fileName, &color);
+ sscanf(line.c_str(), "%u %u %25s %*u %d", &_x, &_y, fileName, &color);
_fileName = Common::String(fileName);
- if (color > 0xFFFF) {
+ if (color >= 0) {
+ byte r, g, b;
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b);
+ _backgroundColor = _engine->_pixelFormat.RGBToColor(r, g, b);
+ } else {
+ _backgroundColor = color;
+ }
+
+ if (color > 65535) {
warning("Background color for ActionSetPartialScreen is bigger than a uint16");
}
- _backgroundColor = color;
}
-bool ActionSetPartialScreen::execute(ZVision *engine) {
- RenderManager *renderManager = engine->getRenderManager();
-
- if (_backgroundColor > 0) {
- renderManager->clearWorkingWindowTo555Color(_backgroundColor);
+bool ActionSetPartialScreen::execute() {
+ RenderManager *renderManager = _engine->getRenderManager();
+
+ if (_engine->getGameId() == GID_NEMESIS) {
+ if (_backgroundColor)
+ renderManager->renderImageToBackground(_fileName, _x, _y, 0, 0);
+ else
+ renderManager->renderImageToBackground(_fileName, _x, _y);
+ } else {
+ if (_backgroundColor >= 0)
+ renderManager->renderImageToBackground(_fileName, _x, _y, _backgroundColor);
+ else if (_backgroundColor == -2)
+ renderManager->renderImageToBackground(_fileName, _x, _y, 0, 0);
+ else
+ renderManager->renderImageToBackground(_fileName, _x, _y);
}
- renderManager->renderImageToScreen(_fileName, _x, _y);
return true;
}
-
//////////////////////////////////////////////////////////////////////////////
// ActionSetScreen
//////////////////////////////////////////////////////////////////////////////
-ActionSetScreen::ActionSetScreen(const Common::String &line) {
- char fileName[26];
- sscanf(line.c_str(), "%*[^(](%25[^)])", fileName);
+ActionSetScreen::ActionSetScreen(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
+ sscanf(line.c_str(), "%25s", fileName);
_fileName = Common::String(fileName);
}
-bool ActionSetScreen::execute(ZVision *engine) {
- engine->getRenderManager()->setBackgroundImage(_fileName);
+bool ActionSetScreen::execute() {
+ _engine->getRenderManager()->setBackgroundImage(_fileName);
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionSetVenus
+//////////////////////////////////////////////////////////////////////////////
+
+ActionSetVenus::ActionSetVenus(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ sscanf(line.c_str(), "%d", &_key);
+}
+
+bool ActionSetVenus::execute() {
+ if (_engine->getScriptManager()->getStateValue(_key))
+ _engine->getScriptManager()->setStateValue(StateKey_Venus, _key);
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionStop
+//////////////////////////////////////////////////////////////////////////////
+
+ActionStop::ActionStop(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ _key = 0;
+ sscanf(line.c_str(), "%u", &_key);
+}
+
+bool ActionStop::execute() {
+ _engine->getScriptManager()->stopSideFx(_key);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionStreamVideo
//////////////////////////////////////////////////////////////////////////////
-ActionStreamVideo::ActionStreamVideo(const Common::String &line) {
- char fileName[26];
- uint skippable;
+ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
+ uint skipline; //skipline - render video with skip every second line, not skippable.
- sscanf(line.c_str(), "%*[^(](%25s %u %u %u %u %u %u)", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skippable);
+ sscanf(line.c_str(), "%25s %u %u %u %u %u %u", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skipline);
_fileName = Common::String(fileName);
- _skippable = (skippable == 0) ? false : true;
+ _skippable = true;
}
-bool ActionStreamVideo::execute(ZVision *engine) {
+bool ActionStreamVideo::execute() {
ZorkAVIDecoder decoder;
- if (!decoder.loadFile(_fileName)) {
- return true;
- }
+ Common::File *_file = _engine->getSearchManager()->openFile(_fileName);
+
+ if (_file) {
+ if (!decoder.loadStream(_file)) {
+ return true;
+ }
+
+ _engine->getCursorManager()->showMouse(false);
+
+ Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1);
+
+ Common::String subname = _fileName;
+ subname.setChar('s', subname.size() - 3);
+ subname.setChar('u', subname.size() - 2);
+ subname.setChar('b', subname.size() - 1);
+
+ Subtitle *sub = NULL;
- Common::Rect destRect;
- if ((_flags & DIFFERENT_DIMENSIONS) == DIFFERENT_DIMENSIONS) {
- destRect = Common::Rect(_x1, _y1, _x2, _y2);
+ if (_engine->getSearchManager()->hasFile(subname))
+ sub = new Subtitle(_engine, subname);
+
+ _engine->playVideo(decoder, destRect, _skippable, sub);
+
+ _engine->getCursorManager()->showMouse(true);
+
+ if (sub)
+ delete sub;
}
- engine->playVideo(decoder, destRect, _skippable);
return true;
}
+//////////////////////////////////////////////////////////////////////////////
+// ActionSyncSound
+//////////////////////////////////////////////////////////////////////////////
+
+ActionSyncSound::ActionSyncSound(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char fileName[25];
+ int notUsed;
+
+ sscanf(line.c_str(), "%d %d %25s", &_syncto, &notUsed, fileName);
+
+ _fileName = Common::String(fileName);
+}
+
+bool ActionSyncSound::execute() {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_syncto);
+ if (!fx)
+ return true;
+
+ if (!(fx->getType() & SideFX::SIDEFX_ANIM))
+ return true;
+
+ AnimationNode *animnode = (AnimationNode *)fx;
+ if (animnode->getFrameDelay() > 200) // Hack for fix incorrect framedelay in some animpreload
+ animnode->setNewFrameDelay(66); // ~15fps
+
+ _engine->getScriptManager()->addSideFX(new SyncSoundNode(_engine, _slotKey, _fileName, _syncto));
+ return true;
+}
//////////////////////////////////////////////////////////////////////////////
// ActionTimer
//////////////////////////////////////////////////////////////////////////////
-ActionTimer::ActionTimer(const Common::String &line) {
- sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%u)", &_key, &_time);
+ActionTimer::ActionTimer(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char timeBuffer[64];
+ memset(timeBuffer, 0, 64);
+ sscanf(line.c_str(), "%s", timeBuffer);
+ _time = new ValueSlot(_engine->getScriptManager(), timeBuffer);
+}
+
+ActionTimer::~ActionTimer() {
+ if (_time)
+ delete _time;
+ _engine->getScriptManager()->killSideFx(_slotKey);
+}
+
+bool ActionTimer::execute() {
+ if (_engine->getScriptManager()->getSideFX(_slotKey))
+ return true;
+ _engine->getScriptManager()->addSideFX(new TimerNode(_engine, _slotKey, _time->getValue()));
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ActionTtyText
+//////////////////////////////////////////////////////////////////////////////
+
+ActionTtyText::ActionTtyText(ZVision *engine, int32 slotkey, const Common::String &line) :
+ ResultAction(engine, slotkey) {
+ char filename[64];
+ int32 x1, y1, x2, y2;
+ sscanf(line.c_str(), "%d %d %d %d %s %u", &x1, &y1, &x2, &y2, filename, &_delay);
+ _r = Common::Rect(x1, y1, x2, y2);
+ _filename = Common::String(filename);
+}
+
+ActionTtyText::~ActionTtyText() {
+ _engine->getScriptManager()->killSideFx(_slotKey);
}
-bool ActionTimer::execute(ZVision *engine) {
- engine->getScriptManager()->addControl(new TimerNode(engine, _key, _time));
+bool ActionTtyText::execute() {
+ if (_engine->getScriptManager()->getSideFX(_slotKey))
+ return true;
+ _engine->getScriptManager()->addSideFX(new ttyTextNode(_engine, _slotKey, _filename, _r, _delay));
return true;
}
diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h
index 01457d21cc..f9e4ee8167 100644
--- a/engines/zvision/scripting/actions.h
+++ b/engines/zvision/scripting/actions.h
@@ -24,14 +24,15 @@
#define ZVISION_ACTIONS_H
#include "common/str.h"
+#include "common/rect.h"
#include "audio/mixer.h"
-
namespace ZVision {
// Forward declaration of ZVision. This file is included before ZVision is declared
class ZVision;
+class ValueSlot;
/**
* The base class that represents any action that a Puzzle can take.
@@ -39,6 +40,7 @@ class ZVision;
*/
class ResultAction {
public:
+ ResultAction(ZVision *engine, int32 slotkey) : _engine(engine), _slotKey(slotkey) {}
virtual ~ResultAction() {}
/**
* This is called by the script system whenever a Puzzle's criteria are found to be true.
@@ -48,75 +50,47 @@ public:
* @param engine A pointer to the base engine so the ResultAction can access all the necessary methods
* @return Should the script system continue to test any remaining puzzles (true) or immediately break and go on to the next frame (false)
*/
- virtual bool execute(ZVision *engine) = 0;
-};
-
-
-// The different types of actions
-// DEBUG,
-// DISABLE_CONTROL,
-// DISABLE_VENUS,
-// DISPLAY_MESSAGE,
-// DISSOLVE,
-// DISTORT,
-// ENABLE_CONTROL,
-// FLUSH_MOUSE_EVENTS,
-// INVENTORY,
-// KILL,
-// MENU_BAR_ENABLE,
-// MUSIC,
-// PAN_TRACK,
-// PLAY_PRELOAD,
-// PREFERENCES,
-// QUIT,
-// RANDOM,
-// REGION,
-// RESTORE_GAME,
-// ROTATE_TO,
-// SAVE_GAME,
-// SET_PARTIAL_SCREEN,
-// SET_SCREEN,
-// SET_VENUS,
-// STOP,
-// STREAM_VIDEO,
-// SYNC_SOUND,
-// TTY_TEXT,
-// UNIVERSE_MUSIC,
+ virtual bool execute() = 0;
+protected:
+ ZVision *_engine;
+ int32 _slotKey;
+};
class ActionAdd : public ResultAction {
public:
- ActionAdd(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionAdd(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _key;
- uint _value;
+ int _value;
};
class ActionAssign : public ResultAction {
public:
- ActionAssign(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionAssign(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionAssign();
+ bool execute();
private:
uint32 _key;
- uint _value;
+ ValueSlot *_value;
};
class ActionAttenuate : public ResultAction {
public:
- ActionAttenuate(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionAttenuate(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _key;
- int _attenuation;
+ int32 _attenuation;
};
class ActionChangeLocation : public ResultAction {
public:
- ActionChangeLocation(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionChangeLocation(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
char _world;
@@ -128,41 +102,49 @@ private:
class ActionCrossfade : public ResultAction {
public:
- ActionCrossfade(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionCrossfade(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _keyOne;
uint32 _keyTwo;
- uint _oneStartVolume;
- uint _twoStartVolume;
- uint _oneEndVolume;
- uint _twoEndVolume;
- uint _timeInMillis;
+ int32 _oneStartVolume;
+ int32 _twoStartVolume;
+ int32 _oneEndVolume;
+ int32 _twoEndVolume;
+ int32 _timeInMillis;
+};
+
+class ActionCursor : public ResultAction {
+public:
+ ActionCursor(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ uint8 _action;
};
class ActionDebug : public ResultAction {
public:
- ActionDebug(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDebug(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
};
class ActionDelayRender : public ResultAction {
public:
- ActionDelayRender(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDelayRender(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
- // TODO: Check if this should actually be frames or if it should be milliseconds/seconds
- uint32 framesToDelay;
+ uint32 _framesToDelay;
};
class ActionDisableControl : public ResultAction {
public:
- ActionDisableControl(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDisableControl(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _key;
@@ -170,79 +152,138 @@ private:
class ActionDisableVenus : public ResultAction {
public:
- ActionDisableVenus(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDisableVenus(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
+ int32 _key;
};
class ActionDisplayMessage : public ResultAction {
public:
- ActionDisplayMessage(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDisplayMessage(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
+ int16 _control;
+ int16 _msgid;
};
class ActionDissolve : public ResultAction {
public:
- ActionDissolve();
- bool execute(ZVision *engine);
+ ActionDissolve(ZVision *engine);
+ bool execute();
};
class ActionDistort : public ResultAction {
public:
- ActionDistort(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionDistort(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionDistort();
+ bool execute();
private:
+ int16 _distSlot;
+ int16 _speed;
+ float _startAngle;
+ float _endAngle;
+ float _startLineScale;
+ float _endLineScale;
};
class ActionEnableControl : public ResultAction {
public:
- ActionEnableControl(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionEnableControl(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ uint32 _key;
+};
+
+class ActionFlushMouseEvents : public ResultAction {
+public:
+ ActionFlushMouseEvents(ZVision *engine, int32 slotkey);
+ bool execute();
+};
+
+class ActionInventory : public ResultAction {
+public:
+ ActionInventory(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+private:
+ uint8 _type;
+ int32 _key;
+};
+
+class ActionKill : public ResultAction {
+public:
+ ActionKill(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _key;
+ uint32 _type;
+};
+
+class ActionMenuBarEnable : public ResultAction {
+public:
+ ActionMenuBarEnable(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+private:
+ uint16 _menus;
};
class ActionMusic : public ResultAction {
public:
- ActionMusic(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionMusic(ZVision *engine, int32 slotkey, const Common::String &line, bool global);
+ ~ActionMusic();
+ bool execute();
private:
uint32 _key;
- Audio::Mixer::SoundType _soundType;
Common::String _fileName;
bool _loop;
byte _volume;
+ bool _universe;
+ bool _midi;
+ int8 _note;
+ int8 _prog;
+};
+
+class ActionPanTrack : public ResultAction {
+public:
+ ActionPanTrack(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionPanTrack();
+ bool execute();
+
+private:
+ int32 _pos;
+ uint32 _musicSlot;
};
class ActionPlayAnimation : public ResultAction {
public:
- ActionPlayAnimation(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionPlayAnimation(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionPlayAnimation();
+ bool execute();
private:
uint32 _key;
Common::String _fileName;
uint32 _x;
uint32 _y;
- uint32 _width;
- uint32 _height;
+ uint32 _x2;
+ uint32 _y2;
uint32 _start;
uint32 _end;
- uint _mask;
- uint _framerate;
- uint _loopCount;
+ int32 _mask;
+ int32 _framerate;
+ int32 _loopCount;
};
class ActionPlayPreloadAnimation : public ResultAction {
public:
- ActionPlayPreloadAnimation(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionPlayPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint32 _animationKey;
@@ -258,64 +299,130 @@ private:
class ActionPreloadAnimation : public ResultAction {
public:
- ActionPreloadAnimation(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionPreloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionPreloadAnimation();
+ bool execute();
private:
uint32 _key;
Common::String _fileName;
- uint _mask;
- uint _framerate;
+ int32 _mask;
+ int32 _framerate;
+};
+
+class ActionPreferences : public ResultAction {
+public:
+ ActionPreferences(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ bool _save;
};
class ActionQuit : public ResultAction {
public:
- ActionQuit() {}
- bool execute(ZVision *engine);
+ ActionQuit(ZVision *engine, int32 slotkey) : ResultAction(engine, slotkey) {}
+ bool execute();
+};
+
+class ActionRegion : public ResultAction {
+public:
+ ActionRegion(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionRegion();
+ bool execute();
+
+private:
+ Common::String _art;
+ Common::String _custom;
+ Common::Rect _rect;
+ uint16 _delay;
+ uint16 _type;
+ uint16 _unk1;
+ uint16 _unk2;
};
// TODO: See if this exists in ZGI. It doesn't in ZNem
class ActionUnloadAnimation : public ResultAction {
public:
- ActionUnloadAnimation(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionUnloadAnimation(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+private:
+ uint32 _key;
};
class ActionRandom : public ResultAction {
public:
- ActionRandom(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionRandom(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionRandom();
+ bool execute();
private:
uint32 _key;
- uint _max;
+ ValueSlot *_max;
+};
+
+class ActionRestoreGame : public ResultAction {
+public:
+ ActionRestoreGame(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ Common::String _fileName;
+};
+
+class ActionRotateTo : public ResultAction {
+public:
+ ActionRotateTo(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ int32 _toPos;
+ int32 _time;
};
class ActionSetPartialScreen : public ResultAction {
public:
- ActionSetPartialScreen(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionSetPartialScreen(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
uint _x;
uint _y;
Common::String _fileName;
- uint16 _backgroundColor;
+ int32 _backgroundColor;
};
class ActionSetScreen : public ResultAction {
public:
- ActionSetScreen(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionSetScreen(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
Common::String _fileName;
};
+class ActionSetVenus : public ResultAction {
+public:
+ ActionSetVenus(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ int32 _key;
+};
+
+class ActionStop : public ResultAction {
+public:
+ ActionStop(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
+
+private:
+ uint32 _key;
+};
+
class ActionStreamVideo : public ResultAction {
public:
- ActionStreamVideo(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionStreamVideo(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
enum {
@@ -331,16 +438,37 @@ private:
bool _skippable;
};
-class ActionTimer : public ResultAction {
+class ActionSyncSound : public ResultAction {
public:
- ActionTimer(const Common::String &line);
- bool execute(ZVision *engine);
+ ActionSyncSound(ZVision *engine, int32 slotkey, const Common::String &line);
+ bool execute();
private:
+ int _syncto;
+ Common::String _fileName;
+};
+
+class ActionTimer : public ResultAction {
+public:
+ ActionTimer(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionTimer();
+ bool execute();
+private:
uint32 _key;
- uint _time;
+ ValueSlot *_time;
};
+class ActionTtyText : public ResultAction {
+public:
+ ActionTtyText(ZVision *engine, int32 slotkey, const Common::String &line);
+ ~ActionTtyText();
+ bool execute();
+
+private:
+ Common::String _filename;
+ uint32 _delay;
+ Common::Rect _r;
+};
} // End of namespace ZVision
#endif
diff --git a/engines/zvision/scripting/control.cpp b/engines/zvision/scripting/control.cpp
index 2343c83c56..5469106928 100644
--- a/engines/zvision/scripting/control.cpp
+++ b/engines/zvision/scripting/control.cpp
@@ -23,6 +23,7 @@
#include "common/scummsys.h"
#include "zvision/scripting/control.h"
+#include "zvision/scripting/script_manager.h"
#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
@@ -30,27 +31,8 @@
#include "common/stream.h"
-
namespace ZVision {
-void Control::enable() {
- if (!_enabled) {
- _enabled = true;
- return;
- }
-
- debug("Control %u is already enabled", _key);
-}
-
-void Control::disable() {
- if (_enabled) {
- _enabled = false;
- return;
- }
-
- debug("Control %u is already disabled", _key);
-}
-
void Control::parseFlatControl(ZVision *engine) {
engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT);
}
@@ -79,7 +61,9 @@ void Control::parsePanoramaControl(ZVision *engine, Common::SeekableReadStream &
renderTable->setPanoramaReverse(true);
}
} else if (line.matchString("zeropoint*", true)) {
- // TODO: Implement
+ uint point;
+ sscanf(line.c_str(), "zeropoint(%u)", &point);
+ renderTable->setPanoramaZeroPoint(point);
}
line = stream.readLine();
@@ -121,4 +105,34 @@ void Control::parseTiltControl(ZVision *engine, Common::SeekableReadStream &stre
renderTable->generateRenderTable();
}
+void Control::getParams(const Common::String &inputStr, Common::String &parameter, Common::String &values) {
+ const char *chrs = inputStr.c_str();
+ uint lbr;
+
+ for (lbr = 0; lbr < inputStr.size(); lbr++)
+ if (chrs[lbr] == '(')
+ break;
+
+ if (lbr >= inputStr.size())
+ return;
+
+ uint rbr;
+
+ for (rbr = lbr + 1; rbr < inputStr.size(); rbr++)
+ if (chrs[rbr] == ')')
+ break;
+
+ if (rbr >= inputStr.size())
+ return;
+
+ parameter = Common::String(chrs, chrs + lbr);
+ values = Common::String(chrs + lbr + 1, chrs + rbr);
+}
+
+void Control::setVenus() {
+ if (_venusId >= 0)
+ if (_engine->getScriptManager()->getStateValue(_venusId) > 0)
+ _engine->getScriptManager()->setStateValue(StateKey_Venus, _venusId);
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/control.h b/engines/zvision/scripting/control.h
index ffeacb273d..803d0cf1ce 100644
--- a/engines/zvision/scripting/control.h
+++ b/engines/zvision/scripting/control.h
@@ -8,12 +8,12 @@
* 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.
@@ -24,7 +24,7 @@
#define ZVISION_CONTROL_H
#include "common/keyboard.h"
-
+#include "common/str.h"
namespace Common {
class SeekableReadStream;
@@ -38,14 +38,32 @@ class ZVision;
class Control {
public:
- Control() : _engine(0), _key(0), _enabled(false) {}
- Control(ZVision *engine, uint32 key) : _engine(engine), _key(key), _enabled(false) {}
+
+ enum ControlType {
+ CONTROL_UNKNOW,
+ CONTROL_INPUT,
+ CONTROL_PUSHTGL,
+ CONTROL_SLOT,
+ CONTROL_LEVER,
+ CONTROL_SAVE,
+ CONTROL_SAFE,
+ CONTROL_FIST,
+ CONTROL_TITLER,
+ CONTROL_HOTMOV,
+ CONTROL_PAINT
+ };
+
+ Control(ZVision *engine, uint32 key, ControlType type) : _engine(engine), _key(key), _type(type), _venusId(-1) {}
virtual ~Control() {}
- uint32 getKey() { return _key; }
+ uint32 getKey() {
+ return _key;
+ }
+
+ ControlType getType() {
+ return _type;
+ }
- virtual void enable();
- virtual void disable();
virtual void focus() {}
virtual void unfocus() {}
/**
@@ -54,14 +72,18 @@ public:
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
- virtual void onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {}
+ virtual bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ return false;
+ }
/**
* Called when LeftMouse is lifted. Default is NOP.
*
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
- virtual void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {}
+ virtual bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ return false;
+ }
/**
* Called on every MouseMove. Default is NOP.
*
@@ -69,78 +91,52 @@ public:
* @param backgroundImageSpacePos The position of the mouse in background image space
* @return Was the cursor changed?
*/
- virtual bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { return false; }
+ virtual bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ return false;
+ }
/**
* Called when a key is pressed. Default is NOP.
*
* @param keycode The key that was pressed
*/
- virtual void onKeyDown(Common::KeyState keyState) {}
+ virtual bool onKeyDown(Common::KeyState keyState) {
+ return false;
+ }
/**
* Called when a key is released. Default is NOP.
*
* @param keycode The key that was pressed
*/
- virtual void onKeyUp(Common::KeyState keyState) {}
+ virtual bool onKeyUp(Common::KeyState keyState) {
+ return false;
+ }
/**
* Processes the node given the deltaTime since last frame. Default is NOP.
*
* @param deltaTimeInMillis The number of milliseconds that have passed since last frame
* @return If true, the node can be deleted after process() finishes
*/
- virtual bool process(uint32 deltaTimeInMillis) { return false; }
- /**
- * Serialize a Control for save game use. This should only be used if a Control needs
- * to save values that would be different from initialization. AKA a TimerNode needs to
- * store the amount of time left on the timer. Any Controls overriding this *MUST* write
- * their key as the first data outputted. The default implementation is NOP.
- *
- * NOTE: If this method is overridden, you MUST also override deserialize()
- * and needsSerialization()
- *
- * @param stream Stream to write any needed data to
- */
- virtual void serialize(Common::WriteStream *stream) {}
- /**
- * De-serialize data from a save game stream. This should only be implemented if the
- * Control also implements serialize(). The calling method assumes the size of the
- * data read from the stream exactly equals that written in serialize(). The default
- * implementation is NOP.
- *
- * NOTE: If this method is overridden, you MUST also override serialize()
- * and needsSerialization()
- *
- * @param stream Save game file stream
- */
- virtual void deserialize(Common::SeekableReadStream *stream) {}
- /**
- * If a Control overrides serialize() and deserialize(), this should return true
- *
- * @return Does the Control need save game serialization?
- */
- virtual inline bool needsSerialization() { return false; }
+ virtual bool process(uint32 deltaTimeInMillis) {
+ return false;
+ }
+
+ void setVenus();
protected:
- ZVision * _engine;
+ ZVision *_engine;
uint32 _key;
- bool _enabled;
+ int32 _venusId;
+ void getParams(const Common::String &inputStr, Common::String &parameter, Common::String &values);
// Static member functions
public:
static void parseFlatControl(ZVision *engine);
static void parsePanoramaControl(ZVision *engine, Common::SeekableReadStream &stream);
static void parseTiltControl(ZVision *engine, Common::SeekableReadStream &stream);
+private:
+ ControlType _type;
};
-// TODO: Implement InputControl
-// TODO: Implement SaveControl
-// TODO: Implement SlotControl
-// TODO: Implement SafeControl
-// TODO: Implement FistControl
-// TODO: Implement HotMovieControl
-// TODO: Implement PaintControl
-// TODO: Implement TilterControl
-
} // End of namespace ZVision
#endif
diff --git a/engines/zvision/scripting/controls/animation_control.cpp b/engines/zvision/scripting/controls/animation_control.cpp
deleted file mode 100644
index e351e81d25..0000000000
--- a/engines/zvision/scripting/controls/animation_control.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/scummsys.h"
-
-#include "zvision/scripting/controls/animation_control.h"
-
-#include "zvision/zvision.h"
-#include "zvision/graphics/render_manager.h"
-#include "zvision/scripting/script_manager.h"
-#include "zvision/animation/rlf_animation.h"
-#include "zvision/video/zork_avi_decoder.h"
-
-#include "video/video_decoder.h"
-
-#include "graphics/surface.h"
-
-
-namespace ZVision {
-
-AnimationControl::AnimationControl(ZVision *engine, uint32 controlKey, const Common::String &fileName)
- : Control(engine, controlKey),
- _fileType(RLF),
- _loopCount(1),
- _currentLoop(0),
- _accumulatedTime(0),
- _cachedFrame(0),
- _cachedFrameNeedsDeletion(false) {
- if (fileName.hasSuffix(".rlf")) {
- _fileType = RLF;
- _animation.rlf = new RlfAnimation(fileName, false);
- } else if (fileName.hasSuffix(".avi")) {
- _fileType = AVI;
- _animation.avi = new ZorkAVIDecoder();
- _animation.avi->loadFile(fileName);
- } else {
- warning("Unrecognized animation file type: %s", fileName.c_str());
- }
-
- _cachedFrame = new Graphics::Surface();
-}
-
-AnimationControl::~AnimationControl() {
- if (_fileType == RLF) {
- delete _animation.rlf;
- } else if (_fileType == AVI) {
- delete _animation.avi;
- }
-
- _cachedFrame->free();
- delete _cachedFrame;
-}
-
-bool AnimationControl::process(uint32 deltaTimeInMillis) {
- if (!_enabled) {
- return false;
- }
-
- bool finished = false;
-
- if (_fileType == RLF) {
- _accumulatedTime += deltaTimeInMillis;
-
- uint32 frameTime = _animation.rlf->frameTime();
- if (_accumulatedTime >= frameTime) {
- while (_accumulatedTime >= frameTime) {
- _accumulatedTime -= frameTime;
-
- // Make sure the frame is inside the working window
- // If it's not, then just return
-
- RenderManager *renderManager = _engine->getRenderManager();
- Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
- Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _animation.rlf->width(), workingWindowPoint.y + _animation.rlf->height());
-
- // If the clip returns false, it means the animation is outside the working window
- if (!renderManager->clipRectToWorkingWindow(subRect)) {
- return false;
- }
-
- const Graphics::Surface *frame = _animation.rlf->getNextFrame();
-
- // Animation frames for PANORAMAs are transposed, so un-transpose them
- RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
- if (state == RenderTable::PANORAMA) {
- Graphics::Surface *tranposedFrame = RenderManager::tranposeSurface(frame);
-
- renderManager->copyRectToWorkingWindow((uint16 *)tranposedFrame->getBasePtr(tranposedFrame->w - subRect.width(), tranposedFrame->h - subRect.height()), subRect.left, subRect.top, _animation.rlf->width(), subRect.width(), subRect.height());
-
- // If the background can move, we need to cache the last frame so it can be rendered during background movement
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- if (_cachedFrameNeedsDeletion) {
- _cachedFrame->free();
- delete _cachedFrame;
- _cachedFrameNeedsDeletion = false;
- }
- _cachedFrame = tranposedFrame;
- _cachedFrameNeedsDeletion = true;
- } else {
- // Cleanup
- tranposedFrame->free();
- delete tranposedFrame;
- }
- } else {
- renderManager->copyRectToWorkingWindow((const uint16 *)frame->getBasePtr(frame->w - subRect.width(), frame->h - subRect.height()), subRect.left, subRect.top, _animation.rlf->width(), subRect.width(), subRect.height());
-
- // If the background can move, we need to cache the last frame so it can be rendered during background movement
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- if (_cachedFrameNeedsDeletion) {
- _cachedFrame->free();
- delete _cachedFrame;
- _cachedFrameNeedsDeletion = false;
- }
- _cachedFrame->copyFrom(*frame);
- }
- }
-
- // Check if we should continue looping
- if (_animation.rlf->endOfAnimation()) {
- _animation.rlf->seekToFrame(-1);
- if (_loopCount > 0) {
- _currentLoop++;
- if (_currentLoop >= _loopCount) {
- finished = true;
- }
- }
- }
- }
- } else {
- // If the background can move, we have to keep rendering animation frames, otherwise the animation flickers during background movement
- RenderManager *renderManager = _engine->getRenderManager();
- RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
-
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
- Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _cachedFrame->w, workingWindowPoint.y + _cachedFrame->h);
-
- // If the clip returns false, it means the animation is outside the working window
- if (!renderManager->clipRectToWorkingWindow(subRect)) {
- return false;
- }
-
- renderManager->copyRectToWorkingWindow((uint16 *)_cachedFrame->getBasePtr(_cachedFrame->w - subRect.width(), _cachedFrame->h - subRect.height()), subRect.left, subRect.top, _cachedFrame->w, subRect.width(), subRect.height());
- }
- }
- } else if (_fileType == AVI) {
- if (!_animation.avi->isPlaying()) {
- _animation.avi->start();
- }
-
- if (_animation.avi->needsUpdate()) {
- const Graphics::Surface *frame = _animation.avi->decodeNextFrame();
-
- if (frame) {
- // Make sure the frame is inside the working window
- // If it's not, then just return
-
- RenderManager *renderManager = _engine->getRenderManager();
- Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
- Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + frame->w, workingWindowPoint.y + frame->h);
-
- // If the clip returns false, it means the animation is outside the working window
- if (!renderManager->clipRectToWorkingWindow(subRect)) {
- return false;
- }
-
- // Animation frames for PANORAMAs are transposed, so un-transpose them
- RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
- if (state == RenderTable::PANORAMA) {
- Graphics::Surface *tranposedFrame = RenderManager::tranposeSurface(frame);
-
- renderManager->copyRectToWorkingWindow((uint16 *)tranposedFrame->getBasePtr(tranposedFrame->w - subRect.width(), tranposedFrame->h - subRect.height()), subRect.left, subRect.top, frame->w, subRect.width(), subRect.height());
-
- // If the background can move, we need to cache the last frame so it can be rendered during background movement
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- if (_cachedFrameNeedsDeletion) {
- _cachedFrame->free();
- delete _cachedFrame;
- _cachedFrameNeedsDeletion = false;
- }
- _cachedFrame = tranposedFrame;
- _cachedFrameNeedsDeletion = true;
- } else {
- // Cleanup
- tranposedFrame->free();
- delete tranposedFrame;
- }
- } else {
- renderManager->copyRectToWorkingWindow((const uint16 *)frame->getBasePtr(frame->w - subRect.width(), frame->h - subRect.height()), subRect.left, subRect.top, frame->w, subRect.width(), subRect.height());
-
- // If the background can move, we need to cache the last frame so it can be rendered during background movement
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- if (_cachedFrameNeedsDeletion) {
- _cachedFrame->free();
- delete _cachedFrame;
- _cachedFrameNeedsDeletion = false;
- }
- _cachedFrame->copyFrom(*frame);
- }
- }
- } else {
- // If the background can move, we have to keep rendering animation frames, otherwise the animation flickers during background movement
- RenderManager *renderManager = _engine->getRenderManager();
- RenderTable::RenderState state = renderManager->getRenderTable()->getRenderState();
-
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- Common::Point workingWindowPoint = renderManager->imageSpaceToWorkingWindowSpace(Common::Point(_x, _y));
- Common::Rect subRect(workingWindowPoint.x, workingWindowPoint.y, workingWindowPoint.x + _cachedFrame->w, workingWindowPoint.y + _cachedFrame->h);
-
- // If the clip returns false, it means the animation is outside the working window
- if (!renderManager->clipRectToWorkingWindow(subRect)) {
- return false;
- }
-
- renderManager->copyRectToWorkingWindow((uint16 *)_cachedFrame->getBasePtr(_cachedFrame->w - subRect.width(), _cachedFrame->h - subRect.height()), subRect.left, subRect.top, _cachedFrame->w, subRect.width(), subRect.height());
- }
- }
- }
-
- // Check if we should continue looping
- if (_animation.avi->endOfVideo()) {
- _animation.avi->rewind();
- if (_loopCount > 0) {
- _currentLoop++;
- if (_currentLoop >= _loopCount) {
- _animation.avi->stop();
- finished = true;
- }
- }
- }
- }
-
- // If we're done, set _animation key = 2 (Why 2? I don't know. It's just the value that they used)
- // Then disable the control. DON'T delete it. It can be re-used
- if (finished) {
- _engine->getScriptManager()->setStateValue(_animationKey, 2);
- disable();
- _currentLoop = 0;
- }
-
- return false;
-}
-
-} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/fist_control.cpp b/engines/zvision/scripting/controls/fist_control.cpp
new file mode 100644
index 0000000000..dd6a7f11a9
--- /dev/null
+++ b/engines/zvision/scripting/controls/fist_control.cpp
@@ -0,0 +1,319 @@
+/* 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 "zvision/scripting/controls/fist_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/animation/meta_animation.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
+namespace ZVision {
+
+FistControl::FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_FIST) {
+ _cursor = CursorIndex_Idle;
+ _animation = NULL;
+ _soundKey = 0;
+ _fiststatus = 0;
+ _order = 0;
+ _fistnum = 0;
+
+ _frameCur = -1;
+ _frameEnd = -1;
+ _frameTime = 0;
+ _lastRenderedFrame = -1;
+ _animationId = 0;
+
+ clearFistArray(_fistsUp);
+ clearFistArray(_fistsDwn);
+
+ _numEntries = 0;
+ _entries.clear();
+
+ _anmRect = Common::Rect();
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("sound_key", true)) {
+ _soundKey = atoi(values.c_str());
+ } else if (param.matchString("cursor", true)) {
+ _cursor = _engine->getCursorManager()->getCursorId(values);
+ } else if (param.matchString("descfile", true)) {
+ readDescFile(values);
+ } else if (param.matchString("animation_id", true)) {
+ _animationId = atoi(values.c_str());
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+}
+
+FistControl::~FistControl() {
+ if (_animation)
+ delete _animation;
+
+ clearFistArray(_fistsUp);
+ clearFistArray(_fistsDwn);
+ _entries.clear();
+}
+
+void FistControl::renderFrame(uint frameNumber) {
+ if ((int32)frameNumber == _lastRenderedFrame)
+ return;
+
+ _lastRenderedFrame = frameNumber;
+
+ const Graphics::Surface *frameData;
+
+ if (_animation) {
+ frameData = _animation->getFrameData(frameNumber);
+ if (frameData)
+ _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _anmRect);
+ }
+}
+
+bool FistControl::process(uint32 deltaTimeInMillis) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_frameCur >= 0 && _frameEnd >= 0)
+ if (_frameCur <= _frameEnd) {
+ _frameTime -= deltaTimeInMillis;
+
+ if (_frameTime <= 0) {
+ _frameTime = _animation->frameTime();
+
+ renderFrame(_frameCur);
+
+ _frameCur++;
+
+ if (_frameCur > _frameEnd)
+ _engine->getScriptManager()->setStateValue(_animationId, 2);
+ }
+ }
+
+ return false;
+}
+
+bool FistControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (mouseIn(screenSpacePos, backgroundImageSpacePos) >= 0) {
+ _engine->getCursorManager()->changeCursor(_cursor);
+ return true;
+ }
+
+ return false;
+}
+
+bool FistControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ int fistNumber = mouseIn(screenSpacePos, backgroundImageSpacePos);
+
+ if (fistNumber >= 0) {
+ setVenus();
+
+ uint32 oldStatus = _fiststatus;
+ _fiststatus ^= (1 << fistNumber);
+
+ for (int i = 0; i < _numEntries; i++)
+ if (_entries[i]._bitsStrt == oldStatus && _entries[i]._bitsEnd == _fiststatus) {
+ _frameCur = _entries[i]._anmStrt;
+ _frameEnd = _entries[i]._anmEnd;
+ _frameTime = 0;
+
+ _engine->getScriptManager()->setStateValue(_animationId, 1);
+ _engine->getScriptManager()->setStateValue(_soundKey, _entries[i]._sound);
+ break;
+ }
+
+ _engine->getScriptManager()->setStateValue(_key, _fiststatus);
+ }
+
+ return false;
+}
+
+void FistControl::readDescFile(const Common::String &fileName) {
+ Common::File file;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("Desc file %s could could be opened", fileName.c_str());
+ return;
+ }
+
+ Common::String line;
+ Common::String param;
+ Common::String values;
+
+ while (!file.eos()) {
+ line = file.readLine();
+ getFistParams(line, param, values);
+
+ if (param.matchString("animation_id", true)) {
+ // Not used
+ } else if (param.matchString("animation", true)) {
+ _animation = new MetaAnimation(values, _engine);
+ } else if (param.matchString("anim_rect", true)) {
+ int left, top, right, bottom;
+ sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom);
+ _anmRect = Common::Rect(left, top, right, bottom);
+ } else if (param.matchString("num_fingers", true)) {
+ sscanf(values.c_str(), "%d", &_fistnum);
+ _fistsUp.resize(_fistnum);
+ _fistsDwn.resize(_fistnum);
+ } else if (param.matchString("entries", true)) {
+ sscanf(values.c_str(), "%d", &_numEntries);
+ _entries.resize(_numEntries);
+ } else if (param.matchString("eval_order_ascending", true)) {
+ sscanf(values.c_str(), "%d", &_order);
+ } else if (param.matchString("up_hs_num_*", true)) {
+ int fist, num;
+ num = atoi(values.c_str());
+
+ sscanf(param.c_str(), "up_hs_num_%d", &fist);
+ _fistsUp[fist].resize(num);
+ } else if (param.matchString("up_hs_*", true)) {
+ int16 fist, box, x1, y1, x2, y2;
+ sscanf(param.c_str(), "up_hs_%hd_%hd", &fist, &box);
+ sscanf(values.c_str(), "%hd %hd %hd %hd", &x1, &y1, &x2, &y2);
+ (_fistsUp[fist])[box] = Common::Rect(x1, y1, x2, y2);
+ } else if (param.matchString("down_hs_num_*", true)) {
+ int fist, num;
+ num = atoi(values.c_str());
+
+ sscanf(param.c_str(), "down_hs_num_%d", &fist);
+ _fistsDwn[fist].resize(num);
+ } else if (param.matchString("down_hs_*", true)) {
+ int16 fist, box, x1, y1, x2, y2;
+ sscanf(param.c_str(), "down_hs_%hd_%hd", &fist, &box);
+ sscanf(values.c_str(), "%hd %hd %hd %hd", &x1, &y1, &x2, &y2);
+ (_fistsDwn[fist])[box] = Common::Rect(x1, y1, x2, y2);
+ } else {
+ int entry, start, end, sound;
+ char bitsStart[33];
+ char bitsEnd[33];
+ entry = atoi(param.c_str());
+ if (sscanf(values.c_str(), "%s %s %d %d (%d)", bitsStart, bitsEnd, &start, &end, &sound) == 5) {
+ _entries[entry]._bitsStrt = readBits(bitsStart);
+ _entries[entry]._bitsEnd = readBits(bitsEnd);
+ _entries[entry]._anmStrt = start;
+ _entries[entry]._anmEnd = end;
+ _entries[entry]._sound = sound;
+ }
+ }
+ }
+ file.close();
+}
+
+void FistControl::clearFistArray(Common::Array< Common::Array<Common::Rect> > &arr) {
+ for (uint i = 0; i < arr.size(); i++)
+ arr[i].clear();
+
+ arr.clear();
+}
+
+uint32 FistControl::readBits(const char *str) {
+ uint32 bfield = 0;
+ int len = strlen(str);
+ for (int i = 0; i < len; i++)
+ if (str[i] != '0')
+ bfield |= (1 << i);
+ return bfield;
+}
+
+int FistControl::mouseIn(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_order) {
+ for (int i = 0; i < _fistnum; i++) {
+ if (((_fiststatus >> i) & 1) == 1) {
+ for (uint j = 0; j < _fistsDwn[i].size(); j++)
+ if ((_fistsDwn[i])[j].contains(backgroundImageSpacePos))
+ return i;
+ } else {
+ for (uint j = 0; j < _fistsUp[i].size(); j++)
+ if ((_fistsUp[i])[j].contains(backgroundImageSpacePos))
+ return i;
+ }
+ }
+ } else {
+ for (int i = _fistnum - 1; i >= 0; i--) {
+ if (((_fiststatus >> i) & 1) == 1) {
+ for (uint j = 0; j < _fistsDwn[i].size(); j++)
+ if ((_fistsDwn[i])[j].contains(backgroundImageSpacePos))
+ return i;
+ } else {
+ for (uint j = 0; j < _fistsUp[i].size(); j++)
+ if ((_fistsUp[i])[j].contains(backgroundImageSpacePos))
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+void FistControl::getFistParams(const Common::String &inputStr, Common::String &parameter, Common::String &values) {
+ const char *chrs = inputStr.c_str();
+ uint lbr;
+
+ for (lbr = 0; lbr < inputStr.size(); lbr++)
+ if (chrs[lbr] == ':')
+ break;
+
+ if (lbr >= inputStr.size())
+ return;
+
+ uint rbr;
+
+ for (rbr = lbr + 1; rbr < inputStr.size(); rbr++)
+ if (chrs[rbr] == '~')
+ break;
+
+ if (rbr >= inputStr.size())
+ return;
+
+ parameter = Common::String(chrs, chrs + lbr);
+ values = Common::String(chrs + lbr + 1, chrs + rbr);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h
new file mode 100644
index 0000000000..cb765c429a
--- /dev/null
+++ b/engines/zvision/scripting/controls/fist_control.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_FIST_CONTROL_H
+#define ZVISION_FIST_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace ZVision {
+
+class MetaAnimation;
+
+class FistControl : public Control {
+public:
+ FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~FistControl();
+
+private:
+ uint32 _fiststatus;
+ int _fistnum;
+ int16 _cursor;
+ int _order;
+
+ Common::Array< Common::Array<Common::Rect> > _fistsUp;
+ Common::Array< Common::Array<Common::Rect> > _fistsDwn;
+
+ int32 _numEntries;
+
+ struct entries {
+ uint32 _bitsStrt;
+ uint32 _bitsEnd;
+ int32 _anmStrt;
+ int32 _anmEnd;
+ int32 _sound;
+ };
+
+ Common::Array<entries> _entries;
+
+ MetaAnimation *_animation;
+ Common::Rect _anmRect;
+ int32 _soundKey;
+ int32 _frameCur;
+ int32 _frameEnd;
+ int32 _frameTime;
+ int32 _lastRenderedFrame;
+ int32 _animationId;
+
+public:
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ void renderFrame(uint frameNumber);
+ void readDescFile(const Common::String &fileName);
+ void clearFistArray(Common::Array< Common::Array<Common::Rect> > &arr);
+ uint32 readBits(const char *str);
+ int mouseIn(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ void getFistParams(const Common::String &inputStr, Common::String &parameter, Common::String &values);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/hotmov_control.cpp b/engines/zvision/scripting/controls/hotmov_control.cpp
new file mode 100644
index 0000000000..68861dc221
--- /dev/null
+++ b/engines/zvision/scripting/controls/hotmov_control.cpp
@@ -0,0 +1,200 @@
+/* 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 "zvision/scripting/controls/hotmov_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/animation/meta_animation.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
+namespace ZVision {
+
+HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_HOTMOV) {
+ _animation = NULL;
+ _cycle = 0;
+ _curFrame = -1;
+ _lastRenderedFrame = -1;
+ _frames.clear();
+ _frameTime = 0;
+ _cyclesCount = 0;
+ _framesCount = 0;
+
+ _engine->getScriptManager()->setStateValue(_key, 0);
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("hs_frame_list", true)) {
+ readHsFile(values);
+ } else if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _rectangle = Common::Rect(x, y, width, height);
+ } else if (param.matchString("num_frames", true)) {
+ _framesCount = atoi(values.c_str());
+ } else if (param.matchString("num_cycles", true)) {
+ _cyclesCount = atoi(values.c_str());
+ } else if (param.matchString("animation", true)) {
+ char filename[64];
+ sscanf(values.c_str(), "%s", filename);
+ values = Common::String(filename);
+ _animation = new MetaAnimation(values, _engine);
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+}
+
+HotMovControl::~HotMovControl() {
+ if (_animation)
+ delete _animation;
+
+ _frames.clear();
+}
+
+void HotMovControl::renderFrame(uint frameNumber) {
+ if ((int)frameNumber == _lastRenderedFrame)
+ return;
+
+ _lastRenderedFrame = frameNumber;
+
+ const Graphics::Surface *frameData;
+
+ if (_animation) {
+ frameData = _animation->getFrameData(frameNumber);
+ if (frameData)
+ _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _rectangle);
+ }
+}
+
+bool HotMovControl::process(uint32 deltaTimeInMillis) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_cycle < _cyclesCount) {
+ _frameTime -= deltaTimeInMillis;
+
+ if (_frameTime <= 0) {
+ _curFrame++;
+ if (_curFrame >= _framesCount) {
+ _curFrame = 0;
+ _cycle++;
+ }
+ if (_cycle != _cyclesCount)
+ renderFrame(_curFrame);
+ else
+ _engine->getScriptManager()->setStateValue(_key, 2);
+
+ _frameTime = _animation->frameTime();
+ }
+ }
+
+ return false;
+}
+
+bool HotMovControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_cycle < _cyclesCount) {
+ if (_frames[_curFrame].contains(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(CursorIndex_Active);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool HotMovControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_cycle < _cyclesCount) {
+ if (_frames[_curFrame].contains(backgroundImageSpacePos)) {
+ setVenus();
+ _engine->getScriptManager()->setStateValue(_key, 1);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void HotMovControl::readHsFile(const Common::String &fileName) {
+ if (_framesCount == 0)
+ return;
+
+ Common::File file;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("HS file %s could could be opened", fileName.c_str());
+ return;
+ }
+
+ Common::String line;
+
+ _frames.resize(_framesCount);
+
+ while (!file.eos()) {
+ line = file.readLine();
+
+ int frame;
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(line.c_str(), "%d:%d %d %d %d~", &frame, &x, &y, &width, &height);
+
+ if (frame >= 0 && frame < _framesCount)
+ _frames[frame] = Common::Rect(x, y, width, height);
+ }
+ file.close();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/hotmov_control.h b/engines/zvision/scripting/controls/hotmov_control.h
new file mode 100644
index 0000000000..86600d65dc
--- /dev/null
+++ b/engines/zvision/scripting/controls/hotmov_control.h
@@ -0,0 +1,62 @@
+/* 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 ZVISION_HOTMOV_CONTROL_H
+#define ZVISION_HOTMOV_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace ZVision {
+
+class MetaAnimation;
+
+class HotMovControl : public Control {
+public:
+ HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~HotMovControl();
+
+private:
+ int32 _framesCount;
+ int32 _frameTime;
+ int32 _curFrame;
+ int32 _lastRenderedFrame;
+ int32 _cycle;
+ int32 _cyclesCount;
+ MetaAnimation *_animation;
+ Common::Rect _rectangle;
+ Common::Array<Common::Rect> _frames;
+public:
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ void renderFrame(uint frameNumber);
+ void readHsFile(const Common::String &fileName);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
index a35548d02e..c541693ec3 100644
--- a/engines/zvision/scripting/controls/input_control.cpp
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -23,10 +23,11 @@
#include "common/scummsys.h"
#include "zvision/scripting/controls/input_control.h"
+#include "zvision/cursors/cursor_manager.h"
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
-#include "zvision/strings/string_manager.h"
+#include "zvision/text/string_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/utility/utility.h"
@@ -34,109 +35,221 @@
#include "common/stream.h"
#include "common/rect.h"
-
namespace ZVision {
InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
- : Control(engine, key),
- _nextTabstop(0),
- _focused(false),
- _textChanged(false),
- _cursorOffset(0) {
+ : Control(engine, key, CONTROL_INPUT),
+ _nextTabstop(0),
+ _focused(false),
+ _textChanged(false),
+ _cursorOffset(0),
+ _enterPressed(false),
+ _readOnly(false),
+ _txtWidth(0),
+ _animation(NULL) {
// Loop until we find the closing brace
Common::String line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
- if (line.matchString("*rectangle*", true)) {
+ if (param.matchString("rectangle", true)) {
int x1;
int y1;
int x2;
int y2;
- sscanf(line.c_str(), "%*[^(](%d %d %d %d)", &x1, &y1, &x2, &y2);
+ sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2);
_textRectangle = Common::Rect(x1, y1, x2, y2);
- } else if (line.matchString("*aux_hotspot*", true)) {
+ } else if (param.matchString("aux_hotspot", true)) {
int x1;
int y1;
int x2;
int y2;
- sscanf(line.c_str(), "%*[^(](%d %d %d %d)", &x1, &y1, &x2, &y2);
+ sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2);
_headerRectangle = Common::Rect(x1, y1, x2, y2);
- } else if (line.matchString("*string_init*", true)) {
+ } else if (param.matchString("string_init", true)) {
uint fontFormatNumber;
- sscanf(line.c_str(), "%*[^(](%u)", &fontFormatNumber);
+ sscanf(values.c_str(), "%u", &fontFormatNumber);
- _textStyle = _engine->getStringManager()->getTextStyle(fontFormatNumber);
- } else if (line.matchString("*next_tabstop*", true)) {
- sscanf(line.c_str(), "%*[^(](%u)", &_nextTabstop);
- } else if (line.matchString("*cursor_animation*", true)) {
- char fileName[26];
+ _stringInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
+ } else if (param.matchString("chooser_init_string", true)) {
+ uint fontFormatNumber;
- sscanf(line.c_str(), "%*[^(](%25s %*u)", fileName);
+ sscanf(values.c_str(), "%u", &fontFormatNumber);
- _cursorAnimationFileName = Common::String(fileName);
- } else if (line.matchString("*cursor_dimensions*", true)) {
+ _stringChooserInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
+ } else if (param.matchString("next_tabstop", true)) {
+ sscanf(values.c_str(), "%u", &_nextTabstop);
+ } else if (param.matchString("cursor_dimensions", true)) {
// Ignore, use the dimensions in the animation file
- } else if (line.matchString("*cursor_animation_frames*", true)) {
+ } else if (param.matchString("cursor_animation_frames", true)) {
// Ignore, use the frame count in the animation file
- } else if (line.matchString("*focus*", true)) {
+ } else if (param.matchString("cursor_animation", true)) {
+ char fileName[25];
+
+ sscanf(values.c_str(), "%25s %*u", fileName);
+
+ _animation = new MetaAnimation(fileName, _engine);
+ _frame = -1;
+ _frameDelay = 0;
+ } else if (param.matchString("focus", true)) {
_focused = true;
+ _engine->getScriptManager()->setFocusControlKey(_key);
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
}
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+}
+
+bool InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_textRectangle.contains(backgroundImageSpacePos)) {
+ if (!_readOnly) {
+ // Save
+ _engine->getScriptManager()->focusControl(_key);
+ setVenus();
+ } else {
+ // Restore
+ if (_currentInputText.size()) {
+ setVenus();
+ _enterPressed = true;
+ }
+ }
}
+ return false;
}
-void InputControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- _engine->getScriptManager()->focusControl(_key);
+bool InputControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_textRectangle.contains(backgroundImageSpacePos)) {
+ if (!_readOnly) {
+ // Save
+ _engine->getCursorManager()->changeCursor(CursorIndex_Active);
+ return true;
+ } else {
+ // Restore
+ if (_currentInputText.size()) {
+ _engine->getCursorManager()->changeCursor(CursorIndex_Active);
+ _engine->getScriptManager()->focusControl(_key);
+ return true;
+ }
+ }
+ }
+ return false;
}
-void InputControl::onKeyDown(Common::KeyState keyState) {
+bool InputControl::onKeyDown(Common::KeyState keyState) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
if (!_focused) {
- return;
+ return false;
}
if (keyState.keycode == Common::KEYCODE_BACKSPACE) {
- _currentInputText.deleteLastChar();
+ if (!_readOnly) {
+ _currentInputText.deleteLastChar();
+ _textChanged = true;
+ }
+ } else if (keyState.keycode == Common::KEYCODE_RETURN) {
+ _enterPressed = true;
} else if (keyState.keycode == Common::KEYCODE_TAB) {
- _focused = false;
+ unfocus();
// Focus the next input control
_engine->getScriptManager()->focusControl(_nextTabstop);
+ // Don't process this event for other controls
+ return true;
} else {
- // Otherwise, append the new character to the end of the current text
-
- uint16 asciiValue = keyState.ascii;
- // We only care about text values
- if (asciiValue >= 32 && asciiValue <= 126) {
- _currentInputText += (char)asciiValue;
- _textChanged = true;
+ if (!_readOnly) {
+ // Otherwise, append the new character to the end of the current text
+ uint16 asciiValue = keyState.ascii;
+ // We only care about text values
+ if (asciiValue >= 32 && asciiValue <= 126) {
+ _currentInputText += (char)asciiValue;
+ _textChanged = true;
+ }
}
}
+ return false;
}
bool InputControl::process(uint32 deltaTimeInMillis) {
- if (!_focused) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
- }
// First see if we need to render the text
if (_textChanged) {
// Blit the text using the RenderManager
- Common::Rect destRect = _engine->getRenderManager()->renderTextToWorkingWindow(_key, _currentInputText, _textStyle.font, _textRectangle.left, _textRectangle.top, _textStyle.color, _textRectangle.width());
- _cursorOffset = destRect.left - _textRectangle.left;
+ Graphics::Surface txt;
+ txt.create(_textRectangle.width(), _textRectangle.height(), _engine->_pixelFormat);
+
+ if (!_readOnly || !_focused)
+ _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringInit, txt);
+ else
+ _txtWidth = _engine->getTextRenderer()->drawTxt(_currentInputText, _stringChooserInit, txt);
+
+ _engine->getRenderManager()->blitSurfaceToBkg(txt, _textRectangle.left, _textRectangle.top);
+
+ txt.free();
}
- // Render the next frame of the animation
- // TODO: Implement animation handling
+ if (_animation && !_readOnly && _focused) {
+ bool needDraw = true;// = _textChanged;
+ _frameDelay -= deltaTimeInMillis;
+ if (_frameDelay <= 0) {
+ _frame = (_frame + 1) % _animation->frameCount();
+ _frameDelay = _animation->frameTime();
+ needDraw = true;
+ }
+ if (needDraw) {
+ const Graphics::Surface *srf = _animation->getFrameData(_frame);
+ uint32 xx = _textRectangle.left + _txtWidth;
+ if (xx >= _textRectangle.left + (_textRectangle.width() - _animation->width()))
+ xx = _textRectangle.left + _textRectangle.width() - _animation->width();
+ _engine->getRenderManager()->blitSurfaceToBkg(*srf, xx, _textRectangle.top);
+ }
+ }
+
+ _textChanged = false;
+ return false;
+}
+
+bool InputControl::enterPress() {
+ if (_enterPressed) {
+ _enterPressed = false;
+ return true;
+ }
return false;
}
+void InputControl::setText(const Common::String &_str) {
+ _currentInputText = _str;
+ _textChanged = true;
+}
+
+const Common::String InputControl::getText() {
+ return _currentInputText;
+}
+
+void InputControl::setReadOnly(bool readonly) {
+ _readOnly = readonly;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h
index 32432438bb..410caf6d49 100644
--- a/engines/zvision/scripting/controls/input_control.h
+++ b/engines/zvision/scripting/controls/input_control.h
@@ -24,11 +24,12 @@
#define ZVISION_INPUT_CONTROL_H
#include "zvision/scripting/control.h"
-#include "zvision/strings/string_manager.h"
+#include "zvision/animation/meta_animation.h"
+#include "zvision/text/text.h"
+#include "zvision/text/string_manager.h"
#include "common/rect.h"
-
namespace ZVision {
class InputControl : public Control {
@@ -38,21 +39,39 @@ public:
private:
Common::Rect _textRectangle;
Common::Rect _headerRectangle;
- StringManager::TextStyle _textStyle;
+ cTxtStyle _stringInit;
+ cTxtStyle _stringChooserInit;
uint32 _nextTabstop;
- Common::String _cursorAnimationFileName;
bool _focused;
Common::String _currentInputText;
bool _textChanged;
uint _cursorOffset;
+ bool _enterPressed;
+ bool _readOnly;
+
+ int16 _txtWidth;
+ MetaAnimation *_animation;
+ int32 _frameDelay;
+ int16 _frame;
public:
- void focus() { _focused = true; }
- void unfocus() { _focused = false; }
- void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
- void onKeyDown(Common::KeyState keyState);
+ void focus() {
+ _focused = true;
+ _textChanged = true;
+ }
+ void unfocus() {
+ _focused = false;
+ _textChanged = true;
+ }
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onKeyDown(Common::KeyState keyState);
bool process(uint32 deltaTimeInMillis);
+ void setText(const Common::String &_str);
+ const Common::String getText();
+ bool enterPress();
+ void setReadOnly(bool);
};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 9724e661b7..1e4087963e 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -28,8 +28,7 @@
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/cursors/cursor_manager.h"
-#include "zvision/animation/rlf_animation.h"
-#include "zvision/video/zork_avi_decoder.h"
+#include "zvision/animation/meta_animation.h"
#include "zvision/utility/utility.h"
#include "common/stream.h"
@@ -39,118 +38,116 @@
#include "graphics/surface.h"
-
namespace ZVision {
LeverControl::LeverControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
- : Control(engine, key),
- _frameInfo(0),
- _frameCount(0),
- _startFrame(0),
- _currentFrame(0),
- _lastRenderedFrame(0),
- _mouseIsCaptured(false),
- _isReturning(false),
- _accumulatedTime(0),
- _returnRoutesCurrentFrame(0) {
+ : Control(engine, key, CONTROL_LEVER),
+ _frameInfo(0),
+ _frameCount(0),
+ _startFrame(0),
+ _currentFrame(0),
+ _lastRenderedFrame(0),
+ _mouseIsCaptured(false),
+ _isReturning(false),
+ _accumulatedTime(0),
+ _returnRoutesCurrentFrame(0) {
// Loop until we find the closing brace
Common::String line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
while (!stream.eos() && !line.contains('}')) {
- if (line.matchString("*descfile*", true)) {
+ if (param.matchString("descfile", true)) {
char levFileName[25];
- sscanf(line.c_str(), "%*[^(](%25[^)])", levFileName);
+ sscanf(values.c_str(), "%25s", levFileName);
parseLevFile(levFileName);
- } else if (line.matchString("*cursor*", true)) {
+ } else if (param.matchString("cursor", true)) {
char cursorName[25];
- sscanf(line.c_str(), "%*[^(](%25[^)])", cursorName);
+ sscanf(values.c_str(), "%25s", cursorName);
- _cursorName = Common::String(cursorName);
+ _cursor = _engine->getCursorManager()->getCursorId(Common::String(cursorName));
}
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
}
renderFrame(_currentFrame);
}
LeverControl::~LeverControl() {
- if (_fileType == AVI) {
- delete _animation.avi;
- } else if (_fileType == RLF) {
- delete _animation.rlf;
- }
-
+ if (_animation)
+ delete _animation;
+
delete[] _frameInfo;
}
void LeverControl::parseLevFile(const Common::String &fileName) {
Common::File file;
- if (!file.open(fileName)) {
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
warning("LEV file %s could could be opened", fileName.c_str());
return;
}
- Common::String line = file.readLine();
+ Common::String line;
+ Common::String param;
+ Common::String values;
while (!file.eos()) {
- if (line.matchString("*animation_id*", true)) {
+ line = file.readLine();
+ getLevParams(line, param, values);
+
+ if (param.matchString("animation_id", true)) {
// Not used
- } else if (line.matchString("*filename*", true)) {
- char fileNameBuffer[25];
- sscanf(line.c_str(), "%*[^:]:%25[^~]~", fileNameBuffer);
-
- Common::String animationFileName(fileNameBuffer);
-
- if (animationFileName.hasSuffix(".avi")) {
- _animation.avi = new ZorkAVIDecoder();
- _animation.avi->loadFile(animationFileName);
- _fileType = AVI;
- } else if (animationFileName.hasSuffix(".rlf")) {
- _animation.rlf = new RlfAnimation(animationFileName, false);
- _fileType = RLF;
- }
- } else if (line.matchString("*skipcolor*", true)) {
+ } else if (param.matchString("filename", true)) {
+ _animation = new MetaAnimation(values, _engine);
+ } else if (param.matchString("skipcolor", true)) {
// Not used
- } else if (line.matchString("*anim_coords*", true)) {
+ } else if (param.matchString("anim_coords", true)) {
int left, top, right, bottom;
- sscanf(line.c_str(), "%*[^:]:%d %d %d %d~", &left, &top, &right, &bottom);
+ sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom);
_animationCoords.left = left;
_animationCoords.top = top;
_animationCoords.right = right;
_animationCoords.bottom = bottom;
- } else if (line.matchString("*mirrored*", true)) {
+ } else if (param.matchString("mirrored", true)) {
uint mirrored;
- sscanf(line.c_str(), "%*[^:]:%u~", &mirrored);
+ sscanf(values.c_str(), "%u", &mirrored);
_mirrored = mirrored == 0 ? false : true;
- } else if (line.matchString("*frames*", true)) {
- sscanf(line.c_str(), "%*[^:]:%u~", &_frameCount);
+ } else if (param.matchString("frames", true)) {
+ sscanf(values.c_str(), "%u", &_frameCount);
_frameInfo = new FrameInfo[_frameCount];
- } else if (line.matchString("*elsewhere*", true)) {
+ } else if (param.matchString("elsewhere", true)) {
// Not used
- } else if (line.matchString("*out_of_control*", true)) {
+ } else if (param.matchString("out_of_control", true)) {
// Not used
- } else if (line.matchString("*start_pos*", true)) {
- sscanf(line.c_str(), "%*[^:]:%u~", &_startFrame);
+ } else if (param.matchString("start_pos", true)) {
+ sscanf(values.c_str(), "%u", &_startFrame);
_currentFrame = _startFrame;
- } else if (line.matchString("*hotspot_deltas*", true)) {
+ } else if (param.matchString("hotspot_deltas", true)) {
uint x;
uint y;
- sscanf(line.c_str(), "%*[^:]:%u %u~", &x, &y);
+ sscanf(values.c_str(), "%u %u", &x, &y);
_hotspotDelta.x = x;
_hotspotDelta.y = y;
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
} else {
uint frameNumber;
uint x, y;
+ line.toLowercase();
+
if (sscanf(line.c_str(), "%u:%u %u", &frameNumber, &x, &y) == 3) {
_frameInfo[frameNumber].hotspot.left = x;
_frameInfo[frameNumber].hotspot.top = y;
@@ -158,13 +155,13 @@ void LeverControl::parseLevFile(const Common::String &fileName) {
_frameInfo[frameNumber].hotspot.bottom = y + _hotspotDelta.y;
}
- Common::StringTokenizer tokenizer(line, " ^=()");
+ Common::StringTokenizer tokenizer(line, " ^=()~");
tokenizer.nextToken();
tokenizer.nextToken();
Common::String token = tokenizer.nextToken();
while (!tokenizer.empty()) {
- if (token == "D") {
+ if (token == "d") {
token = tokenizer.nextToken();
uint angle;
@@ -172,7 +169,7 @@ void LeverControl::parseLevFile(const Common::String &fileName) {
sscanf(token.c_str(), "%u,%u", &toFrame, &angle);
_frameInfo[frameNumber].directions.push_back(Direction(angle, toFrame));
- } else if (token.hasPrefix("P")) {
+ } else if (token.hasPrefix("p")) {
// Format: P(<from> to <to>)
tokenizer.nextToken();
tokenizer.nextToken();
@@ -186,26 +183,26 @@ void LeverControl::parseLevFile(const Common::String &fileName) {
}
}
- line = file.readLine();
+ // Don't read lines in this place because last will not be parsed.
}
}
-void LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_enabled) {
- return;
- }
-
+bool LeverControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
+ setVenus();
_mouseIsCaptured = true;
_lastMousePos = backgroundImageSpacePos;
}
+ return false;
}
-void LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_enabled) {
- return;
- }
-
+bool LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
if (_mouseIsCaptured) {
_mouseIsCaptured = false;
_engine->getScriptManager()->setStateValue(_key, _currentFrame);
@@ -214,20 +211,19 @@ void LeverControl::onMouseUp(const Common::Point &screenSpacePos, const Common::
_returnRoutesCurrentProgress = _frameInfo[_currentFrame].returnRoute.begin();
_returnRoutesCurrentFrame = _currentFrame;
}
+ return false;
}
bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_enabled) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
- }
-
+
bool cursorWasChanged = false;
if (_mouseIsCaptured) {
- // Make sure the square distance between the last point and the current point is greater than 64
+ // Make sure the square distance between the last point and the current point is greater than 16
// This is a heuristic. This determines how responsive the lever is to mouse movement.
- // TODO: Fiddle with the heuristic to get a good lever responsiveness 'feel'
- if (_lastMousePos.sqrDist(backgroundImageSpacePos) >= 64) {
+ if (_lastMousePos.sqrDist(backgroundImageSpacePos) >= 16) {
int angle = calculateVectorAngle(_lastMousePos, backgroundImageSpacePos);
_lastMousePos = backgroundImageSpacePos;
@@ -240,7 +236,7 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
}
}
} else if (_frameInfo[_currentFrame].hotspot.contains(backgroundImageSpacePos)) {
- _engine->getCursorManager()->changeCursor(_cursorName);
+ _engine->getCursorManager()->changeCursor(_cursor);
cursorWasChanged = true;
}
@@ -248,9 +244,8 @@ bool LeverControl::onMouseMove(const Common::Point &screenSpacePos, const Common
}
bool LeverControl::process(uint32 deltaTimeInMillis) {
- if (!_enabled) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
- }
if (_isReturning) {
_accumulatedTime += deltaTimeInMillis;
@@ -276,7 +271,7 @@ bool LeverControl::process(uint32 deltaTimeInMillis) {
renderFrame(_returnRoutesCurrentFrame);
}
}
-
+
return false;
}
@@ -301,7 +296,7 @@ int LeverControl::calculateVectorAngle(const Common::Point &pointOne, const Comm
// Calculate the angle using arctan
// Then convert to degrees. (180 / 3.14159 = 57.2958)
- int angle = int(atan((float)yDist / (float)xDist) * 57);
+ int angle = int(atan((float)yDist / (float)abs(xDist)) * 57);
// Calculate what quadrant pointTwo is in
uint quadrant = ((yDist > 0 ? 1 : 0) << 1) | (xDist < 0 ? 1 : 0);
@@ -350,16 +345,16 @@ int LeverControl::calculateVectorAngle(const Common::Point &pointOne, const Comm
// Convert the local angles to unit circle angles
switch (quadrant) {
case 0:
- angle = 180 + angle;
+ angle = -angle;
break;
case 1:
- // Do nothing
+ angle = angle + 180;
break;
case 2:
- angle = 180 + angle;
+ angle = 360 - angle;
break;
case 3:
- angle = 360 + angle;
+ angle = 180 + angle;
break;
}
@@ -377,26 +372,35 @@ void LeverControl::renderFrame(uint frameNumber) {
_lastRenderedFrame = frameNumber;
}
- const uint16 *frameData = 0;
- int x = _animationCoords.left;
- int y = _animationCoords.top;
- int width = 0;
- int height = 0;
-
- if (_fileType == RLF) {
- // getFrameData() will automatically optimize to getNextFrame() / getPreviousFrame() if it can
- frameData = (const uint16 *)_animation.rlf->getFrameData(frameNumber)->getPixels();
- width = _animation.rlf->width(); // Use the animation width instead of _animationCoords.width()
- height = _animation.rlf->height(); // Use the animation height instead of _animationCoords.height()
- } else if (_fileType == AVI) {
- _animation.avi->seekToFrame(frameNumber);
- const Graphics::Surface *surface = _animation.avi->decodeNextFrame();
- frameData = (const uint16 *)surface->getPixels();
- width = surface->w;
- height = surface->h;
- }
+ const Graphics::Surface *frameData;
+
+ frameData = _animation->getFrameData(frameNumber);
+ if (frameData)
+ _engine->getRenderManager()->blitSurfaceToBkgScaled(*frameData, _animationCoords);
+}
+
+void LeverControl::getLevParams(const Common::String &inputStr, Common::String &parameter, Common::String &values) {
+ const char *chrs = inputStr.c_str();
+ uint lbr;
+
+ for (lbr = 0; lbr < inputStr.size(); lbr++)
+ if (chrs[lbr] == ':')
+ break;
+
+ if (lbr >= inputStr.size())
+ return;
+
+ uint rbr;
+
+ for (rbr = lbr + 1; rbr < inputStr.size(); rbr++)
+ if (chrs[rbr] == '~')
+ break;
+
+ if (rbr >= inputStr.size())
+ return;
- _engine->getRenderManager()->copyRectToWorkingWindow(frameData, x, y, width, width, height);
+ parameter = Common::String(chrs, chrs + lbr);
+ values = Common::String(chrs + lbr + 1, chrs + rbr);
}
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h
index 49e4fd3806..37d4d3bd8d 100644
--- a/engines/zvision/scripting/controls/lever_control.h
+++ b/engines/zvision/scripting/controls/lever_control.h
@@ -28,11 +28,10 @@
#include "common/list.h"
#include "common/rect.h"
-
namespace ZVision {
class ZorkAVIDecoder;
-class RlfAnimation;
+class MetaAnimation;
class LeverControl : public Control {
public:
@@ -40,10 +39,6 @@ public:
~LeverControl();
private:
- enum FileType {
- RLF = 1,
- AVI = 2
- };
struct Direction {
Direction(uint a, uint t) : angle(a), toFrame(t) {}
@@ -64,13 +59,9 @@ private:
};
private:
- union {
- RlfAnimation *rlf;
- ZorkAVIDecoder *avi;
- } _animation;
- FileType _fileType;
+ MetaAnimation *_animation;
- Common::String _cursorName;
+ int _cursor;
Common::Rect _animationCoords;
bool _mirrored;
uint _frameCount;
@@ -88,8 +79,8 @@ private:
uint32 _accumulatedTime;
public:
- void onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
- void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
bool process(uint32 deltaTimeInMillis);
@@ -120,6 +111,7 @@ private:
*/
static int calculateVectorAngle(const Common::Point &pointOne, const Common::Point &pointTwo);
void renderFrame(uint frameNumber);
+ void getLevParams(const Common::String &inputStr, Common::String &parameter, Common::String &values);
};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/paint_control.cpp b/engines/zvision/scripting/controls/paint_control.cpp
new file mode 100644
index 0000000000..9bad6f2c58
--- /dev/null
+++ b/engines/zvision/scripting/controls/paint_control.cpp
@@ -0,0 +1,214 @@
+/* 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 "zvision/scripting/controls/paint_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+namespace ZVision {
+
+PaintControl::PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_PAINT) {
+
+ _cursor = CursorIndex_Active;
+ _paint = NULL;
+ _bkg = NULL;
+ _brush = NULL;
+ _colorKey = 0;
+ _mouseDown = false;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _rectangle = Common::Rect(x, y, width + x, height + y);
+ } else if (param.matchString("cursor", true)) {
+ _cursor = _engine->getCursorManager()->getCursorId(values);
+ } else if (param.matchString("brush_file", true)) {
+ _brush = _engine->getRenderManager()->loadImage(values, false);
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
+ } else if (param.matchString("paint_file", true)) {
+ _paint = _engine->getRenderManager()->loadImage(values, false);
+ } else if (param.matchString("eligible_objects", true)) {
+ char buf[256];
+ memset(buf, 0, 256);
+ strcpy(buf, values.c_str());
+
+ char *curpos = buf;
+ char *strend = buf + strlen(buf);
+ while (true) {
+ char *st = curpos;
+
+ if (st >= strend)
+ break;
+
+ while (*curpos != ' ' && curpos < strend)
+ curpos++;
+
+ *curpos = 0;
+ curpos++;
+
+ int obj = atoi(st);
+
+ _eligibleObjects.push_back(obj);
+ }
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+
+ if (_paint) {
+ _colorKey = _paint->format.RGBToColor(255, 0, 255);
+ _bkg = new Graphics::Surface;
+ _bkg->create(_rectangle.width(), _rectangle.height(), _paint->format);
+ _bkg->fillRect(Common::Rect(_rectangle.width(), _rectangle.height()), _colorKey);
+
+ Graphics::Surface *tmp = new Graphics::Surface;
+ tmp->create(_rectangle.width(), _rectangle.height(), _paint->format);
+ _engine->getRenderManager()->blitSurfaceToSurface(*_paint, _rectangle, *tmp, 0, 0);
+ _paint->free();
+ delete _paint;
+ _paint = tmp;
+ }
+}
+
+PaintControl::~PaintControl() {
+ // Clear the state value back to 0
+ //_engine->getScriptManager()->setStateValue(_key, 0);
+ if (_paint)
+ delete _paint;
+ if (_brush)
+ delete _brush;
+ if (_bkg)
+ delete _bkg;
+}
+
+bool PaintControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ _mouseDown = false;
+
+ return false;
+}
+
+bool PaintControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_rectangle.contains(backgroundImageSpacePos)) {
+ int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
+
+ if (eligeblity(mouseItem)) {
+ setVenus();
+ _mouseDown = true;
+ }
+ }
+
+ return false;
+}
+
+bool PaintControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_rectangle.contains(backgroundImageSpacePos)) {
+ int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
+
+ if (eligeblity(mouseItem)) {
+ _engine->getCursorManager()->changeCursor(_cursor);
+
+ if (_mouseDown) {
+ Common::Rect bkgRect = paint(backgroundImageSpacePos);
+ if (!bkgRect.isEmpty()) {
+ Common::Rect imgRect = bkgRect;
+ imgRect.translate(-_rectangle.left, -_rectangle.top);
+
+ Graphics::Surface imgUpdate = _bkg->getSubArea(imgRect);
+
+ _engine->getRenderManager()->blitSurfaceToBkg(imgUpdate, bkgRect.left, bkgRect.top, _colorKey);
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool PaintControl::eligeblity(int itemId) {
+ for (Common::List<int>::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++)
+ if (*it == itemId)
+ return true;
+ return false;
+}
+
+Common::Rect PaintControl::paint(const Common::Point &point) {
+ Common::Rect paintRect = Common::Rect(_brush->w, _brush->h);
+ paintRect.moveTo(point);
+ paintRect.clip(_rectangle);
+
+ if (!paintRect.isEmpty()) {
+ Common::Rect brushRect = paintRect;
+ brushRect.translate(-point.x, -point.y);
+
+ Common::Rect bkgRect = paintRect;
+ bkgRect.translate(-_rectangle.left, -_rectangle.top);
+
+ for (int yy = 0; yy < brushRect.height(); yy++) {
+ uint16 *mask = (uint16 *)_brush->getBasePtr(brushRect.left, brushRect.top + yy);
+ uint16 *from = (uint16 *)_paint->getBasePtr(bkgRect.left, bkgRect.top + yy);
+ uint16 *to = (uint16 *)_bkg->getBasePtr(bkgRect.left, bkgRect.top + yy);
+ for (int xx = 0; xx < brushRect.width(); xx++) {
+ if (*mask != 0)
+ *(to + xx) = *(from + xx);
+
+ mask++;
+ }
+ }
+
+ }
+ return paintRect;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/paint_control.h b/engines/zvision/scripting/controls/paint_control.h
new file mode 100644
index 0000000000..8097290ac2
--- /dev/null
+++ b/engines/zvision/scripting/controls/paint_control.h
@@ -0,0 +1,91 @@
+/* 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 ZVISION_PAINT_CONTROL_H
+#define ZVISION_PAINT_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/list.h"
+
+namespace ZVision {
+
+class PaintControl : public Control {
+public:
+ PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~PaintControl();
+
+ /**
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+
+ /**
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
+ *
+ * @param engine The base engine
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+
+ bool process(uint32 deltaTimeInMillis) {
+ return false;
+ };
+
+private:
+ /**
+ * The area that will trigger the event
+ * This is in image space coordinates, NOT screen space
+ */
+
+ uint32 _colorKey;
+
+ Graphics::Surface *_paint;
+ Graphics::Surface *_bkg;
+ Graphics::Surface *_brush;
+
+ Common::List<int> _eligibleObjects;
+
+ int _cursor;
+ Common::Rect _rectangle;
+
+ bool _mouseDown;
+
+ bool eligeblity(int itemId);
+ Common::Rect paint(const Common::Point &point);
+
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/push_toggle_control.cpp b/engines/zvision/scripting/controls/push_toggle_control.cpp
index 82736b7576..c5ec070899 100644
--- a/engines/zvision/scripting/controls/push_toggle_control.cpp
+++ b/engines/zvision/scripting/controls/push_toggle_control.cpp
@@ -31,68 +31,117 @@
#include "common/stream.h"
-
namespace ZVision {
PushToggleControl::PushToggleControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
- : Control(engine, key) {
+ : Control(engine, key, CONTROL_PUSHTGL),
+ _countTo(2),
+ _event(Common::EVENT_LBUTTONUP) {
+
+ _hotspots.clear();
+
// Loop until we find the closing brace
Common::String line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
while (!stream.eos() && !line.contains('}')) {
- if (line.matchString("*_hotspot*", true)) {
+ if (param.matchString("*_hotspot", true)) {
uint x;
uint y;
uint width;
uint height;
- sscanf(line.c_str(), "%*[^(](%u,%u,%u,%u)", &x, &y, &width, &height);
-
- _hotspot = Common::Rect(x, y, x + width, y + height);
- } else if (line.matchString("cursor*", true)) {
- char nameBuffer[25];
-
- sscanf(line.c_str(), "%*[^(](%25[^)])", nameBuffer);
-
- _hoverCursor = Common::String(nameBuffer);
+ sscanf(values.c_str(), "%u,%u,%u,%u", &x, &y, &width, &height);
+
+ _hotspots.push_back(Common::Rect(x, y, x + width + 1, y + height + 1));
+ } else if (param.matchString("cursor", true)) {
+ _cursor = _engine->getCursorManager()->getCursorId(values);
+ } else if (param.matchString("animation", true)) {
+ // Not used
+ } else if (param.matchString("sound", true)) {
+ // Not used
+ } else if (param.matchString("count_to", true)) {
+ sscanf(values.c_str(), "%u", &_countTo);
+ } else if (param.matchString("mouse_event", true)) {
+ if (values.equalsIgnoreCase("up")) {
+ _event = Common::EVENT_LBUTTONUP;
+ } else if (values.equalsIgnoreCase("down")) {
+ _event = Common::EVENT_LBUTTONDOWN;
+ } else if (values.equalsIgnoreCase("double")) {
+ // Not used
+ }
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
}
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
}
- if (_hotspot.isEmpty() || _hoverCursor.empty()) {
- warning("Push_toggle cursor %u was parsed incorrectly", key);
+ if (_hotspots.size() == 0) {
+ warning("Push_toggle %u was parsed incorrectly", key);
}
}
PushToggleControl::~PushToggleControl() {
- // Clear the state value back to 0
- _engine->getScriptManager()->setStateValue(_key, 0);
+ _hotspots.clear();
}
-void PushToggleControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_enabled) {
- return;
+bool PushToggleControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_event != Common::EVENT_LBUTTONUP)
+ return false;
+
+ if (contain(backgroundImageSpacePos)) {
+ setVenus();
+ int32 val = _engine->getScriptManager()->getStateValue(_key);
+ val = (val + 1) % _countTo;
+ _engine->getScriptManager()->setStateValue(_key, val);
+ return true;
}
-
- if (_hotspot.contains(backgroundImageSpacePos)) {
- _engine->getScriptManager()->setStateValue(_key, 1);
+ return false;
+}
+
+bool PushToggleControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_event != Common::EVENT_LBUTTONDOWN)
+ return false;
+
+ if (contain(backgroundImageSpacePos)) {
+ setVenus();
+ int32 val = _engine->getScriptManager()->getStateValue(_key);
+ val = (val + 1) % _countTo;
+ _engine->getScriptManager()->setStateValue(_key, val);
+ return true;
}
+ return false;
}
bool PushToggleControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- if (!_enabled) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
return false;
- }
-
- if (_hotspot.contains(backgroundImageSpacePos)) {
- _engine->getCursorManager()->changeCursor(_hoverCursor);
+
+ if (contain(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(_cursor);
return true;
}
return false;
}
+bool PushToggleControl::contain(const Common::Point &point) {
+ for (uint i = 0; i < _hotspots.size(); i++)
+ if (_hotspots[i].contains(point))
+ return true;
+ return false;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/push_toggle_control.h b/engines/zvision/scripting/controls/push_toggle_control.h
index 3854fc2005..9444c77cb6 100644
--- a/engines/zvision/scripting/controls/push_toggle_control.h
+++ b/engines/zvision/scripting/controls/push_toggle_control.h
@@ -26,7 +26,8 @@
#include "zvision/scripting/control.h"
#include "common/rect.h"
-
+#include "common/events.h"
+#include "common/array.h"
namespace ZVision {
@@ -36,12 +37,19 @@ public:
~PushToggleControl();
/**
+ * Called when LeftMouse is pushed. Default is NOP.
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ bool onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
* Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
*
* @param screenSpacePos The position of the mouse in screen space
* @param backgroundImageSpacePos The position of the mouse in background image space
*/
- void onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
/**
* Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
*
@@ -57,9 +65,15 @@ private:
* The area that will trigger the event
* This is in image space coordinates, NOT screen space
*/
- Common::Rect _hotspot;
+ Common::Array<Common::Rect> _hotspots;
/** The cursor to use when hovering over _hotspot */
- Common::String _hoverCursor;
+ int _cursor;
+ /** Button maximal values count */
+ uint _countTo;
+
+ Common::EventType _event;
+
+ bool contain(const Common::Point &point);
};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/safe_control.cpp b/engines/zvision/scripting/controls/safe_control.cpp
new file mode 100644
index 0000000000..3ad5d3a8ae
--- /dev/null
+++ b/engines/zvision/scripting/controls/safe_control.cpp
@@ -0,0 +1,204 @@
+/* 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 "zvision/scripting/controls/safe_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/animation/meta_animation.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "common/tokenizer.h"
+#include "common/system.h"
+
+#include "graphics/surface.h"
+
+namespace ZVision {
+
+SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_SAFE) {
+ _statesCount = 0;
+ _curState = 0;
+ _animation = NULL;
+ _innerRaduis = 0;
+ _innerRadiusSqr = 0;
+ _outerRadius = 0;
+ _outerRadiusSqr = 0;
+ _zeroPointer = 0;
+ _startPointer = 0;
+ _curFrame = -1;
+ _targetFrame = 0;
+ _frameTime = 0;
+ _lastRenderedFrame = -1;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("animation", true)) {
+ _animation = new MetaAnimation(values, _engine);
+ } else if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _rectangle = Common::Rect(x, y, width, height);
+ } else if (param.matchString("num_states", true)) {
+ _statesCount = atoi(values.c_str());
+ } else if (param.matchString("center", true)) {
+ int x;
+ int y;
+
+ sscanf(values.c_str(), "%d %d", &x, &y);
+ _center = Common::Point(x, y);
+ } else if (param.matchString("dial_inner_radius", true)) {
+ _innerRaduis = atoi(values.c_str());
+ _innerRadiusSqr = _innerRaduis * _innerRaduis;
+ } else if (param.matchString("radius", true)) {
+ _outerRadius = atoi(values.c_str());
+ _outerRadiusSqr = _outerRadius * _outerRadius;
+ } else if (param.matchString("zero_radians_offset", true)) {
+ _zeroPointer = atoi(values.c_str());
+ } else if (param.matchString("pointer_offset", true)) {
+ _startPointer = atoi(values.c_str());
+ _curState = _startPointer;
+ } else if (param.matchString("cursor", true)) {
+ // Not used
+ } else if (param.matchString("mirrored", true)) {
+ // Not used
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+ renderFrame(_curState);
+}
+
+SafeControl::~SafeControl() {
+ if (_animation)
+ delete _animation;
+
+}
+
+void SafeControl::renderFrame(uint frameNumber) {
+ if (frameNumber == 0) {
+ _lastRenderedFrame = frameNumber;
+ } else if ((int16)frameNumber < _lastRenderedFrame) {
+ _lastRenderedFrame = frameNumber;
+ frameNumber = (_statesCount * 2) - frameNumber;
+ } else {
+ _lastRenderedFrame = frameNumber;
+ }
+
+ const Graphics::Surface *frameData;
+ int x = _rectangle.left;
+ int y = _rectangle.top;
+
+ frameData = _animation->getFrameData(frameNumber);
+ if (frameData)
+ _engine->getRenderManager()->blitSurfaceToBkg(*frameData, x, y);
+}
+
+bool SafeControl::process(uint32 deltaTimeInMillis) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_curFrame != _targetFrame) {
+ _frameTime -= deltaTimeInMillis;
+
+ if (_frameTime <= 0) {
+ if (_curFrame < _targetFrame) {
+ _curFrame++;
+ renderFrame(_curFrame);
+ } else if (_curFrame > _targetFrame) {
+ _curFrame--;
+ renderFrame(_curFrame);
+ }
+ _frameTime = _animation->frameTime();
+ }
+ }
+ return false;
+}
+
+bool SafeControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_rectangle.contains(backgroundImageSpacePos)) {
+ int32 mR = backgroundImageSpacePos.sqrDist(_center);
+ if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
+ _engine->getCursorManager()->changeCursor(CursorIndex_Active);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SafeControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_rectangle.contains(backgroundImageSpacePos)) {
+ int32 mR = backgroundImageSpacePos.sqrDist(_center);
+ if (mR <= _outerRadiusSqr && mR >= _innerRadiusSqr) {
+ setVenus();
+
+ Common::Point tmp = backgroundImageSpacePos - _center;
+
+ float dd = atan2((float)tmp.x, (float)tmp.y) * 57.29578;
+
+ int16 dp_state = 360 / _statesCount;
+
+ int16 m_state = (_statesCount - ((((int16)dd + 540) % 360) / dp_state)) % _statesCount;
+
+ int16 tmp2 = (m_state + _curState - _zeroPointer + _statesCount - 1) % _statesCount;
+
+ _curFrame = (_curState + _statesCount - _startPointer) % _statesCount;
+
+ _curState = (_statesCount * 2 + tmp2) % _statesCount;
+
+ _targetFrame = (_curState + _statesCount - _startPointer) % _statesCount;
+
+ _engine->getScriptManager()->setStateValue(_key, _curState);
+ return true;
+ }
+ }
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/safe_control.h b/engines/zvision/scripting/controls/safe_control.h
new file mode 100644
index 0000000000..e32ca97b70
--- /dev/null
+++ b/engines/zvision/scripting/controls/safe_control.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.
+ *
+ */
+
+#ifndef ZVISION_SAFE_CONTROL_H
+#define ZVISION_SAFE_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/list.h"
+#include "common/rect.h"
+
+namespace ZVision {
+
+class ZorkAVIDecoder;
+class MetaAnimation;
+
+class SafeControl : public Control {
+public:
+ SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~SafeControl();
+
+private:
+ int16 _statesCount;
+ int16 _curState;
+ MetaAnimation *_animation;
+ Common::Point _center;
+ Common::Rect _rectangle;
+ int16 _innerRaduis;
+ int32 _innerRadiusSqr;
+ int16 _outerRadius;
+ int32 _outerRadiusSqr;
+ int16 _zeroPointer;
+ int16 _startPointer;
+ int16 _curFrame;
+ int16 _targetFrame;
+ int32 _frameTime;
+
+ int16 _lastRenderedFrame;
+
+public:
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ void renderFrame(uint frameNumber);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp
new file mode 100644
index 0000000000..d773b5fc6f
--- /dev/null
+++ b/engines/zvision/scripting/controls/save_control.cpp
@@ -0,0 +1,124 @@
+/* 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 "zvision/scripting/controls/input_control.h"
+#include "zvision/scripting/controls/save_control.h"
+#include "zvision/utility/utility.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/text/string_manager.h"
+
+#include "zvision/core/save_manager.h"
+
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace ZVision {
+
+SaveControl::SaveControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_SAVE),
+ _saveControl(false) {
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("savebox", true)) {
+ int saveId;
+ int inputId;
+
+ sscanf(values.c_str(), "%d %d", &saveId, &inputId);
+ saveElement elmnt;
+ elmnt.inputKey = inputId;
+ elmnt.saveId = saveId;
+ elmnt.exist = false;
+ _inputs.push_back(elmnt);
+ } else if (param.matchString("control_type", true)) {
+ if (values.contains("save"))
+ _saveControl = true;
+ else
+ _saveControl = false;
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+
+ for (saveElmntList::iterator iter = _inputs.begin(); iter != _inputs.end(); ++iter) {
+ Control *ctrl = _engine->getScriptManager()->getControl(iter->inputKey);
+ if (ctrl && ctrl->getType() == Control::CONTROL_INPUT) {
+ InputControl *inp = (InputControl *)ctrl;
+ inp->setReadOnly(!_saveControl);
+ Common::SeekableReadStream *save = _engine->getSaveManager()->getSlotFile(iter->saveId);
+ if (save) {
+ SaveGameHeader header;
+ _engine->getSaveManager()->readSaveGameHeader(save, header);
+ delete save;
+ inp->setText(header.saveName);
+ iter->exist = true;
+ }
+ }
+ }
+}
+
+bool SaveControl::process(uint32 deltaTimeInMillis) {
+ for (saveElmntList::iterator iter = _inputs.begin(); iter != _inputs.end(); ++iter) {
+ Control *ctrl = _engine->getScriptManager()->getControl(iter->inputKey);
+ if (ctrl && ctrl->getType() == Control::CONTROL_INPUT) {
+ InputControl *inp = (InputControl *)ctrl;
+ if (inp->enterPress()) {
+ if (_saveControl) {
+ if (inp->getText().size() > 0) {
+ bool toSave = true;
+ if (iter->exist)
+ if (!_engine->askQuestion(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEXIST)))
+ toSave = false;
+
+ if (toSave) {
+ // FIXME: At this point, the screen shows the save control, so the save game thumbnails will always
+ // show the save control
+ _engine->getSaveManager()->saveGameBuffered(iter->saveId, inp->getText());
+ _engine->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000);
+ _engine->getScriptManager()->changeLocation(_engine->getScriptManager()->getLastMenuLocation());
+ }
+ } else {
+ _engine->timedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVEEMPTY), 2000);
+ }
+ } else {
+ _engine->getSaveManager()->loadGame(iter->saveId);
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/save_control.h b/engines/zvision/scripting/controls/save_control.h
new file mode 100644
index 0000000000..cdc50eb54d
--- /dev/null
+++ b/engines/zvision/scripting/controls/save_control.h
@@ -0,0 +1,55 @@
+/* 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 ZVISION_SAVE_CONTROL_H
+#define ZVISION_SAVE_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "common/list.h"
+
+namespace ZVision {
+
+class SaveControl : public Control {
+public:
+ SaveControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+
+private:
+ struct saveElement {
+ int saveId;
+ int inputKey;
+ bool exist;
+ };
+ typedef Common::List<saveElement> saveElmntList;
+ saveElmntList _inputs;
+
+ bool _saveControl;
+
+public:
+
+ bool process(uint32 deltaTimeInMillis);
+
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/slot_control.cpp b/engines/zvision/scripting/controls/slot_control.cpp
new file mode 100644
index 0000000000..1d83b44392
--- /dev/null
+++ b/engines/zvision/scripting/controls/slot_control.cpp
@@ -0,0 +1,218 @@
+/* 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 "zvision/scripting/controls/slot_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+namespace ZVision {
+
+SlotControl::SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_SLOT) {
+
+ _renderedItem = 0;
+ _bkg = NULL;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("hotspot", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _hotspot = Common::Rect(x, y, width, height);
+ } else if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _rectangle = Common::Rect(x, y, width, height);
+ } else if (param.matchString("cursor", true)) {
+ _cursor = _engine->getCursorManager()->getCursorId(values);
+ } else if (param.matchString("distance_id", true)) {
+ sscanf(values.c_str(), "%c", &_distanceId);
+ } else if (param.matchString("venus_id", true)) {
+ _venusId = atoi(values.c_str());
+ } else if (param.matchString("eligible_objects", true)) {
+ char buf[256];
+ memset(buf, 0, 256);
+ strcpy(buf, values.c_str());
+
+ char *curpos = buf;
+ char *strend = buf + strlen(buf);
+ while (true) {
+ char *st = curpos;
+
+ if (st >= strend)
+ break;
+
+ while (*curpos != ' ' && curpos < strend)
+ curpos++;
+
+ *curpos = 0;
+ curpos++;
+
+ int obj = atoi(st);
+
+ _eligibleObjects.push_back(obj);
+ }
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+
+ if (_hotspot.isEmpty() || _rectangle.isEmpty()) {
+ warning("Slot %u was parsed incorrectly", key);
+ }
+}
+
+SlotControl::~SlotControl() {
+ // Clear the state value back to 0
+ //_engine->getScriptManager()->setStateValue(_key, 0);
+
+ if (_bkg)
+ delete _bkg;
+}
+
+bool SlotControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ setVenus();
+
+ int item = _engine->getScriptManager()->getStateValue(_key);
+ int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
+ if (item != 0) {
+ if (mouseItem != 0) {
+ if (eligeblity(mouseItem)) {
+ _engine->getScriptManager()->inventoryDrop(mouseItem);
+ _engine->getScriptManager()->inventoryAdd(item);
+ _engine->getScriptManager()->setStateValue(_key, mouseItem);
+ }
+ } else {
+ _engine->getScriptManager()->inventoryAdd(item);
+ _engine->getScriptManager()->setStateValue(_key, 0);
+ }
+ } else if (mouseItem == 0) {
+ if (eligeblity(0)) {
+ _engine->getScriptManager()->inventoryDrop(0);
+ _engine->getScriptManager()->setStateValue(_key, 0);
+ }
+ } else if (eligeblity(mouseItem)) {
+ _engine->getScriptManager()->setStateValue(_key, mouseItem);
+ _engine->getScriptManager()->inventoryDrop(mouseItem);
+ }
+ }
+ return false;
+}
+
+bool SlotControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(_cursor);
+ return true;
+ }
+
+ return false;
+}
+
+bool SlotControl::process(uint32 deltaTimeInMillis) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_engine->canRender()) {
+ int curItem = _engine->getScriptManager()->getStateValue(_key);
+ if (curItem != _renderedItem) {
+ if (_renderedItem != 0 && curItem == 0) {
+ _engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
+ _renderedItem = curItem;
+ } else {
+ if (_renderedItem == 0) {
+ if (_bkg)
+ delete _bkg;
+
+ _bkg = _engine->getRenderManager()->getBkgRect(_rectangle);
+ } else {
+ _engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
+ }
+
+ char buf[16];
+ if (_engine->getGameId() == GID_NEMESIS)
+ sprintf(buf, "%d%cobj.tga", curItem, _distanceId);
+ else
+ sprintf(buf, "g0z%cu%2.2x1.tga", _distanceId, curItem);
+
+ Graphics::Surface *srf = _engine->getRenderManager()->loadImage(buf);
+
+ int16 drawx = _rectangle.left;
+ int16 drawy = _rectangle.top;
+
+ if (_rectangle.width() > srf->w)
+ drawx = _rectangle.left + (_rectangle.width() - srf->w) / 2;
+
+ if (_rectangle.height() > srf->h)
+ drawy = _rectangle.top + (_rectangle.height() - srf->h) / 2;
+
+ _engine->getRenderManager()->blitSurfaceToBkg(*srf, drawx, drawy, 0);
+
+ delete srf;
+
+ _renderedItem = curItem;
+ }
+ }
+ }
+ return false;
+}
+
+bool SlotControl::eligeblity(int itemId) {
+ for (Common::List<int>::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++)
+ if (*it == itemId)
+ return true;
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/slot_control.h b/engines/zvision/scripting/controls/slot_control.h
new file mode 100644
index 0000000000..e776d99311
--- /dev/null
+++ b/engines/zvision/scripting/controls/slot_control.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_SLOT_CONTROL_H
+#define ZVISION_SLOT_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/list.h"
+
+namespace ZVision {
+
+class SlotControl : public Control {
+public:
+ SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~SlotControl();
+
+ /**
+ * Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
+ *
+ * @param engine The base engine
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ /**
+ * The area that will trigger the event
+ * This is in image space coordinates, NOT screen space
+ */
+ Common::Rect _rectangle;
+ Common::Rect _hotspot;
+
+ int _cursor;
+ char _distanceId;
+
+ int _renderedItem;
+
+ Common::List<int> _eligibleObjects;
+
+ bool eligeblity(int itemId);
+
+ Graphics::Surface *_bkg;
+
+ /** The cursor to use when hovering over _hotspot */
+ Common::String _hoverCursor;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp
new file mode 100644
index 0000000000..f0126bebc2
--- /dev/null
+++ b/engines/zvision/scripting/controls/titler_control.cpp
@@ -0,0 +1,107 @@
+/* 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 "zvision/scripting/controls/titler_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/text/text.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+namespace ZVision {
+
+TitlerControl::TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key, CONTROL_TITLER) {
+
+ _surface = NULL;
+ _curString = -1;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("string_resource_file", true)) {
+ readStringsFile(values);
+ } else if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int x2;
+ int y2;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &x2, &y2);
+
+ _rectangle = Common::Rect(x, y, x2, y2);
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+
+ if (!_rectangle.isEmpty()) {
+ _surface = new Graphics::Surface;
+ _surface->create(_rectangle.width(), _rectangle.height(), _engine->_pixelFormat);
+ _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
+ }
+}
+
+TitlerControl::~TitlerControl() {
+ if (_surface)
+ delete _surface;
+}
+
+void TitlerControl::setString(int strLine) {
+ if (strLine != _curString && strLine >= 0 && strLine < (int)_strings.size()) {
+ _surface->fillRect(Common::Rect(_surface->w, _surface->h), 0);
+ _engine->getTextRenderer()->drawTxtInOneLine(_strings[strLine], *_surface);
+ _engine->getRenderManager()->blitSurfaceToBkg(*_surface, _rectangle.left, _rectangle.top);
+ _curString = strLine;
+ }
+}
+
+void TitlerControl::readStringsFile(const Common::String &fileName) {
+ Common::File file;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("String_resource_file %s could could be opened", fileName.c_str());
+ return;
+ }
+
+ _strings.clear();
+
+ while (!file.eos()) {
+
+ Common::String line = readWideLine(file);
+ _strings.push_back(line);
+ }
+ file.close();
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/titler_control.h b/engines/zvision/scripting/controls/titler_control.h
new file mode 100644
index 0000000000..075e47c9e9
--- /dev/null
+++ b/engines/zvision/scripting/controls/titler_control.h
@@ -0,0 +1,54 @@
+/* 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 ZVISION_TITLER_CONTROL_H
+#define ZVISION_TITLER_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+
+namespace ZVision {
+
+class TitlerControl : public Control {
+public:
+ TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~TitlerControl();
+
+ void setString(int strLine);
+
+private:
+
+ Common::Array< Common::String > _strings;
+ Common::Rect _rectangle;
+ int16 _curString;
+ Graphics::Surface *_surface;
+
+ void readStringsFile(const Common::String &fileName);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/inventory.cpp b/engines/zvision/scripting/inventory.cpp
new file mode 100644
index 0000000000..76d43b200b
--- /dev/null
+++ b/engines/zvision/scripting/inventory.cpp
@@ -0,0 +1,122 @@
+/* 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 "zvision/scripting/script_manager.h"
+
+namespace ZVision {
+
+int8 ScriptManager::inventoryGetCount() {
+ return getStateValue(StateKey_Inv_Cnt_Slot);
+}
+
+void ScriptManager::inventorySetCount(int8 cnt) {
+ setStateValue(StateKey_Inv_Cnt_Slot, cnt);
+}
+
+int16 ScriptManager::inventoryGetItem(int8 id) {
+ if (id < 49 && id >= 0)
+ return getStateValue(StateKey_Inv_1_Slot + id);
+ return -1;
+}
+
+void ScriptManager::inventorySetItem(int8 id, int16 item) {
+ if (id < 49 && id >= 0)
+ setStateValue(StateKey_Inv_1_Slot + id, item);
+}
+
+void ScriptManager::inventoryAdd(int16 item) {
+ int8 cnt = inventoryGetCount();
+
+ if (cnt < 49) {
+ bool notExist = true;
+
+ if (cnt == 0) {
+ inventorySetItem(0, 0);
+ inventorySetCount(1); // we needed empty item for cycle code
+ cnt = 1;
+ }
+
+ for (int8 cur = 0; cur < cnt; cur++)
+ if (inventoryGetItem(cur) == item) {
+ notExist = false;
+ break;
+ }
+
+ if (notExist) {
+ for (int8 i = cnt; i > 0; i--)
+ inventorySetItem(i, inventoryGetItem(i - 1));
+
+ inventorySetItem(0, item);
+
+ setStateValue(StateKey_InventoryItem, item);
+
+ inventorySetCount(cnt + 1);
+ }
+ }
+}
+
+void ScriptManager::inventoryDrop(int16 item) {
+ int8 itemCount = inventoryGetCount();
+
+ // if items in inventory > 0
+ if (itemCount != 0) {
+ int8 index = 0;
+
+ // finding needed item
+ while (index < itemCount) {
+ if (inventoryGetItem(index) == item)
+ break;
+
+ index++;
+ }
+
+ // if item in the inventory
+ if (itemCount != index) {
+ // shift all items left with rewrite founded item
+ for (int8 v = index; v < itemCount - 1 ; v++)
+ inventorySetItem(v, inventoryGetItem(v + 1));
+
+ // del last item
+ inventorySetItem(itemCount - 1, 0);
+ inventorySetCount(inventoryGetCount() - 1);
+
+ setStateValue(StateKey_InventoryItem, inventoryGetItem(0));
+ }
+ }
+}
+void ScriptManager::inventoryCycle() {
+ int8 itemCount = inventoryGetCount();
+ int8 curItem = inventoryGetItem(0);
+ if (itemCount > 1) {
+ for (int8 i = 0; i < itemCount - 1; i++)
+ inventorySetItem(i, inventoryGetItem(i + 1));
+
+ inventorySetItem(itemCount - 1, curItem);
+
+ setStateValue(StateKey_InventoryItem, inventoryGetItem(0));
+
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/puzzle.h b/engines/zvision/scripting/puzzle.h
index ee9ce521c9..4123880835 100644
--- a/engines/zvision/scripting/puzzle.h
+++ b/engines/zvision/scripting/puzzle.h
@@ -8,12 +8,12 @@
* 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.
@@ -28,7 +28,6 @@
#include "common/list.h"
#include "common/ptr.h"
-
namespace ZVision {
struct Puzzle {
@@ -63,10 +62,17 @@ struct Puzzle {
bool argumentIsAKey;
};
+ enum StateFlags {
+ ONCE_PER_INST = 0x01,
+ DISABLED = 0x02,
+ DO_ME_NOW = 0x04
+ };
+
uint32 key;
Common::List<Common::List <CriteriaEntry> > criteriaList;
// This has to be list of pointers because ResultAction is abstract
Common::List<ResultAction *> resultActions;
+ bool addedBySetState;
};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp
index 753ce4ac6a..f97eed6b75 100644
--- a/engines/zvision/scripting/scr_file_handling.cpp
+++ b/engines/zvision/scripting/scr_file_handling.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -22,6 +22,7 @@
#include "common/scummsys.h"
+#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/utility/utility.h"
@@ -29,22 +30,29 @@
#include "zvision/scripting/actions.h"
#include "zvision/scripting/controls/push_toggle_control.h"
#include "zvision/scripting/controls/lever_control.h"
+#include "zvision/scripting/controls/slot_control.h"
+#include "zvision/scripting/controls/save_control.h"
+#include "zvision/scripting/controls/input_control.h"
+#include "zvision/scripting/controls/safe_control.h"
+#include "zvision/scripting/controls/hotmov_control.h"
+#include "zvision/scripting/controls/fist_control.h"
+#include "zvision/scripting/controls/paint_control.h"
+#include "zvision/scripting/controls/titler_control.h"
#include "common/textconsole.h"
#include "common/file.h"
#include "common/tokenizer.h"
-
namespace ZVision {
-void ScriptManager::parseScrFile(const Common::String &fileName, bool isGlobal) {
+void ScriptManager::parseScrFile(const Common::String &fileName, ScriptScope &scope) {
Common::File file;
- if (!file.open(fileName)) {
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
warning("Script file not found: %s", fileName.c_str());
return;
}
- while(!file.eos()) {
+ while (!file.eos()) {
Common::String line = file.readLine();
if (file.err()) {
warning("Error parsing scr file: %s", fileName.c_str());
@@ -57,18 +65,19 @@ void ScriptManager::parseScrFile(const Common::String &fileName, bool isGlobal)
if (line.matchString("puzzle:*", true)) {
Puzzle *puzzle = new Puzzle();
- sscanf(line.c_str(),"puzzle:%u",&(puzzle->key));
-
+ sscanf(line.c_str(), "puzzle:%u", &(puzzle->key));
+ if (getStateFlag(puzzle->key) & Puzzle::ONCE_PER_INST)
+ setStateValue(puzzle->key, 0);
parsePuzzle(puzzle, file);
- if (isGlobal) {
- _globalPuzzles.push_back(puzzle);
- } else {
- _activePuzzles.push_back(puzzle);
- }
+ scope.puzzles.push_back(puzzle);
+
} else if (line.matchString("control:*", true)) {
- parseControl(line, file);
+ Control *ctrl = parseControl(line, file);
+ if (ctrl)
+ scope.controls.push_back(ctrl);
}
}
+ scope.procCount = 0;
}
void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stream) {
@@ -81,12 +90,14 @@ void ScriptManager::parsePuzzle(Puzzle *puzzle, Common::SeekableReadStream &stre
} else if (line.matchString("results {", true)) {
parseResults(stream, puzzle->resultActions);
} else if (line.matchString("flags {", true)) {
- setStateFlags(puzzle->key, parseFlags(stream));
+ setStateFlag(puzzle->key, parseFlags(stream));
}
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
}
+
+ puzzle->addedBySetState = 0;
}
bool ScriptManager::parseCriteria(Common::SeekableReadStream &stream, Common::List<Common::List<Puzzle::CriteriaEntry> > &criteriaList) const {
@@ -148,103 +159,148 @@ void ScriptManager::parseResults(Common::SeekableReadStream &stream, Common::Lis
// Loop until we find the closing brace
Common::String line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ line.toLowercase();
// TODO: Re-order the if-then statements in order of highest occurrence
while (!stream.eos() && !line.contains('}')) {
if (line.empty()) {
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
-
+ line.toLowercase();
continue;
}
- // Parse for the action type
- if (line.matchString("*:add*", true)) {
- actionList.push_back(new ActionAdd(line));
- } else if (line.matchString("*:animplay*", true)) {
- actionList.push_back(new ActionPlayAnimation(line));
- } else if (line.matchString("*:animpreload*", true)) {
- actionList.push_back(new ActionPreloadAnimation(line));
- } else if (line.matchString("*:animunload*", true)) {
- //actionList.push_back(new ActionUnloadAnimation(line));
- } else if (line.matchString("*:attenuate*", true)) {
- // TODO: Implement ActionAttenuate
- } else if (line.matchString("*:assign*", true)) {
- actionList.push_back(new ActionAssign(line));
- } else if (line.matchString("*:change_location*", true)) {
- actionList.push_back(new ActionChangeLocation(line));
- } else if (line.matchString("*:crossfade*", true)) {
- // TODO: Implement ActionCrossfade
- } else if (line.matchString("*:debug*", true)) {
- // TODO: Implement ActionDebug
- } else if (line.matchString("*:delay_render*", true)) {
- // TODO: Implement ActionDelayRender
- } else if (line.matchString("*:disable_control*", true)) {
- actionList.push_back(new ActionDisableControl(line));
- } else if (line.matchString("*:disable_venus*", true)) {
- // TODO: Implement ActionDisableVenus
- } else if (line.matchString("*:display_message*", true)) {
- // TODO: Implement ActionDisplayMessage
- } else if (line.matchString("*:dissolve*", true)) {
- // TODO: Implement ActionDissolve
- } else if (line.matchString("*:distort*", true)) {
- // TODO: Implement ActionDistort
- } else if (line.matchString("*:enable_control*", true)) {
- actionList.push_back(new ActionEnableControl(line));
- } else if (line.matchString("*:flush_mouse_events*", true)) {
- // TODO: Implement ActionFlushMouseEvents
- } else if (line.matchString("*:inventory*", true)) {
- // TODO: Implement ActionInventory
- } else if (line.matchString("*:kill*", true)) {
- // TODO: Implement ActionKill
- } else if (line.matchString("*:menu_bar_enable*", true)) {
- // TODO: Implement ActionMenuBarEnable
- } else if (line.matchString("*:music*", true)) {
- actionList.push_back(new ActionMusic(line));
- } else if (line.matchString("*:pan_track*", true)) {
- // TODO: Implement ActionPanTrack
- } else if (line.matchString("*:playpreload*", true)) {
- actionList.push_back(new ActionPlayPreloadAnimation(line));
- } else if (line.matchString("*:preferences*", true)) {
- // TODO: Implement ActionPreferences
- } else if (line.matchString("*:quit*", true)) {
- actionList.push_back(new ActionQuit());
- } else if (line.matchString("*:random*", true)) {
- actionList.push_back(new ActionRandom(line));
- } else if (line.matchString("*:region*", true)) {
- // TODO: Implement ActionRegion
- } else if (line.matchString("*:restore_game*", true)) {
- // TODO: Implement ActionRestoreGame
- } else if (line.matchString("*:rotate_to*", true)) {
- // TODO: Implement ActionRotateTo
- } else if (line.matchString("*:save_game*", true)) {
- // TODO: Implement ActionSaveGame
- } else if (line.matchString("*:set_partial_screen*", true)) {
- actionList.push_back(new ActionSetPartialScreen(line));
- } else if (line.matchString("*:set_screen*", true)) {
- actionList.push_back(new ActionSetScreen(line));
- } else if (line.matchString("*:set_venus*", true)) {
- // TODO: Implement ActionSetVenus
- } else if (line.matchString("*:stop*", true)) {
- // TODO: Implement ActionStop
- } else if (line.matchString("*:streamvideo*", true)) {
- actionList.push_back(new ActionStreamVideo(line));
- } else if (line.matchString("*:syncsound*", true)) {
- // TODO: Implement ActionSyncSound
- } else if (line.matchString("*:timer*", true)) {
- actionList.push_back(new ActionTimer(line));
- } else if (line.matchString("*:ttytext*", true)) {
- // TODO: Implement ActionTTYText
- } else if (line.matchString("*:universe_music*", true)) {
- // TODO: Implement ActionUniverseMusic
- } else if (line.matchString("*:copy_file*", true)) {
- // Not used. Purposely left empty
- } else {
- warning("Unhandled result action type: %s", line.c_str());
+ const char *chrs = line.c_str();
+ uint pos;
+ for (pos = 0; pos < line.size(); pos++)
+ if (chrs[pos] == ':')
+ break;
+
+ if (pos < line.size()) {
+
+ uint startpos = pos + 1;
+
+ for (pos = startpos; pos < line.size(); pos++)
+ if (chrs[pos] == ':' || chrs[pos] == '(')
+ break;
+
+ if (pos < line.size()) {
+ int32 slot = 11;
+ Common::String args = "";
+ Common::String act(chrs + startpos, chrs + pos);
+
+ startpos = pos + 1;
+
+ if (chrs[pos] == ':') {
+ for (pos = startpos; pos < line.size(); pos++)
+ if (chrs[pos] == '(')
+ break;
+ Common::String strSlot(chrs + startpos, chrs + pos);
+ slot = atoi(strSlot.c_str());
+
+ startpos = pos + 1;
+ }
+
+ if (pos < line.size()) {
+ for (pos = startpos; pos < line.size(); pos++)
+ if (chrs[pos] == ')')
+ break;
+
+ args = Common::String(chrs + startpos, chrs + pos);
+ }
+
+ // Parse for the action type
+ if (act.matchString("add", true)) {
+ actionList.push_back(new ActionAdd(_engine, slot, args));
+ } else if (act.matchString("animplay", true)) {
+ actionList.push_back(new ActionPlayAnimation(_engine, slot, args));
+ } else if (act.matchString("animpreload", true)) {
+ actionList.push_back(new ActionPreloadAnimation(_engine, slot, args));
+ } else if (act.matchString("animunload", true)) {
+ actionList.push_back(new ActionUnloadAnimation(_engine, slot, args));
+ } else if (act.matchString("attenuate", true)) {
+ actionList.push_back(new ActionAttenuate(_engine, slot, args));
+ } else if (act.matchString("assign", true)) {
+ actionList.push_back(new ActionAssign(_engine, slot, args));
+ } else if (act.matchString("change_location", true)) {
+ actionList.push_back(new ActionChangeLocation(_engine, slot, args));
+ } else if (act.matchString("crossfade", true)) {
+ actionList.push_back(new ActionCrossfade(_engine, slot, args));
+ } else if (act.matchString("cursor", true)) {
+ actionList.push_back(new ActionCursor(_engine, slot, args));
+ } else if (act.matchString("debug", true)) {
+ // Not used. Purposely left empty
+ } else if (act.matchString("delay_render", true)) {
+ actionList.push_back(new ActionDelayRender(_engine, slot, args));
+ } else if (act.matchString("disable_control", true)) {
+ actionList.push_back(new ActionDisableControl(_engine, slot, args));
+ } else if (act.matchString("disable_venus", true)) {
+ actionList.push_back(new ActionDisableVenus(_engine, slot, args));
+ } else if (act.matchString("display_message", true)) {
+ actionList.push_back(new ActionDisplayMessage(_engine, slot, args));
+ } else if (act.matchString("dissolve", true)) {
+ actionList.push_back(new ActionDissolve(_engine));
+ } else if (act.matchString("distort", true)) {
+ actionList.push_back(new ActionDistort(_engine, slot, args));
+ } else if (act.matchString("enable_control", true)) {
+ actionList.push_back(new ActionEnableControl(_engine, slot, args));
+ } else if (act.matchString("flush_mouse_events", true)) {
+ actionList.push_back(new ActionFlushMouseEvents(_engine, slot));
+ } else if (act.matchString("inventory", true)) {
+ actionList.push_back(new ActionInventory(_engine, slot, args));
+ } else if (act.matchString("kill", true)) {
+ actionList.push_back(new ActionKill(_engine, slot, args));
+ } else if (act.matchString("menu_bar_enable", true)) {
+ actionList.push_back(new ActionMenuBarEnable(_engine, slot, args));
+ } else if (act.matchString("music", true)) {
+ actionList.push_back(new ActionMusic(_engine, slot, args, false));
+ } else if (act.matchString("pan_track", true)) {
+ actionList.push_back(new ActionPanTrack(_engine, slot, args));
+ } else if (act.matchString("playpreload", true)) {
+ actionList.push_back(new ActionPlayPreloadAnimation(_engine, slot, args));
+ } else if (act.matchString("preferences", true)) {
+ actionList.push_back(new ActionPreferences(_engine, slot, args));
+ } else if (act.matchString("quit", true)) {
+ actionList.push_back(new ActionQuit(_engine, slot));
+ } else if (act.matchString("random", true)) {
+ actionList.push_back(new ActionRandom(_engine, slot, args));
+ } else if (act.matchString("region", true)) {
+ actionList.push_back(new ActionRegion(_engine, slot, args));
+ } else if (act.matchString("restore_game", true)) {
+ actionList.push_back(new ActionRestoreGame(_engine, slot, args));
+ } else if (act.matchString("rotate_to", true)) {
+ actionList.push_back(new ActionRotateTo(_engine, slot, args));
+ } else if (act.matchString("save_game", true)) {
+ // Not used. Purposely left empty
+ } else if (act.matchString("set_partial_screen", true)) {
+ actionList.push_back(new ActionSetPartialScreen(_engine, slot, args));
+ } else if (act.matchString("set_screen", true)) {
+ actionList.push_back(new ActionSetScreen(_engine, slot, args));
+ } else if (act.matchString("set_venus", true)) {
+ actionList.push_back(new ActionSetVenus(_engine, slot, args));
+ } else if (act.matchString("stop", true)) {
+ actionList.push_back(new ActionStop(_engine, slot, args));
+ } else if (act.matchString("streamvideo", true)) {
+ actionList.push_back(new ActionStreamVideo(_engine, slot, args));
+ } else if (act.matchString("syncsound", true)) {
+ actionList.push_back(new ActionSyncSound(_engine, slot, args));
+ } else if (act.matchString("timer", true)) {
+ actionList.push_back(new ActionTimer(_engine, slot, args));
+ } else if (act.matchString("ttytext", true)) {
+ actionList.push_back(new ActionTtyText(_engine, slot, args));
+ } else if (act.matchString("universe_music", true)) {
+ actionList.push_back(new ActionMusic(_engine, slot, args, true));
+ } else if (act.matchString("copy_file", true)) {
+ // Not used. Purposely left empty
+ } else {
+ warning("Unhandled result action type: %s", line.c_str());
+ }
+ }
}
line = stream.readLine();
trimCommentsAndWhiteSpace(&line);
+ line.toLowercase();
}
return;
@@ -259,11 +315,11 @@ uint ScriptManager::parseFlags(Common::SeekableReadStream &stream) const {
while (!stream.eos() && !line.contains('}')) {
if (line.matchString("ONCE_PER_INST", true)) {
- flags |= ONCE_PER_INST;
+ flags |= Puzzle::ONCE_PER_INST;
} else if (line.matchString("DO_ME_NOW", true)) {
- flags |= DO_ME_NOW;
+ flags |= Puzzle::DO_ME_NOW;
} else if (line.matchString("DISABLED", true)) {
- flags |= DISABLED;
+ flags |= Puzzle::DISABLED;
}
line = stream.readLine();
@@ -273,7 +329,7 @@ uint ScriptManager::parseFlags(Common::SeekableReadStream &stream) const {
return flags;
}
-void ScriptManager::parseControl(Common::String &line, Common::SeekableReadStream &stream) {
+Control *ScriptManager::parseControl(Common::String &line, Common::SeekableReadStream &stream) {
uint32 key;
char controlTypeBuffer[20];
@@ -282,21 +338,36 @@ void ScriptManager::parseControl(Common::String &line, Common::SeekableReadStrea
Common::String controlType(controlTypeBuffer);
if (controlType.equalsIgnoreCase("push_toggle")) {
- _activeControls.push_back(new PushToggleControl(_engine, key, stream));
- return;
+ return new PushToggleControl(_engine, key, stream);
} else if (controlType.equalsIgnoreCase("flat")) {
Control::parseFlatControl(_engine);
- return;
+ return NULL;
} else if (controlType.equalsIgnoreCase("pana")) {
Control::parsePanoramaControl(_engine, stream);
- return;
+ return NULL;
} else if (controlType.equalsIgnoreCase("tilt")) {
Control::parseTiltControl(_engine, stream);
- return;
+ return NULL;
} else if (controlType.equalsIgnoreCase("lever")) {
- _activeControls.push_back(new LeverControl(_engine, key, stream));
- return;
+ return new LeverControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("slot")) {
+ return new SlotControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("input")) {
+ return new InputControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("save")) {
+ return new SaveControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("safe")) {
+ return new SafeControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("hotmovie")) {
+ return new HotMovControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("fist")) {
+ return new FistControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("paint")) {
+ return new PaintControl(_engine, key, stream);
+ } else if (controlType.equalsIgnoreCase("titler")) {
+ return new TitlerControl(_engine, key, stream);
}
+ return NULL;
}
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp
index 41b835e550..c532a2b15d 100644
--- a/engines/zvision/scripting/script_manager.cpp
+++ b/engines/zvision/scripting/script_manager.cpp
@@ -1,24 +1,24 @@
/* 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.
- *
- */
+*
+* 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"
@@ -30,168 +30,233 @@
#include "zvision/core/save_manager.h"
#include "zvision/scripting/actions.h"
#include "zvision/utility/utility.h"
+#include "zvision/scripting/sidefx/timer_node.h"
#include "common/algorithm.h"
#include "common/hashmap.h"
#include "common/debug.h"
#include "common/stream.h"
-
+#include "common/config-manager.h"
namespace ZVision {
ScriptManager::ScriptManager(ZVision *engine)
: _engine(engine),
- _currentlyFocusedControl(0) {
+ _currentlyFocusedControl(0),
+ _activeControls(NULL) {
}
ScriptManager::~ScriptManager() {
- for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
- delete (*iter);
- }
- for (PuzzleList::iterator iter = _globalPuzzles.begin(); iter != _globalPuzzles.end(); ++iter) {
- delete (*iter);
- }
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- delete (*iter);
- }
+ cleanScriptScope(universe);
+ cleanScriptScope(world);
+ cleanScriptScope(room);
+ cleanScriptScope(nodeview);
+ _controlEvents.clear();
}
void ScriptManager::initialize() {
- parseScrFile("universe.scr", true);
+ cleanScriptScope(universe);
+ cleanScriptScope(world);
+ cleanScriptScope(room);
+ cleanScriptScope(nodeview);
+
+ _currentLocation.node = 0;
+ _currentLocation.world = 0;
+ _currentLocation.room = 0;
+ _currentLocation.view = 0;
+
+ parseScrFile("universe.scr", universe);
changeLocation('g', 'a', 'r', 'y', 0);
+
+ _controlEvents.clear();
}
void ScriptManager::update(uint deltaTimeMillis) {
+ if (_currentLocation.node != _nextLocation.node ||
+ _currentLocation.room != _nextLocation.room ||
+ _currentLocation.view != _nextLocation.view ||
+ _currentLocation.world != _nextLocation.world)
+ ChangeLocationReal();
+
updateNodes(deltaTimeMillis);
- checkPuzzleCriteria();
+ if (! execScope(nodeview))
+ return;
+ if (! execScope(room))
+ return;
+ if (! execScope(world))
+ return;
+ if (! execScope(universe))
+ return;
+ updateControls(deltaTimeMillis);
}
-void ScriptManager::createReferenceTable() {
- // Iterate through each local Puzzle
- for (PuzzleList::iterator activePuzzleIter = _activePuzzles.begin(); activePuzzleIter != _activePuzzles.end(); ++activePuzzleIter) {
- Puzzle *puzzlePtr = (*activePuzzleIter);
-
- // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
- for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*activePuzzleIter)->criteriaList.begin(); criteriaIter != (*activePuzzleIter)->criteriaList.end(); ++criteriaIter) {
- for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
- _referenceTable[entryIter->key].push_back(puzzlePtr);
-
- // If the argument is a key, add a reference to it as well
- if (entryIter->argumentIsAKey) {
- _referenceTable[entryIter->argument].push_back(puzzlePtr);
- }
- }
- }
+bool ScriptManager::execScope(ScriptScope &scope) {
+ // Swap queues
+ PuzzleList *tmp = scope.execQueue;
+ scope.execQueue = scope.scopeQueue;
+ scope.scopeQueue = tmp;
+ scope.scopeQueue->clear();
+
+ for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter)
+ (*PuzzleIter)->addedBySetState = 0;
+
+ if (scope.procCount < 2 || getStateValue(StateKey_ExecScopeStyle)) {
+ for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter)
+ if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount))
+ return false;
+ } else {
+ for (PuzzleList::iterator PuzzleIter = scope.execQueue->begin(); PuzzleIter != scope.execQueue->end(); ++PuzzleIter)
+ if (!checkPuzzleCriteria(*PuzzleIter, scope.procCount))
+ return false;
}
- // Iterate through each global Puzzle
- for (PuzzleList::iterator globalPuzzleIter = _globalPuzzles.begin(); globalPuzzleIter != _globalPuzzles.end(); ++globalPuzzleIter) {
- Puzzle *puzzlePtr = (*globalPuzzleIter);
+ if (scope.procCount < 2) {
+ scope.procCount++;
+ }
+ return true;
+}
- // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
- for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*globalPuzzleIter)->criteriaList.begin(); criteriaIter != (*globalPuzzleIter)->criteriaList.end(); ++criteriaIter) {
- for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
- _referenceTable[entryIter->key].push_back(puzzlePtr);
-
- // If the argument is a key, add a reference to it as well
- if (entryIter->argumentIsAKey) {
- _referenceTable[entryIter->argument].push_back(puzzlePtr);
- }
- }
- }
+void ScriptManager::referenceTableAddPuzzle(uint32 key, PuzzleRef ref) {
+ if (_referenceTable.contains(key)) {
+ Common::Array<PuzzleRef> *arr = &_referenceTable[key];
+ for (uint32 i = 0; i < arr->size(); i++)
+ if ((*arr)[i].puz == ref.puz)
+ return;
}
- // Remove duplicate entries
- for (PuzzleMap::iterator referenceTableIter = _referenceTable.begin(); referenceTableIter != _referenceTable.end(); ++referenceTableIter) {
- removeDuplicateEntries(referenceTableIter->_value);
+ _referenceTable[key].push_back(ref);
+}
+
+void ScriptManager::addPuzzlesToReferenceTable(ScriptScope &scope) {
+ // Iterate through each local Puzzle
+ for (PuzzleList::iterator PuzzleIter = scope.puzzles.begin(); PuzzleIter != scope.puzzles.end(); ++PuzzleIter) {
+ Puzzle *puzzlePtr = (*PuzzleIter);
+
+ PuzzleRef ref;
+ ref.scope = &scope;
+ ref.puz = puzzlePtr;
+
+ referenceTableAddPuzzle(puzzlePtr->key, ref);
+
+ // Iterate through each CriteriaEntry and add a reference from the criteria key to the Puzzle
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = (*PuzzleIter)->criteriaList.begin(); criteriaIter != (*PuzzleIter)->criteriaList.end(); ++criteriaIter)
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter)
+ referenceTableAddPuzzle(entryIter->key, ref);
}
}
void ScriptManager::updateNodes(uint deltaTimeMillis) {
// If process() returns true, it means the node can be deleted
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end();) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end();) {
if ((*iter)->process(deltaTimeMillis)) {
- delete (*iter);
+ delete(*iter);
// Remove the node
- iter = _activeControls.erase(iter);
+ iter = _activeSideFx.erase(iter);
} else {
++iter;
}
}
}
-void ScriptManager::checkPuzzleCriteria() {
- while (!_puzzlesToCheck.empty()) {
- Puzzle *puzzle = _puzzlesToCheck.pop();
-
- // Check if the puzzle is already finished
- // Also check that the puzzle isn't disabled
- if (getStateValue(puzzle->key) == 1 && (getStateFlags(puzzle->key) & DISABLED) == 0) {
- continue;
+void ScriptManager::updateControls(uint deltaTimeMillis) {
+ if (!_activeControls)
+ return;
+
+ // Process only one event
+ if (!_controlEvents.empty()) {
+ Common::Event _event = _controlEvents.front();
+ Common::Point imageCoord;
+ switch (_event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ imageCoord = _engine->getRenderManager()->screenSpaceToImageSpace(_event.mouse);
+ onMouseDown(_event.mouse, imageCoord);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ imageCoord = _engine->getRenderManager()->screenSpaceToImageSpace(_event.mouse);
+ onMouseUp(_event.mouse, imageCoord);
+ break;
+ case Common::EVENT_KEYDOWN:
+ onKeyDown(_event.kbd);
+ break;
+ case Common::EVENT_KEYUP:
+ onKeyUp(_event.kbd);
+ break;
+ default:
+ break;
}
+ _controlEvents.pop_front();
+ }
+
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); iter++)
+ if ((*iter)->process(deltaTimeMillis))
+ break;
+}
+
+bool ScriptManager::checkPuzzleCriteria(Puzzle *puzzle, uint counter) {
+ // Check if the puzzle is already finished
+ // Also check that the puzzle isn't disabled
+ if (getStateValue(puzzle->key) == 1 || (getStateFlag(puzzle->key) & Puzzle::DISABLED) == Puzzle::DISABLED) {
+ return true;
+ }
- // Check each Criteria
-
- bool criteriaMet = false;
- for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = puzzle->criteriaList.begin(); criteriaIter != puzzle->criteriaList.end(); ++criteriaIter) {
- criteriaMet = false;
-
- for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
- // Get the value to compare against
- uint argumentValue;
- if (entryIter->argumentIsAKey)
- argumentValue = getStateValue(entryIter->argument);
- else
- argumentValue = entryIter->argument;
-
- // Do the comparison
- switch (entryIter->criteriaOperator) {
- case Puzzle::EQUAL_TO:
- criteriaMet = getStateValue(entryIter->key) == argumentValue;
- break;
- case Puzzle::NOT_EQUAL_TO:
- criteriaMet = getStateValue(entryIter->key) != argumentValue;
- break;
- case Puzzle::GREATER_THAN:
- criteriaMet = getStateValue(entryIter->key) > argumentValue;
- break;
- case Puzzle::LESS_THAN:
- criteriaMet = getStateValue(entryIter->key) < argumentValue;
- break;
- }
-
- // If one check returns false, don't keep checking
- if (!criteriaMet) {
- break;
- }
+ // Check each Criteria
+ if (counter == 0 && (getStateFlag(puzzle->key) & Puzzle::DO_ME_NOW) == 0)
+ return true;
+
+ bool criteriaMet = false;
+ for (Common::List<Common::List<Puzzle::CriteriaEntry> >::iterator criteriaIter = puzzle->criteriaList.begin(); criteriaIter != puzzle->criteriaList.end(); ++criteriaIter) {
+ criteriaMet = false;
+
+ for (Common::List<Puzzle::CriteriaEntry>::iterator entryIter = criteriaIter->begin(); entryIter != criteriaIter->end(); ++entryIter) {
+ // Get the value to compare against
+ int argumentValue;
+ if (entryIter->argumentIsAKey)
+ argumentValue = getStateValue(entryIter->argument);
+ else
+ argumentValue = entryIter->argument;
+
+ // Do the comparison
+ switch (entryIter->criteriaOperator) {
+ case Puzzle::EQUAL_TO:
+ criteriaMet = getStateValue(entryIter->key) == argumentValue;
+ break;
+ case Puzzle::NOT_EQUAL_TO:
+ criteriaMet = getStateValue(entryIter->key) != argumentValue;
+ break;
+ case Puzzle::GREATER_THAN:
+ criteriaMet = getStateValue(entryIter->key) > argumentValue;
+ break;
+ case Puzzle::LESS_THAN:
+ criteriaMet = getStateValue(entryIter->key) < argumentValue;
+ break;
}
- // If any of the Criteria are *fully* met, then execute the results
- if (criteriaMet) {
+ // If one check returns false, don't keep checking
+ if (!criteriaMet) {
break;
}
}
- // criteriaList can be empty. Aka, the puzzle should be executed immediately
- if (puzzle->criteriaList.empty() || criteriaMet) {
- debug(1, "Puzzle %u criteria passed. Executing its ResultActions", puzzle->key);
+ // If any of the Criteria are *fully* met, then execute the results
+ if (criteriaMet) {
+ break;
+ }
+ }
- // Set the puzzle as completed
- setStateValue(puzzle->key, 1);
+ // criteriaList can be empty. Aka, the puzzle should be executed immediately
+ if (puzzle->criteriaList.empty() || criteriaMet) {
+ debug(1, "Puzzle %u criteria passed. Executing its ResultActions", puzzle->key);
- bool shouldContinue = true;
- for (Common::List<ResultAction *>::iterator resultIter = puzzle->resultActions.begin(); resultIter != puzzle->resultActions.end(); ++resultIter) {
- shouldContinue = shouldContinue && (*resultIter)->execute(_engine);
- if (!shouldContinue) {
- break;
- }
- }
+ // Set the puzzle as completed
+ setStateValue(puzzle->key, 1);
- if (!shouldContinue) {
- break;
- }
+ for (Common::List<ResultAction *>::iterator resultIter = puzzle->resultActions.begin(); resultIter != puzzle->resultActions.end(); ++resultIter) {
+ if (!(*resultIter)->execute())
+ return false;
}
}
+
+ return true;
}
void ScriptManager::cleanStateTable() {
@@ -205,62 +270,104 @@ void ScriptManager::cleanStateTable() {
}
}
-uint ScriptManager::getStateValue(uint32 key) {
+void ScriptManager::cleanScriptScope(ScriptScope &scope) {
+ scope.privQueueOne.clear();
+ scope.privQueueTwo.clear();
+ scope.scopeQueue = &scope.privQueueOne;
+ scope.execQueue = &scope.privQueueTwo;
+ for (PuzzleList::iterator iter = scope.puzzles.begin(); iter != scope.puzzles.end(); ++iter)
+ delete(*iter);
+
+ scope.puzzles.clear();
+
+ for (ControlList::iterator iter = scope.controls.begin(); iter != scope.controls.end(); ++iter)
+ delete(*iter);
+
+ scope.controls.clear();
+
+ scope.procCount = 0;
+}
+
+int ScriptManager::getStateValue(uint32 key) {
if (_globalState.contains(key))
return _globalState[key];
else
return 0;
}
-void ScriptManager::setStateValue(uint32 key, uint value) {
- _globalState[key] = value;
-
+void ScriptManager::queuePuzzles(uint32 key) {
if (_referenceTable.contains(key)) {
- for (Common::Array<Puzzle *>::iterator iter = _referenceTable[key].begin(); iter != _referenceTable[key].end(); ++iter) {
- _puzzlesToCheck.push((*iter));
- }
+ Common::Array<PuzzleRef> *arr = &_referenceTable[key];
+ for (int32 i = arr->size() - 1; i >= 0; i--)
+ if (!(*arr)[i].puz->addedBySetState) {
+ (*arr)[i].scope->scopeQueue->push_back((*arr)[i].puz);
+ (*arr)[i].puz->addedBySetState = true;
+ }
}
}
-uint ScriptManager::getStateFlags(uint32 key) {
+void ScriptManager::setStateValue(uint32 key, int value) {
+ if (value == 0)
+ _globalState.erase(key);
+ else
+ _globalState[key] = value;
+
+ queuePuzzles(key);
+}
+
+void ScriptManager::setStateValueSilent(uint32 key, int value) {
+ if (value == 0)
+ _globalState.erase(key);
+ else
+ _globalState[key] = value;
+}
+
+uint ScriptManager::getStateFlag(uint32 key) {
if (_globalStateFlags.contains(key))
return _globalStateFlags[key];
else
return 0;
}
-void ScriptManager::setStateFlags(uint32 key, uint flags) {
- _globalStateFlags[key] = flags;
+void ScriptManager::setStateFlag(uint32 key, uint value) {
+ queuePuzzles(key);
- if (_referenceTable.contains(key)) {
- for (Common::Array<Puzzle *>::iterator iter = _referenceTable[key].begin(); iter != _referenceTable[key].end(); ++iter) {
- _puzzlesToCheck.push((*iter));
- }
- }
+ _globalStateFlags[key] |= value;
}
-void ScriptManager::addToStateValue(uint32 key, uint valueToAdd) {
- _globalState[key] += valueToAdd;
+void ScriptManager::setStateFlagSilent(uint32 key, uint value) {
+ if (value == 0)
+ _globalStateFlags.erase(key);
+ else
+ _globalStateFlags[key] = value;
}
-void ScriptManager::addControl(Control *control) {
- _activeControls.push_back(control);
-}
+void ScriptManager::unsetStateFlag(uint32 key, uint value) {
+ queuePuzzles(key);
-Control *ScriptManager::getControl(uint32 key) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- if ((*iter)->getKey() == key) {
- return (*iter);
- }
+ if (_globalStateFlags.contains(key)) {
+ _globalStateFlags[key] &= ~value;
+
+ if (_globalStateFlags[key] == 0)
+ _globalStateFlags.erase(key);
}
+}
+Control *ScriptManager::getControl(uint32 key) {
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter)
+ if ((*iter)->getKey() == key)
+ return *iter;
return nullptr;
}
void ScriptManager::focusControl(uint32 key) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
+ if (!_activeControls)
+ return;
+ if (_currentlyFocusedControl == key)
+ return;
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
uint32 controlKey = (*iter)->getKey();
-
+
if (controlKey == key) {
(*iter)->focus();
} else if (controlKey == _currentlyFocusedControl) {
@@ -271,167 +378,394 @@ void ScriptManager::focusControl(uint32 key) {
_currentlyFocusedControl = key;
}
+void ScriptManager::setFocusControlKey(uint32 key) {
+ _currentlyFocusedControl = key;
+}
+
+void ScriptManager::addSideFX(SideFX *fx) {
+ _activeSideFx.push_back(fx);
+}
+
+SideFX *ScriptManager::getSideFX(uint32 key) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ return (*iter);
+ }
+ }
+
+ return nullptr;
+}
+
+void ScriptManager::deleteSideFx(uint32 key) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ delete(*iter);
+ _activeSideFx.erase(iter);
+ break;
+ }
+ }
+}
+
+void ScriptManager::stopSideFx(uint32 key) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ bool ret = (*iter)->stop();
+ if (ret) {
+ delete(*iter);
+ _activeSideFx.erase(iter);
+ }
+ break;
+ }
+ }
+}
+
+void ScriptManager::killSideFx(uint32 key) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter) {
+ if ((*iter)->getKey() == key) {
+ (*iter)->kill();
+ delete(*iter);
+ _activeSideFx.erase(iter);
+ break;
+ }
+ }
+}
+
+void ScriptManager::killSideFxType(SideFX::SideFXType type) {
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end();) {
+ if ((*iter)->getType() & type) {
+ (*iter)->kill();
+ delete(*iter);
+ iter = _activeSideFx.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
void ScriptManager::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos);
+ if (!_activeControls)
+ return;
+ for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
+ if ((*iter)->onMouseDown(screenSpacePos, backgroundImageSpacePos))
+ return;
}
}
void ScriptManager::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos);
+ if (!_activeControls)
+ return;
+ for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
+ if ((*iter)->onMouseUp(screenSpacePos, backgroundImageSpacePos))
+ return;
}
}
bool ScriptManager::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
- bool cursorWasChanged = false;
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- cursorWasChanged = cursorWasChanged || (*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos);
+ if (!_activeControls)
+ return false;
+
+ for (ControlList::iterator iter = _activeControls->reverse_begin(); iter != _activeControls->end(); iter--) {
+ if ((*iter)->onMouseMove(screenSpacePos, backgroundImageSpacePos))
+ return true;
}
- return cursorWasChanged;
+ return false;
}
void ScriptManager::onKeyDown(Common::KeyState keyState) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->onKeyDown(keyState);
+ if (!_activeControls)
+ return;
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
+ if ((*iter)->onKeyDown(keyState))
+ return;
}
}
void ScriptManager::onKeyUp(Common::KeyState keyState) {
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->onKeyUp(keyState);
+ if (!_activeControls)
+ return;
+ for (ControlList::iterator iter = _activeControls->begin(); iter != _activeControls->end(); ++iter) {
+ if ((*iter)->onKeyUp(keyState))
+ return;
}
}
-void ScriptManager::changeLocation(char world, char room, char node, char view, uint32 offset) {
- assert(world != 0);
- debug(1, "Changing location to: %c %c %c %c %u", world, room, node, view, offset);
+void ScriptManager::changeLocation(const Location &_newLocation) {
+ changeLocation(_newLocation.world, _newLocation.room, _newLocation.node, _newLocation.view, _newLocation.offset);
+}
- // Auto save
- _engine->getSaveManager()->autoSave();
+void ScriptManager::changeLocation(char _world, char _room, char _node, char _view, uint32 offset) {
+ _nextLocation.world = _world;
+ _nextLocation.room = _room;
+ _nextLocation.node = _node;
+ _nextLocation.view = _view;
+ _nextLocation.offset = offset;
+ // If next location 0000 - it's indicate to go to previous location.
+ if (_nextLocation.world == '0' && _nextLocation.room == '0' && _nextLocation.node == '0' && _nextLocation.view == '0') {
+ if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') {
+ _nextLocation.world = getStateValue(StateKey_LastWorld);
+ _nextLocation.room = getStateValue(StateKey_LastRoom);
+ _nextLocation.node = getStateValue(StateKey_LastNode);
+ _nextLocation.view = getStateValue(StateKey_LastView);
+ _nextLocation.offset = getStateValue(StateKey_LastViewPos);
+ } else {
+ _nextLocation.world = getStateValue(StateKey_Menu_LastWorld);
+ _nextLocation.room = getStateValue(StateKey_Menu_LastRoom);
+ _nextLocation.node = getStateValue(StateKey_Menu_LastNode);
+ _nextLocation.view = getStateValue(StateKey_Menu_LastView);
+ _nextLocation.offset = getStateValue(StateKey_Menu_LastViewPos);
+ }
+ }
+}
- // Clear all the containers
- _referenceTable.clear();
- _puzzlesToCheck.clear();
- for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
- delete (*iter);
+void ScriptManager::ChangeLocationReal() {
+ assert(_nextLocation.world != 0);
+ debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset);
+
+ if (_nextLocation.world == 'g' && _nextLocation.room == 'j' && !ConfMan.getBool("originalsaveload")) {
+ if ((_nextLocation.node == 's' || _nextLocation.node == 'r') && _nextLocation.view == 'e') {
+ // Hook up the ScummVM save/restore dialog
+ bool isSave = (_nextLocation.node == 's');
+ bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSave);
+ if (!gameSavedOrLoaded || isSave) {
+ // Reload the current room
+ _nextLocation.world = _currentLocation.world;
+ _nextLocation.room = _currentLocation.room;
+ _nextLocation.node = _currentLocation.node;
+ _nextLocation.view = _currentLocation.view;
+ _nextLocation.offset = _currentLocation.offset;
+ _currentLocation.world = '0';
+ _currentLocation.room = '0';
+ _currentLocation.node = '0';
+ _currentLocation.view = '0';
+ _currentLocation.offset = 0;
+ } else
+ return;
+ }
}
- _activePuzzles.clear();
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- delete (*iter);
+
+ _engine->setRenderDelay(2);
+
+ if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') {
+ if (_nextLocation.world != 'g' || _nextLocation.room != 'j') {
+ setStateValue(StateKey_LastWorld, getStateValue(StateKey_World));
+ setStateValue(StateKey_LastRoom, getStateValue(StateKey_Room));
+ setStateValue(StateKey_LastNode, getStateValue(StateKey_Node));
+ setStateValue(StateKey_LastView, getStateValue(StateKey_View));
+ setStateValue(StateKey_LastViewPos, getStateValue(StateKey_ViewPos));
+ } else {
+ setStateValue(StateKey_Menu_LastWorld, getStateValue(StateKey_World));
+ setStateValue(StateKey_Menu_LastRoom, getStateValue(StateKey_Room));
+ setStateValue(StateKey_Menu_LastNode, getStateValue(StateKey_Node));
+ setStateValue(StateKey_Menu_LastView, getStateValue(StateKey_View));
+ setStateValue(StateKey_Menu_LastViewPos, getStateValue(StateKey_ViewPos));
+ }
}
- _activeControls.clear();
- // Revert to the idle cursor
- _engine->getCursorManager()->revertToIdle();
+ if (_nextLocation.world == 'g' && _nextLocation.room == 'j') {
+ if (_nextLocation.node == 's' && _nextLocation.view == 'e' &&
+ _currentLocation.world != 'g' && _currentLocation.room != 'j')
+ _engine->getSaveManager()->prepareSaveBuffer();
+ } else {
+ if (_currentLocation.world == 'g' && _currentLocation.room == 'j')
+ _engine->getSaveManager()->flushSaveBuffer();
+ else {
+ // Auto save
+ //_engine->getSaveManager()->autoSave();
+ }
+ }
- // Reset the background velocity
- _engine->getRenderManager()->setBackgroundVelocity(0);
+ setStateValue(StateKey_World, _nextLocation.world);
+ setStateValue(StateKey_Room, _nextLocation.room);
+ setStateValue(StateKey_Node, _nextLocation.node);
+ setStateValue(StateKey_View, _nextLocation.view);
+ setStateValue(StateKey_ViewPos, _nextLocation.offset);
- // Remove any alphaEntries
- _engine->getRenderManager()->clearAlphaEntries();
+ _referenceTable.clear();
+ addPuzzlesToReferenceTable(universe);
- // Clean the global state table
- cleanStateTable();
+ _engine->menuBarEnable(0xFFFF);
- // Parse into puzzles and controls
- Common::String fileName = Common::String::format("%c%c%c%c.scr", world, room, node, view);
- parseScrFile(fileName);
+ if (_nextLocation.world != _currentLocation.world) {
+ cleanScriptScope(nodeview);
+ cleanScriptScope(room);
+ cleanScriptScope(world);
- // Change the background position
- _engine->getRenderManager()->setBackgroundPosition(offset);
+ Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+ parseScrFile(fileName, nodeview);
+ addPuzzlesToReferenceTable(nodeview);
- // Enable all the controls
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->enable();
- }
+ fileName = Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room);
+ parseScrFile(fileName, room);
+ addPuzzlesToReferenceTable(room);
- // Add all the local puzzles to the queue to be checked
- for (PuzzleList::iterator iter = _activePuzzles.begin(); iter != _activePuzzles.end(); ++iter) {
- // Reset any Puzzles that have the flag ONCE_PER_INST
- if ((getStateFlags((*iter)->key) & ONCE_PER_INST) == ONCE_PER_INST) {
- setStateValue((*iter)->key, 0);
- }
+ fileName = Common::String::format("%c.scr", _nextLocation.world);
+ parseScrFile(fileName, world);
+ addPuzzlesToReferenceTable(world);
+ } else if (_nextLocation.room != _currentLocation.room) {
+ cleanScriptScope(nodeview);
+ cleanScriptScope(room);
- _puzzlesToCheck.push((*iter));
- }
+ addPuzzlesToReferenceTable(world);
- // Add all the global puzzles to the queue to be checked
- for (PuzzleList::iterator iter = _globalPuzzles.begin(); iter != _globalPuzzles.end(); ++iter) {
- // Reset any Puzzles that have the flag ONCE_PER_INST
- if ((getStateFlags((*iter)->key) & ONCE_PER_INST) == ONCE_PER_INST) {
- setStateValue((*iter)->key, 0);
- }
+ Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+ parseScrFile(fileName, nodeview);
+ addPuzzlesToReferenceTable(nodeview);
+
+ fileName = Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room);
+ parseScrFile(fileName, room);
+ addPuzzlesToReferenceTable(room);
- _puzzlesToCheck.push((*iter));
+ } else if (_nextLocation.node != _currentLocation.node || _nextLocation.view != _currentLocation.view) {
+ cleanScriptScope(nodeview);
+
+ addPuzzlesToReferenceTable(room);
+ addPuzzlesToReferenceTable(world);
+
+ Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+ parseScrFile(fileName, nodeview);
+ addPuzzlesToReferenceTable(nodeview);
}
- // Create the puzzle reference table
- createReferenceTable();
+ _activeControls = &nodeview.controls;
- // Update _currentLocation
- _currentLocation.world = world;
- _currentLocation.room = room;
- _currentLocation.node = node;
- _currentLocation.view = view;
- _currentLocation.offset = offset;
+ // Revert to the idle cursor
+ _engine->getCursorManager()->changeCursor(CursorIndex_Idle);
+
+ // Change the background position
+ _engine->getRenderManager()->setBackgroundPosition(_nextLocation.offset);
+
+ if (_currentLocation.world == 0 && _currentLocation.room == 0 && _currentLocation.node == 0 && _currentLocation.view == 0) {
+ _currentLocation = _nextLocation;
+ execScope(world);
+ execScope(room);
+ execScope(nodeview);
+ } else if (_nextLocation.world != _currentLocation.world) {
+ _currentLocation = _nextLocation;
+ execScope(room);
+ execScope(nodeview);
+ } else if (_nextLocation.room != _currentLocation.room) {
+ _currentLocation = _nextLocation;
+ execScope(room);
+ execScope(nodeview);
+ } else if (_nextLocation.node != _currentLocation.node || _nextLocation.view != _currentLocation.view) {
+ _currentLocation = _nextLocation;
+ execScope(nodeview);
+ }
+
+ _engine->checkBorders();
}
-void ScriptManager::serializeStateTable(Common::WriteStream *stream) {
- // Write the number of state value entries
- stream->writeUint32LE(_globalState.size());
+void ScriptManager::serialize(Common::WriteStream *stream) {
+ stream->writeUint32BE(MKTAG('Z', 'N', 'S', 'G'));
+ stream->writeUint32LE(4);
+ stream->writeUint32LE(0);
+ stream->writeUint32BE(MKTAG('L', 'O', 'C', ' '));
+ stream->writeUint32LE(8);
+ stream->writeByte(getStateValue(StateKey_World));
+ stream->writeByte(getStateValue(StateKey_Room));
+ stream->writeByte(getStateValue(StateKey_Node));
+ stream->writeByte(getStateValue(StateKey_View));
+ stream->writeUint32LE(getStateValue(StateKey_ViewPos));
+
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); ++iter)
+ (*iter)->serialize(stream);
- for (StateMap::iterator iter = _globalState.begin(); iter != _globalState.end(); ++iter) {
- // Write out the key/value pair
- stream->writeUint32LE(iter->_key);
- stream->writeUint32LE(iter->_value);
- }
+ stream->writeUint32BE(MKTAG('F', 'L', 'A', 'G'));
+
+ int32 slots = 20000;
+ if (_engine->getGameId() == GID_NEMESIS)
+ slots = 30000;
+
+ stream->writeUint32LE(slots * 2);
+
+ for (int32 i = 0; i < slots; i++)
+ stream->writeUint16LE(getStateFlag(i));
+
+ stream->writeUint32BE(MKTAG('P', 'U', 'Z', 'Z'));
+
+ stream->writeUint32LE(slots * 2);
+
+ for (int32 i = 0; i < slots; i++)
+ stream->writeSint16LE(getStateValue(i));
}
-void ScriptManager::deserializeStateTable(Common::SeekableReadStream *stream) {
+void ScriptManager::deserialize(Common::SeekableReadStream *stream) {
// Clear out the current table values
_globalState.clear();
+ _globalStateFlags.clear();
- // Read the number of key/value pairs
- uint32 numberOfPairs = stream->readUint32LE();
+ cleanScriptScope(nodeview);
+ cleanScriptScope(room);
+ cleanScriptScope(world);
- for (uint32 i = 0; i < numberOfPairs; ++i) {
- uint32 key = stream->readUint32LE();
- uint32 value = stream->readUint32LE();
- // Directly access the state table so we don't trigger Puzzle checks
- _globalState[key] = value;
- }
-}
+ _currentLocation.node = 0;
+ _currentLocation.world = 0;
+ _currentLocation.room = 0;
+ _currentLocation.view = 0;
-void ScriptManager::serializeControls(Common::WriteStream *stream) {
- // Count how many controls need to save their data
- // Because WriteStream isn't seekable
- uint32 numberOfControlsNeedingSerialization = 0;
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- if ((*iter)->needsSerialization()) {
- numberOfControlsNeedingSerialization++;
- }
- }
- stream->writeUint32LE(numberOfControlsNeedingSerialization);
+ for (SideFXList::iterator iter = _activeSideFx.begin(); iter != _activeSideFx.end(); iter++)
+ delete(*iter);
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- (*iter)->serialize(stream);
+ _activeSideFx.clear();
+
+ _referenceTable.clear();
+
+ if (stream->readUint32BE() != MKTAG('Z', 'N', 'S', 'G') || stream->readUint32LE() != 4) {
+ changeLocation('g', 'a', 'r', 'y', 0);
+ return;
}
-}
-void ScriptManager::deserializeControls(Common::SeekableReadStream *stream) {
- uint32 numberOfControls = stream->readUint32LE();
+ stream->seek(4, SEEK_CUR);
- for (uint32 i = 0; i < numberOfControls; ++i) {
- uint32 key = stream->readUint32LE();
- for (ControlList::iterator iter = _activeControls.begin(); iter != _activeControls.end(); ++iter) {
- if ((*iter)->getKey() == key) {
- (*iter)->deserialize(stream);
- break;
- }
+ if (stream->readUint32BE() != MKTAG('L', 'O', 'C', ' ') || stream->readUint32LE() != 8) {
+ changeLocation('g', 'a', 'r', 'y', 0);
+ return;
+ }
+
+ Location nextLocation;
+
+ nextLocation.world = stream->readByte();
+ nextLocation.room = stream->readByte();
+ nextLocation.node = stream->readByte();
+ nextLocation.view = stream->readByte();
+ nextLocation.offset = stream->readUint32LE() & 0x0000FFFF;
+
+ while (stream->pos() < stream->size()) {
+ uint32 tag = stream->readUint32BE();
+ uint32 tagSize = stream->readUint32LE();
+ switch (tag) {
+ case MKTAG('T', 'I', 'M', 'R'): {
+ uint32 key = stream->readUint32LE();
+ uint32 time = stream->readUint32LE();
+ if (_engine->getGameId() == GID_GRANDINQUISITOR)
+ time /= 100;
+ else if (_engine->getGameId() == GID_NEMESIS)
+ time /= 1000;
+ addSideFX(new TimerNode(_engine, key, time));
+ }
+ break;
+ case MKTAG('F', 'L', 'A', 'G'):
+ for (uint32 i = 0; i < tagSize / 2; i++)
+ setStateFlagSilent(i, stream->readUint16LE());
+ break;
+ case MKTAG('P', 'U', 'Z', 'Z'):
+ for (uint32 i = 0; i < tagSize / 2; i++)
+ setStateValueSilent(i, stream->readUint16LE());
+ break;
+ default:
+ stream->seek(tagSize, SEEK_CUR);
}
}
+
+ _nextLocation = nextLocation;
+
+ ChangeLocationReal();
+
+ _engine->setRenderDelay(10);
+ setStateValue(StateKey_RestoreFlag, 1);
+
+ _engine->loadSettings();
}
Location ScriptManager::getCurrentLocation() const {
@@ -441,4 +775,64 @@ Location ScriptManager::getCurrentLocation() const {
return location;
}
+Location ScriptManager::getLastLocation() {
+ Location location;
+ location.world = getStateValue(StateKey_LastWorld);
+ location.room = getStateValue(StateKey_LastRoom);
+ location.node = getStateValue(StateKey_LastNode);
+ location.view = getStateValue(StateKey_LastView);
+ location.offset = getStateValue(StateKey_LastViewPos);
+
+ return location;
+}
+
+Location ScriptManager::getLastMenuLocation() {
+ Location location;
+ location.world = getStateValue(StateKey_Menu_LastWorld);
+ location.room = getStateValue(StateKey_Menu_LastRoom);
+ location.node = getStateValue(StateKey_Menu_LastNode);
+ location.view = getStateValue(StateKey_Menu_LastView);
+ location.offset = getStateValue(StateKey_Menu_LastViewPos);
+
+ return location;
+}
+
+void ScriptManager::addEvent(Common::Event event) {
+ _controlEvents.push_back(event);
+}
+
+void ScriptManager::flushEvent(Common::EventType type) {
+ EventList::iterator it = _controlEvents.begin();
+ while (it != _controlEvents.end()) {
+
+ if ((*it).type == type)
+ it = _controlEvents.erase(it);
+ else
+ it++;
+ }
+}
+
+ValueSlot::ValueSlot(ScriptManager *scriptManager, const char *slotValue):
+ _scriptManager(scriptManager) {
+ value = 0;
+ slot = false;
+ const char *isSlot = strstr(slotValue, "[");
+ if (isSlot) {
+ slot = true;
+ value = atoi(isSlot + 1);
+ } else {
+ slot = false;
+ value = atoi(slotValue);
+ }
+}
+int16 ValueSlot::getValue() {
+ if (slot) {
+ if (value >= 0)
+ return _scriptManager->getStateValue(value);
+ else
+ return 0;
+ } else
+ return value;
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h
index 4d1b1f359b..89b961634b 100644
--- a/engines/zvision/scripting/script_manager.h
+++ b/engines/zvision/scripting/script_manager.h
@@ -8,12 +8,12 @@
* 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.
@@ -25,10 +25,11 @@
#include "zvision/scripting/puzzle.h"
#include "zvision/scripting/control.h"
+#include "zvision/scripting/sidefx.h"
#include "common/hashmap.h"
#include "common/queue.h"
-
+#include "common/events.h"
namespace Common {
class String;
@@ -39,6 +40,63 @@ namespace ZVision {
class ZVision;
+enum StateKey {
+ StateKey_World = 3,
+ StateKey_Room = 4,
+ StateKey_Node = 5,
+ StateKey_View = 6,
+ StateKey_ViewPos = 7,
+ StateKey_KeyPress = 8,
+ StateKey_InventoryItem = 9,
+ StateKey_LMouse = 10,
+ StateKey_NotSet = 11, // This key doesn't set
+ StateKey_Rounds = 12,
+ StateKey_Venus = 13,
+ StateKey_RMouse = 18,
+ StateKey_MenuState = 19,
+ StateKey_RestoreFlag = 20,
+ StateKey_Quitting = 39,
+ StateKey_LastWorld = 40,
+ StateKey_LastRoom = 41,
+ StateKey_LastNode = 42,
+ StateKey_LastView = 43,
+ StateKey_LastViewPos = 44,
+ StateKey_Menu_LastWorld = 45,
+ StateKey_Menu_LastRoom = 46,
+ StateKey_Menu_LastNode = 47,
+ StateKey_Menu_LastView = 48,
+ StateKey_Menu_LastViewPos = 49,
+ StateKey_KbdRotateSpeed = 50,
+ StateKey_Subtitles = 51,
+ StateKey_StreamSkipKey = 52,
+ StateKey_RotateSpeed = 53,
+ StateKey_Volume = 56,
+ StateKey_Qsound = 57,
+ StateKey_VenusEnable = 58,
+ StateKey_HighQuality = 59,
+ StateKey_VideoLineSkip = 65,
+ StateKey_Platform = 66,
+ StateKey_InstallLevel = 67,
+ StateKey_CountryCode = 68,
+ StateKey_CPU = 69,
+ StateKey_MovieCursor = 70,
+ StateKey_NoTurnAnim = 71,
+ StateKey_WIN958 = 72,
+ StateKey_ShowErrorDlg = 73,
+ StateKey_DebugCheats = 74,
+ StateKey_JapanFonts = 75,
+ StateKey_ExecScopeStyle = 76,
+ StateKey_Brightness = 77,
+ StateKey_EF9_R = 91,
+ StateKey_EF9_G = 92,
+ StateKey_EF9_B = 93,
+ StateKey_EF9_Speed = 94,
+ StateKey_Inv_Cnt_Slot = 100,
+ StateKey_Inv_1_Slot = 101,
+ StateKey_Inv_49_Slot = 149,
+ StateKey_Inv_TotalSlots = 150
+};
+
struct Location {
Location() : world('g'), room('a'), node('r'), view('y'), offset(0) {}
@@ -49,68 +107,99 @@ struct Location {
uint32 offset;
};
-typedef Common::HashMap<uint32, Common::Array<Puzzle *> > PuzzleMap;
typedef Common::List<Puzzle *> PuzzleList;
typedef Common::Queue<Puzzle *> PuzzleQueue;
typedef Common::List<Control *> ControlList;
-typedef Common::HashMap<uint32, uint32> StateMap;
-typedef Common::HashMap<uint32, uint> StateFlagMap;
+typedef Common::HashMap<uint32, int32> StateMap;
+typedef Common::List<SideFX *> SideFXList;
+typedef Common::List<Common::Event> EventList;
class ScriptManager {
public:
ScriptManager(ZVision *engine);
~ScriptManager();
-public:
- enum StateFlags {
- ONCE_PER_INST = 0x01,
- DO_ME_NOW = 0x02, // Somewhat useless flag since anything that needs to be done immediately has no criteria
- DISABLED = 0x04
- };
-
private:
ZVision *_engine;
+
+ struct ScriptScope {
+ uint32 procCount;
+
+ PuzzleList *scopeQueue; // For adding puzzles to queue
+ PuzzleList *execQueue; // Switch to it when execute
+ PuzzleList privQueueOne;
+ PuzzleList privQueueTwo;
+
+ PuzzleList puzzles;
+ ControlList controls;
+ };
+
+ struct PuzzleRef {
+ Puzzle *puz;
+ ScriptScope *scope;
+ };
+
+ typedef Common::HashMap<uint32, Common::Array<PuzzleRef> > PuzzleMap;
+
/**
* Holds the global state variable. Do NOT directly modify this. Use the accessors and
* mutators getStateValue() and setStateValue(). This ensures that Puzzles that reference a
* particular state key are checked after the key is modified.
*/
StateMap _globalState;
- /**
- * Holds the flags for the global states. This is used to enable/disable puzzles and/or
- * controls as well as which puzzles should are allowed to be re-executed
- */
- StateFlagMap _globalStateFlags;
+ /** Holds execute flags */
+ StateMap _globalStateFlags;
/** References _globalState keys to Puzzles */
PuzzleMap _referenceTable;
- /** Holds the Puzzles that should be checked this frame */
- PuzzleQueue _puzzlesToCheck;
- /** Holds the currently active puzzles */
- PuzzleList _activePuzzles;
- /** Holds the global puzzles */
- PuzzleList _globalPuzzles;
/** Holds the currently active controls */
- ControlList _activeControls;
+ ControlList *_activeControls;
+
+ EventList _controlEvents;
+
+ ScriptScope universe;
+ ScriptScope world;
+ ScriptScope room;
+ ScriptScope nodeview;
+
+ /** Holds the currently active timers, musics, other */
+ SideFXList _activeSideFx;
Location _currentLocation;
+ Location _nextLocation;
uint32 _currentlyFocusedControl;
public:
void initialize();
void update(uint deltaTimeMillis);
+ void queuePuzzles(uint32 key);
- uint getStateValue(uint32 key);
- void setStateValue(uint32 key, uint value);
- void addToStateValue(uint32 key, uint valueToAdd);
+ int getStateValue(uint32 key);
+ void setStateValue(uint32 key, int value);
- uint getStateFlags(uint32 key);
- void setStateFlags(uint32 key, uint flags);
+ uint getStateFlag(uint32 key);
+ void setStateFlag(uint32 key, uint value);
+ void unsetStateFlag(uint32 key, uint value);
void addControl(Control *control);
Control *getControl(uint32 key);
+ void enableControl(uint32 key);
+ void disableControl(uint32 key);
+
void focusControl(uint32 key);
+ // Only change focus control without call focus/unfocus.
+ void setFocusControlKey(uint32 key);
+
+ void addSideFX(SideFX *fx);
+ SideFX *getSideFX(uint32 key);
+ void deleteSideFx(uint32 key);
+ void stopSideFx(uint32 key);
+ void killSideFx(uint32 key);
+ void killSideFxType(SideFX::SideFXType type);
+
+ void addEvent(Common::Event);
+ void flushEvent(Common::EventType type);
/**
* Called when LeftMouse is pushed.
@@ -147,30 +236,51 @@ public:
*/
void onKeyUp(Common::KeyState keyState);
+ /** Mark next location */
void changeLocation(char world, char room, char node, char view, uint32 offset);
+ void changeLocation(const Location &_newLocation);
- void serializeStateTable(Common::WriteStream *stream);
- void deserializeStateTable(Common::SeekableReadStream *stream);
- void serializeControls(Common::WriteStream *stream);
- void deserializeControls(Common::SeekableReadStream *stream);
+ void serialize(Common::WriteStream *stream);
+ void deserialize(Common::SeekableReadStream *stream);
Location getCurrentLocation() const;
+ Location getLastLocation();
+ Location getLastMenuLocation();
private:
- void createReferenceTable();
+ void referenceTableAddPuzzle(uint32 key, PuzzleRef ref);
+ void addPuzzlesToReferenceTable(ScriptScope &scope);
void updateNodes(uint deltaTimeMillis);
- void checkPuzzleCriteria();
+ void updateControls(uint deltaTimeMillis);
+ bool checkPuzzleCriteria(Puzzle *puzzle, uint counter);
void cleanStateTable();
+ void cleanScriptScope(ScriptScope &scope);
+ bool execScope(ScriptScope &scope);
+
+ /** Perform change location */
+ void ChangeLocationReal();
+
+ int8 inventoryGetCount();
+ void inventorySetCount(int8 cnt);
+ int16 inventoryGetItem(int8 id);
+ void inventorySetItem(int8 id, int16 item);
+
+ void setStateFlagSilent(uint32 key, uint value);
+ void setStateValueSilent(uint32 key, int value);
-// TODO: Make this private. It was only made public so Console::cmdParseAllScrFiles() could use it
public:
+ void inventoryAdd(int16 item);
+ void inventoryDrop(int16 item);
+ void inventoryCycle();
+
+ // TODO: Make this private. It was only made public so Console::cmdParseAllScrFiles() could use it
/**
* Parses a script file into triggers and events
*
* @param fileName Name of the .scr file
* @param isGlobal Are the puzzles included in the file global (true). AKA, the won't be purged during location changes
*/
- void parseScrFile(const Common::String &fileName, bool isGlobal = false);
+ void parseScrFile(const Common::String &fileName, ScriptScope &scope);
private:
/**
@@ -216,9 +326,18 @@ private:
* @param line The line initially read
* @param stream Scr file stream
*/
- void parseControl(Common::String &line, Common::SeekableReadStream &stream);
+ Control *parseControl(Common::String &line, Common::SeekableReadStream &stream);
};
+class ValueSlot {
+public:
+ ValueSlot(ScriptManager *scriptManager, const char *slotValue);
+ int16 getValue();
+private:
+ int16 value;
+ bool slot;
+ ScriptManager *_scriptManager;
+};
} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx.h b/engines/zvision/scripting/sidefx.h
new file mode 100644
index 0000000000..5bb14f0cdd
--- /dev/null
+++ b/engines/zvision/scripting/sidefx.h
@@ -0,0 +1,114 @@
+/* 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 SIDEFX_H_INCLUDED
+#define SIDEFX_H_INCLUDED
+
+namespace Common {
+class SeekableReadStream;
+struct Point;
+class WriteStream;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+class SideFX {
+public:
+
+ enum SideFXType {
+ SIDEFX_ANIM = 1,
+ SIDEFX_AUDIO = 2,
+ SIDEFX_DISTORT = 4,
+ SIDEFX_PANTRACK = 8,
+ SIDEFX_REGION = 16,
+ SIDEFX_TIMER = 32,
+ SIDEFX_TTYTXT = 64,
+ SIDEFX_UNK = 128,
+ SIDEFX_ALL = 255
+ };
+
+ SideFX() : _engine(0), _key(0), _type(SIDEFX_UNK) {}
+ SideFX(ZVision *engine, uint32 key, SideFXType type) : _engine(engine), _key(key), _type(type) {}
+ virtual ~SideFX() {}
+
+ uint32 getKey() {
+ return _key;
+ }
+ SideFXType getType() {
+ return _type;
+ }
+
+ virtual bool process(uint32 deltaTimeInMillis) {
+ return false;
+ }
+ /**
+ * Serialize a SideFX for save game use. This should only be used if a SideFX needs
+ * to save values that would be different from initialization. AKA a TimerNode needs to
+ * store the amount of time left on the timer. Any Controls overriding this *MUST* write
+ * their key as the first data outputted. The default implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override deserialize()
+ * and needsSerialization()
+ *
+ * @param stream Stream to write any needed data to
+ */
+ virtual void serialize(Common::WriteStream *stream) {}
+ /**
+ * De-serialize data from a save game stream. This should only be implemented if the
+ * SideFX also implements serialize(). The calling method assumes the size of the
+ * data read from the stream exactly equals that written in serialize(). The default
+ * implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override serialize()
+ * and needsSerialization()
+ *
+ * @param stream Save game file stream
+ */
+ virtual void deserialize(Common::SeekableReadStream *stream) {}
+ /**
+ * If a SideFX overrides serialize() and deserialize(), this should return true
+ *
+ * @return Does the SideFX need save game serialization?
+ */
+ virtual inline bool needsSerialization() {
+ return false;
+ }
+
+ virtual bool stop() {
+ return true;
+ }
+ virtual void kill() {}
+
+protected:
+ ZVision *_engine;
+ uint32 _key;
+ SideFXType _type;
+
+// Static member functions
+public:
+
+};
+} // End of namespace ZVision
+
+#endif // SIDEFX_H_INCLUDED
diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp
new file mode 100644
index 0000000000..549aacba7f
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/animation_node.cpp
@@ -0,0 +1,204 @@
+/* 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 "zvision/scripting/sidefx/animation_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/animation/meta_animation.h"
+
+#include "graphics/surface.h"
+
+namespace ZVision {
+
+AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse)
+ : SideFX(engine, controlKey, SIDEFX_ANIM),
+ _DisposeAfterUse(DisposeAfterUse),
+ _mask(mask),
+ _animation(NULL) {
+
+ _animation = new MetaAnimation(fileName, engine);
+ _frmDelay = _animation->frameTime();
+
+ if (frate > 0)
+ _frmDelay = 1000.0 / frate;
+}
+
+AnimationNode::~AnimationNode() {
+ if (_animation)
+ delete _animation;
+
+ _engine->getScriptManager()->setStateValue(_key, 2);
+
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ _engine->getScriptManager()->setStateValue((*it).slot, 2);
+
+ if ((*it)._scaled)
+ delete(*it)._scaled;
+ }
+
+ _playList.clear();
+}
+
+bool AnimationNode::process(uint32 deltaTimeInMillis) {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ playnode *nod = &(*it);
+
+ nod->_delay -= deltaTimeInMillis;
+ if (nod->_delay <= 0) {
+ nod->_delay += _frmDelay;
+
+ const Graphics::Surface *frame = NULL;
+
+ if (nod->_curFrame == -1) { // Start of new playlist node
+ nod->_curFrame = nod->start;
+
+ _animation->seekToFrame(nod->_curFrame);
+ frame = _animation->decodeNextFrame();
+
+ nod->_delay = _frmDelay;
+ if (nod->slot)
+ _engine->getScriptManager()->setStateValue(nod->slot, 1);
+ } else {
+ nod->_curFrame++;
+
+ if (nod->_curFrame > nod->stop) {
+ nod->loop--;
+
+ if (nod->loop == 0) {
+ if (nod->slot >= 0)
+ _engine->getScriptManager()->setStateValue(nod->slot, 2);
+ if (nod->_scaled)
+ delete nod->_scaled;
+ _playList.erase(it);
+ return _DisposeAfterUse;
+ }
+
+ nod->_curFrame = nod->start;
+ _animation->seekToFrame(nod->_curFrame);
+ }
+
+ frame = _animation->decodeNextFrame();
+ }
+
+ if (frame) {
+
+ uint32 dstw;
+ uint32 dsth;
+ if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) {
+ dstw = nod->pos.height();
+ dsth = nod->pos.width();
+ } else {
+ dstw = nod->pos.width();
+ dsth = nod->pos.height();
+ }
+
+ if (frame->w != dstw || frame->h != dsth) {
+ if (nod->_scaled)
+ if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) {
+ delete nod->_scaled;
+ nod->_scaled = NULL;
+ }
+
+ if (!nod->_scaled) {
+ nod->_scaled = new Graphics::Surface;
+ nod->_scaled->create(dstw, dsth, frame->format);
+ }
+
+ _engine->getRenderManager()->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth);
+ frame = nod->_scaled;
+ }
+
+ if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) {
+ Graphics::Surface *transposed = RenderManager::tranposeSurface(frame);
+ if (_mask > 0)
+ _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask);
+ else
+ _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top);
+ delete transposed;
+ } else {
+ if (_mask > 0)
+ _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask);
+ else
+ _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops) {
+ playnode nod;
+ nod.loop = loops;
+ nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1);
+ nod.start = startFrame;
+ nod.stop = endFrame;
+
+ if (nod.stop >= (int)_animation->frameCount())
+ nod.stop = _animation->frameCount() - 1;
+
+ nod.slot = slot;
+ nod._curFrame = -1;
+ nod._delay = 0;
+ nod._scaled = NULL;
+ _playList.push_back(nod);
+}
+
+bool AnimationNode::stop() {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ _engine->getScriptManager()->setStateValue((*it).slot, 2);
+ if ((*it)._scaled)
+ delete(*it)._scaled;
+ }
+
+ _playList.clear();
+
+ // We don't need to delete, it's may be reused
+ return false;
+}
+
+void AnimationNode::setNewFrameDelay(int32 newDelay) {
+ if (newDelay > 0) {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ playnode *nod = &(*it);
+ float percent = (float)nod->_delay / (float)_frmDelay;
+ nod->_delay = percent * newDelay; // Scale to new max
+ }
+
+ _frmDelay = newDelay;
+ }
+}
+
+int32 AnimationNode::getFrameDelay() {
+ return _frmDelay;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h
new file mode 100644
index 0000000000..94428d2542
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/animation_node.h
@@ -0,0 +1,83 @@
+/* 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 ZVISION_ANIMATION_NODE_H
+#define ZVISION_ANIMATION_NODE_H
+
+#include "zvision/scripting/sidefx.h"
+#include "common/rect.h"
+#include "common/list.h"
+
+namespace Common {
+class String;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+class MetaAnimation;
+
+class AnimationNode : public SideFX {
+public:
+ AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse = true);
+ ~AnimationNode();
+
+ struct playnode {
+ Common::Rect pos;
+ int32 slot;
+ int32 start;
+ int32 stop;
+ int32 loop;
+ int32 _curFrame;
+ int32 _delay;
+ Graphics::Surface *_scaled;
+ };
+
+private:
+ typedef Common::List<playnode> PlayNodes;
+
+ PlayNodes _playList;
+
+ int32 _mask;
+ bool _DisposeAfterUse;
+
+ MetaAnimation *_animation;
+ int32 _frmDelay;
+
+public:
+ bool process(uint32 deltaTimeInMillis);
+
+ void addPlayNode(int32 slot, int x, int y, int x2, int y2, int startFrame, int endFrame, int loops = 1);
+
+ bool stop();
+
+ void setNewFrameDelay(int32 newDelay);
+ int32 getFrameDelay();
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/distort_node.cpp b/engines/zvision/scripting/sidefx/distort_node.cpp
new file mode 100644
index 0000000000..0d5c8b1ed5
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/distort_node.cpp
@@ -0,0 +1,105 @@
+/* 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 "zvision/scripting/sidefx/distort_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/graphics/render_table.h"
+
+#include "common/stream.h"
+
+namespace ZVision {
+
+DistortNode::DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale)
+ : SideFX(engine, key, SIDEFX_DISTORT) {
+
+ _angle = _engine->getRenderManager()->getRenderTable()->getAngle();
+ _linScale = _engine->getRenderManager()->getRenderTable()->getLinscale();
+
+ _speed = speed;
+ _incr = true;
+ _startAngle = startAngle;
+ _endAngle = endAngle;
+ _startLineScale = startLineScale;
+ _endLineScale = endLineScale;
+
+ _curFrame = 1.0;
+
+ _diffAngle = endAngle - startAngle;
+ _diffLinScale = endLineScale - startLineScale;
+
+ _frmSpeed = (float)speed / 15.0;
+ _frames = ceil((5.0 - _frmSpeed * 2.0) / _frmSpeed);
+ if (_frames <= 0)
+ _frames = 1;
+
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 1);
+}
+
+DistortNode::~DistortNode() {
+ setParams(_angle, _linScale);
+}
+
+bool DistortNode::process(uint32 deltaTimeInMillis) {
+
+ float updTime = deltaTimeInMillis / (1000.0 / 60.0);
+
+ if (_incr)
+ _curFrame += updTime;
+ else
+ _curFrame -= updTime;
+
+ if (_curFrame < 1.0) {
+ _curFrame = 1.0;
+ _incr = true;
+ } else if (_curFrame > _frames) {
+ _curFrame = _frames;
+ _incr = false;
+ }
+
+ float diff = (1.0 / (5.0 - (_curFrame * _frmSpeed))) / (5.0 - _frmSpeed);
+ setParams(_startAngle + diff * _diffAngle, _startLineScale + diff * _diffLinScale);
+
+ return false;
+}
+
+void DistortNode::setParams(float angl, float linScale) {
+ RenderTable *table = _engine->getRenderManager()->getRenderTable();
+ if (table->getRenderState() == RenderTable::PANORAMA) {
+ table->setPanoramaFoV(angl);
+ table->setPanoramaScale(linScale);
+ table->generateRenderTable();
+ _engine->getRenderManager()->markDirty();
+ } else if (table->getRenderState() == RenderTable::TILT) {
+ table->setTiltFoV(angl);
+ table->setTiltScale(linScale);
+ table->generateRenderTable();
+ _engine->getRenderManager()->markDirty();
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/distort_node.h b/engines/zvision/scripting/sidefx/distort_node.h
new file mode 100644
index 0000000000..787a69bdde
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/distort_node.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_DISTORT_NODE_H
+#define ZVISION_DISTORT_NODE_H
+
+#include "zvision/scripting/sidefx.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class DistortNode : public SideFX {
+public:
+ DistortNode(ZVision *engine, uint32 key, int16 speed, float startAngle, float endAngle, float startLineScale, float endLineScale);
+ ~DistortNode();
+
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ int16 _speed;
+ float _startAngle;
+ float _endAngle;
+ float _startLineScale;
+ float _endLineScale;
+
+ float _frmSpeed;
+ float _diffAngle;
+ float _diffLinScale;
+ bool _incr;
+ int16 _frames;
+
+ float _curFrame;
+
+ float _angle;
+ float _linScale;
+
+private:
+ void setParams(float angl, float linScale);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/sidefx/music_node.cpp
new file mode 100644
index 0000000000..a76d3b4e8d
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/music_node.cpp
@@ -0,0 +1,238 @@
+/* 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 "zvision/scripting/sidefx/music_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/core/midi.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/sound/zork_raw.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "audio/decoders/wave.h"
+
+namespace ZVision {
+
+MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume)
+ : MusicNodeBASE(engine, key, SIDEFX_AUDIO) {
+ _loop = loop;
+ _volume = volume;
+ _crossfade = false;
+ _crossfadeTarget = 0;
+ _crossfadeTime = 0;
+ _attenuate = 0;
+ _pantrack = false;
+ _pantrackPosition = 0;
+ _sub = NULL;
+
+ Audio::RewindableAudioStream *audioStream = NULL;
+
+ if (filename.contains(".wav")) {
+ Common::File *file = new Common::File();
+ if (_engine->getSearchManager()->openFile(*file, filename)) {
+ audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ }
+ } else {
+ audioStream = makeRawZorkStream(filename, _engine);
+ }
+
+ _stereo = audioStream->isStereo();
+
+ if (_loop) {
+ Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume);
+ } else {
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume);
+ }
+
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 1);
+
+ Common::String subname = filename;
+ subname.setChar('s', subname.size() - 3);
+ subname.setChar('u', subname.size() - 2);
+ subname.setChar('b', subname.size() - 1);
+
+ if (_engine->getSearchManager()->hasFile(subname))
+ _sub = new Subtitle(_engine, subname);
+}
+
+MusicNode::~MusicNode() {
+ _engine->_mixer->stopHandle(_handle);
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ if (_sub)
+ delete _sub;
+ debug(1, "MusicNode: %d destroyed\n", _key);
+}
+
+void MusicNode::setPanTrack(int16 pos) {
+ if (!_stereo) {
+ _pantrack = true;
+ _pantrackPosition = pos;
+ setVolume(_volume);
+ }
+}
+
+void MusicNode::unsetPanTrack() {
+ _pantrack = false;
+ setVolume(_volume);
+}
+
+void MusicNode::setFade(int32 time, uint8 target) {
+ _crossfadeTarget = target;
+ _crossfadeTime = time;
+ _crossfade = true;
+}
+
+bool MusicNode::process(uint32 deltaTimeInMillis) {
+ if (! _engine->_mixer->isSoundHandleActive(_handle))
+ return stop();
+ else {
+ uint8 _newvol = _volume;
+
+ if (_crossfade) {
+ if (_crossfadeTime > 0) {
+ if ((int32)deltaTimeInMillis > _crossfadeTime)
+ deltaTimeInMillis = _crossfadeTime;
+ _newvol += floor(((float)(_crossfadeTarget - _newvol) / (float)_crossfadeTime)) * (float)deltaTimeInMillis;
+ _crossfadeTime -= deltaTimeInMillis;
+ } else {
+ _crossfade = false;
+ _newvol = _crossfadeTarget;
+ }
+ }
+
+ if (_pantrack || _volume != _newvol)
+ setVolume(_newvol);
+
+ if (_sub)
+ _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100);
+ }
+ return false;
+}
+
+void MusicNode::setVolume(uint8 newVolume) {
+ if (_pantrack) {
+ int curX = _engine->getScriptManager()->getStateValue(StateKey_ViewPos);
+ curX -= _pantrackPosition;
+ int32 _width = _engine->getRenderManager()->getBkgSize().x;
+ if (curX < (-_width) / 2)
+ curX += _width;
+ else if (curX >= _width / 2)
+ curX -= _width;
+
+ float norm = (float)curX / ((float)_width / 2.0);
+ float lvl = fabs(norm);
+ if (lvl > 0.5)
+ lvl = (lvl - 0.5) * 1.7;
+ else
+ lvl = 1.0;
+
+ float bal = sin(-norm * 3.1415926) * 127.0;
+
+ if (_engine->_mixer->isSoundHandleActive(_handle)) {
+ _engine->_mixer->setChannelBalance(_handle, bal);
+ _engine->_mixer->setChannelVolume(_handle, newVolume * lvl);
+ }
+ } else {
+ if (_engine->_mixer->isSoundHandleActive(_handle)) {
+ _engine->_mixer->setChannelBalance(_handle, 0);
+ _engine->_mixer->setChannelVolume(_handle, newVolume);
+ }
+ }
+
+ _volume = newVolume;
+}
+
+PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos)
+ : SideFX(engine, key, SIDEFX_PANTRACK) {
+ _slot = slot;
+
+ SideFX *fx = _engine->getScriptManager()->getSideFX(slot);
+ if (fx && fx->getType() == SIDEFX_AUDIO) {
+ MusicNodeBASE *mus = (MusicNodeBASE *)fx;
+ mus->setPanTrack(pos);
+ }
+}
+
+PanTrackNode::~PanTrackNode() {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_slot);
+ if (fx && fx->getType() == SIDEFX_AUDIO) {
+ MusicNodeBASE *mus = (MusicNodeBASE *)fx;
+ mus->unsetPanTrack();
+ }
+}
+
+MusicMidiNode::MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume)
+ : MusicNodeBASE(engine, key, SIDEFX_AUDIO) {
+ _volume = volume;
+ _prog = program;
+ _noteNumber = note;
+ _pan = 0;
+
+ _chan = _engine->getMidiManager()->getFreeChannel();
+
+ if (_chan >= 0) {
+ _engine->getMidiManager()->setVolume(_chan, _volume);
+ _engine->getMidiManager()->setPan(_chan, _pan);
+ _engine->getMidiManager()->setProgram(_chan, _prog);
+ _engine->getMidiManager()->noteOn(_chan, _noteNumber, _volume);
+ }
+
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 1);
+}
+
+MusicMidiNode::~MusicMidiNode() {
+ if (_chan >= 0) {
+ _engine->getMidiManager()->noteOff(_chan);
+ }
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 2);
+}
+
+void MusicMidiNode::setPanTrack(int16 pos) {
+}
+
+void MusicMidiNode::unsetPanTrack() {
+}
+
+void MusicMidiNode::setFade(int32 time, uint8 target) {
+}
+
+bool MusicMidiNode::process(uint32 deltaTimeInMillis) {
+ return false;
+}
+
+void MusicMidiNode::setVolume(uint8 newVolume) {
+ if (_chan >= 0) {
+ _engine->getMidiManager()->setVolume(_chan, newVolume);
+ }
+ _volume = newVolume;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/sidefx/music_node.h
new file mode 100644
index 0000000000..c89345f0d0
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/music_node.h
@@ -0,0 +1,135 @@
+/* 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 ZVISION_MUSIC_NODE_H
+#define ZVISION_MUSIC_NODE_H
+
+#include "audio/mixer.h"
+#include "zvision/scripting/sidefx.h"
+#include "zvision/graphics/subtitles.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+
+class MusicNodeBASE : public SideFX {
+public:
+ MusicNodeBASE(ZVision *engine, uint32 key, SideFXType type) : SideFX(engine, key, type) {}
+ ~MusicNodeBASE() {}
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ virtual bool process(uint32 deltaTimeInMillis) = 0;
+
+ virtual void setVolume(uint8 volume) = 0;
+
+ virtual void setPanTrack(int16 pos) = 0;
+ virtual void unsetPanTrack() = 0;
+
+ virtual void setFade(int32 time, uint8 target) = 0;
+};
+
+class MusicNode : public MusicNodeBASE {
+public:
+ MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume);
+ ~MusicNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+
+ void setVolume(uint8 volume);
+
+ void setPanTrack(int16 pos);
+ void unsetPanTrack();
+
+ void setFade(int32 time, uint8 target);
+
+private:
+ int32 _timeLeft;
+ bool _pantrack;
+ int32 _pantrackPosition;
+ int32 _attenuate;
+ uint8 _volume;
+ bool _loop;
+ bool _crossfade;
+ uint8 _crossfadeTarget;
+ int32 _crossfadeTime;
+ bool _stereo;
+ Audio::SoundHandle _handle;
+ Subtitle *_sub;
+};
+
+class MusicMidiNode : public MusicNodeBASE {
+public:
+ MusicMidiNode(ZVision *engine, uint32 key, int8 program, int8 note, int8 volume);
+ ~MusicMidiNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+
+ void setVolume(uint8 volume);
+
+ void setPanTrack(int16 pos);
+ void unsetPanTrack();
+
+ void setFade(int32 time, uint8 target);
+
+private:
+ int8 _chan;
+ int8 _noteNumber;
+ int8 _velocity;
+ int8 _pan;
+ int8 _volume;
+ int8 _prog;
+};
+
+class PanTrackNode : public SideFX {
+public:
+ PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos);
+ ~PanTrackNode();
+
+private:
+ uint32 _slot;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/region_node.cpp b/engines/zvision/scripting/sidefx/region_node.cpp
new file mode 100644
index 0000000000..de613d8af2
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/region_node.cpp
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx/region_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+
+namespace ZVision {
+
+RegionNode::RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay)
+ : SideFX(engine, key, SIDEFX_REGION) {
+ _effect = effect;
+ _delay = delay;
+ _timeLeft = 0;
+}
+
+RegionNode::~RegionNode() {
+ _engine->getRenderManager()->deleteEffect(_key);
+}
+
+bool RegionNode::process(uint32 deltaTimeInMillis) {
+ _timeLeft -= deltaTimeInMillis;
+
+ if (_timeLeft <= 0) {
+ _timeLeft = _delay;
+ if (_effect)
+ _effect->update();
+ }
+
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/region_node.h b/engines/zvision/scripting/sidefx/region_node.h
new file mode 100644
index 0000000000..ec716b6e3e
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/region_node.h
@@ -0,0 +1,57 @@
+/* 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 ZVISION_REGION_NODE_H
+#define ZVISION_REGION_NODE_H
+
+#include "graphics/surface.h"
+
+#include "zvision/scripting/sidefx.h"
+#include "zvision/graphics/effect.h"
+
+namespace ZVision {
+
+class ZVision;
+
+class RegionNode : public SideFX {
+public:
+ RegionNode(ZVision *engine, uint32 key, Effect *effect, uint32 delay);
+ ~RegionNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ int32 _timeLeft;
+ uint32 _delay;
+ Effect *_effect;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/syncsound_node.cpp b/engines/zvision/scripting/sidefx/syncsound_node.cpp
new file mode 100644
index 0000000000..c1f139694b
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/syncsound_node.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 "zvision/scripting/sidefx/syncsound_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/sound/zork_raw.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "audio/decoders/wave.h"
+
+namespace ZVision {
+
+SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto)
+ : SideFX(engine, key, SIDEFX_AUDIO) {
+ _syncto = syncto;
+ _sub = NULL;
+
+ Audio::RewindableAudioStream *audioStream = NULL;
+
+ if (filename.contains(".wav")) {
+ Common::File *file = new Common::File();
+ if (_engine->getSearchManager()->openFile(*file, filename)) {
+ audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ }
+ } else {
+ audioStream = makeRawZorkStream(filename, _engine);
+ }
+
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream);
+
+ Common::String subname = filename;
+ subname.setChar('s', subname.size() - 3);
+ subname.setChar('u', subname.size() - 2);
+ subname.setChar('b', subname.size() - 1);
+
+ if (_engine->getSearchManager()->hasFile(subname))
+ _sub = new Subtitle(_engine, subname);
+}
+
+SyncSoundNode::~SyncSoundNode() {
+ _engine->_mixer->stopHandle(_handle);
+ if (_sub)
+ delete _sub;
+}
+
+bool SyncSoundNode::process(uint32 deltaTimeInMillis) {
+ if (! _engine->_mixer->isSoundHandleActive(_handle))
+ return stop();
+ else {
+
+ if (_engine->getScriptManager()->getSideFX(_syncto) == NULL)
+ return stop();
+
+ if (_sub)
+ _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100);
+ }
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/syncsound_node.h b/engines/zvision/scripting/sidefx/syncsound_node.h
new file mode 100644
index 0000000000..7cd02a8aef
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/syncsound_node.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_SYNCSOUND_NODE_H
+#define ZVISION_SYNCSOUND_NODE_H
+
+#include "audio/mixer.h"
+#include "zvision/scripting/sidefx.h"
+#include "zvision/graphics/subtitles.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+class SyncSoundNode : public SideFX {
+public:
+ SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto);
+ ~SyncSoundNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+private:
+ int32 _syncto;
+ Audio::SoundHandle _handle;
+ Subtitle *_sub;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/timer_node.cpp b/engines/zvision/scripting/sidefx/timer_node.cpp
index c8c8a85d34..abf2c90b04 100644
--- a/engines/zvision/scripting/controls/timer_node.cpp
+++ b/engines/zvision/scripting/sidefx/timer_node.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -22,46 +22,52 @@
#include "common/scummsys.h"
-#include "zvision/scripting/controls/timer_node.h"
+#include "zvision/scripting/sidefx/timer_node.h"
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
#include "common/stream.h"
-
namespace ZVision {
-
+
TimerNode::TimerNode(ZVision *engine, uint32 key, uint timeInSeconds)
- : Control(engine, key) {
- if (_engine->getGameId() == GID_NEMESIS) {
+ : SideFX(engine, key, SIDEFX_TIMER) {
+ if (_engine->getGameId() == GID_NEMESIS)
_timeLeft = timeInSeconds * 1000;
- } else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
+ else if (_engine->getGameId() == GID_GRANDINQUISITOR)
_timeLeft = timeInSeconds * 100;
- }
- _engine->getScriptManager()->setStateValue(_key, 1);
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 1);
}
TimerNode::~TimerNode() {
- if (_timeLeft <= 0)
+ if (_key != StateKey_NotSet)
_engine->getScriptManager()->setStateValue(_key, 2);
- else
- _engine->getScriptManager()->setStateValue(_key, _timeLeft); // If timer was stopped by stop or kill
+ int32 timeLeft = _timeLeft / (_engine->getGameId() == GID_NEMESIS ? 1000 : 100);
+ if (timeLeft > 0)
+ _engine->getScriptManager()->setStateValue(_key, timeLeft); // If timer was stopped by stop or kill
}
bool TimerNode::process(uint32 deltaTimeInMillis) {
_timeLeft -= deltaTimeInMillis;
- if (_timeLeft <= 0) {
- // Let the destructor reset the state value
- return true;
- }
+ if (_timeLeft <= 0)
+ return stop();
return false;
}
+bool TimerNode::stop() {
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ return true;
+}
+
void TimerNode::serialize(Common::WriteStream *stream) {
+ stream->writeUint32BE(MKTAG('T', 'I', 'M', 'R'));
+ stream->writeUint32LE(8); // size
stream->writeUint32LE(_key);
stream->writeUint32LE(_timeLeft);
}
diff --git a/engines/zvision/scripting/controls/timer_node.h b/engines/zvision/scripting/sidefx/timer_node.h
index 48b5fad1e9..7a26aff251 100644
--- a/engines/zvision/scripting/controls/timer_node.h
+++ b/engines/zvision/scripting/sidefx/timer_node.h
@@ -8,12 +8,12 @@
* 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.
@@ -23,13 +23,13 @@
#ifndef ZVISION_TIMER_NODE_H
#define ZVISION_TIMER_NODE_H
-#include "zvision/scripting/control.h"
+#include "zvision/scripting/sidefx.h"
namespace ZVision {
class ZVision;
-class TimerNode : public Control {
+class TimerNode : public SideFX {
public:
TimerNode(ZVision *engine, uint32 key, uint timeInSeconds);
~TimerNode();
@@ -44,7 +44,11 @@ public:
bool process(uint32 deltaTimeInMillis);
void serialize(Common::WriteStream *stream);
void deserialize(Common::SeekableReadStream *stream);
- inline bool needsSerialization() { return true; }
+ inline bool needsSerialization() {
+ return true;
+ }
+
+ bool stop();
private:
int32 _timeLeft;
diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/sidefx/ttytext_node.cpp
new file mode 100644
index 0000000000..1fb7c10792
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/ttytext_node.cpp
@@ -0,0 +1,174 @@
+/* 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 "zvision/scripting/sidefx/ttytext_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/text/text.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+
+namespace ZVision {
+
+ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) :
+ SideFX(engine, key, SIDEFX_TTYTXT),
+ _fnt(engine) {
+ _delay = delay;
+ _r = r;
+ _txtpos = 0;
+ _nexttime = 0;
+ _dx = 0;
+ _dy = 0;
+
+ Common::File *infile = _engine->getSearchManager()->openFile(file);
+ if (infile) {
+ while (!infile->eos()) {
+ Common::String asciiLine = readWideLine(*infile);
+ if (asciiLine.empty()) {
+ continue;
+ }
+ _txtbuf += asciiLine;
+ }
+
+ delete infile;
+ }
+ _img.create(_r.width(), _r.height(), _engine->_pixelFormat);
+ _style.sharp = true;
+ _style.readAllStyle(_txtbuf);
+ _style.setFont(_fnt);
+ _engine->getScriptManager()->setStateValue(_key, 1);
+}
+
+ttyTextNode::~ttyTextNode() {
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ _img.free();
+}
+
+bool ttyTextNode::process(uint32 deltaTimeInMillis) {
+ _nexttime -= deltaTimeInMillis;
+
+ if (_nexttime < 0) {
+ if (_txtpos < _txtbuf.size()) {
+ if (_txtbuf[_txtpos] == '<') {
+ int32 strt = _txtpos;
+ int32 endt = 0;
+ int16 ret = 0;
+ while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size())
+ _txtpos++;
+ endt = _txtpos;
+ if (strt != -1)
+ if ((endt - strt - 1) > 0)
+ ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1);
+
+ if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) {
+ if (ret & TXT_RET_FNTCHG)
+ _style.setFont(_fnt);
+ if (ret & TXT_RET_FNTSTL)
+ _style.setFontStyle(_fnt);
+
+ if (ret & TXT_RET_NEWLN)
+ newline();
+ }
+
+ if (ret & TXT_RET_HASSTBOX) {
+ Common::String buf;
+ buf.format("%d", _style.statebox);
+
+ for (uint8 j = 0; j < buf.size(); j++)
+ outchar(buf[j]);
+ }
+
+ _txtpos++;
+ } else {
+ int8 charsz = getUtf8CharSize(_txtbuf[_txtpos]);
+
+ uint16 chr = readUtf8Char(_txtbuf.c_str() + _txtpos);
+
+ if (chr == ' ') {
+ uint32 i = _txtpos + charsz;
+ uint16 width = _fnt.getCharWidth(chr);
+
+ while (i < _txtbuf.size() && _txtbuf[i] != ' ' && _txtbuf[i] != '<') {
+
+ int8 chsz = getUtf8CharSize(_txtbuf[i]);
+ uint16 uchr = readUtf8Char(_txtbuf.c_str() + _txtpos);
+
+ width += _fnt.getCharWidth(uchr);
+
+ i += chsz;
+ }
+
+ if (_dx + width > _r.width())
+ newline();
+ else
+ outchar(chr);
+ } else
+ outchar(chr);
+
+ _txtpos += charsz;
+ }
+ _nexttime = _delay;
+ _engine->getRenderManager()->blitSurfaceToBkg(_img, _r.left, _r.top);
+ } else
+ return stop();
+ }
+
+ return false;
+}
+
+void ttyTextNode::scroll() {
+ int32 scrl = 0;
+ while (_dy - scrl > _r.height() - _fnt.getFontHeight())
+ scrl += _fnt.getFontHeight();
+ int8 *pixels = (int8 *)_img.getPixels();
+ for (uint16 h = scrl; h < _img.h; h++)
+ memcpy(pixels + _img.pitch * (h - scrl), pixels + _img.pitch * h, _img.pitch);
+
+ _img.fillRect(Common::Rect(0, _img.h - scrl, _img.w, _img.h), 0);
+ _dy -= scrl;
+}
+
+void ttyTextNode::newline() {
+ _dy += _fnt.getFontHeight();
+ _dx = 0;
+}
+
+void ttyTextNode::outchar(uint16 chr) {
+ uint32 clr = _engine->_pixelFormat.RGBToColor(_style.red, _style.green, _style.blue);
+
+ if (_dx + _fnt.getCharWidth(chr) > _r.width())
+ newline();
+
+ if (_dy + _fnt.getFontHeight() >= _r.height())
+ scroll();
+
+ _fnt.drawChar(&_img, chr, _dx, _dy, clr);
+
+ _dx += _fnt.getCharWidth(chr);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/ttytext_node.h b/engines/zvision/scripting/sidefx/ttytext_node.h
new file mode 100644
index 0000000000..b6cbed3e34
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/ttytext_node.h
@@ -0,0 +1,73 @@
+/* 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 ZVISION_TTYTEXT_NODE_H
+#define ZVISION_TTYTEXT_NODE_H
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+#include "zvision/scripting/sidefx.h"
+#include "zvision/text/text.h"
+#include "zvision/graphics/truetype_font.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+class ttyTextNode : public SideFX {
+public:
+ ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay);
+ ~ttyTextNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+private:
+ Common::Rect _r;
+
+ cTxtStyle _style;
+ StyledTTFont _fnt;
+ Common::String _txtbuf;
+ uint32 _txtpos;
+
+ int32 _delay;
+ int32 _nexttime;
+ Graphics::Surface _img;
+ int16 _dx;
+ int16 _dy;
+private:
+
+ void newline();
+ void scroll();
+ void outchar(uint16 chr);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp
index edee1fd16e..c26c33a392 100644
--- a/engines/zvision/sound/zork_raw.cpp
+++ b/engines/zvision/sound/zork_raw.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -21,85 +21,79 @@
*/
#include "common/scummsys.h"
-
-#include "zvision/sound/zork_raw.h"
-
-#include "zvision/zvision.h"
-#include "zvision/detection.h"
-#include "zvision/utility/utility.h"
-
#include "common/file.h"
#include "common/str.h"
#include "common/stream.h"
#include "common/memstream.h"
#include "common/bufferedstream.h"
#include "common/util.h"
-
+#include "common/tokenizer.h"
#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
+#include "zvision/sound/zork_raw.h"
+#include "zvision/zvision.h"
+#include "zvision/detection.h"
+#include "zvision/utility/utility.h"
namespace ZVision {
-const int16 RawZorkStream::_stepAdjustmentTable[8] = {-1, -1, -1, 1, 4, 7, 10, 12};
-
-const int32 RawZorkStream::_amplitudeLookupTable[89] = {0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E,
- 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F,
- 0x0022, 0x0025, 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042,
- 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, 0x0082, 0x008F,
- 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
- 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292,
- 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583,
- 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, 0x0BD0,
- 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954,
- 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
- 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF};
-
-const SoundParams RawZorkStream::_zNemSoundParamLookupTable[6] = {{'6', 0x2B11, false, false},
- {'a', 0x5622, false, true},
- {'b', 0x5622, true, true},
- {'n', 0x2B11, false, true},
- {'s', 0x5622, false, true},
- {'t', 0x5622, true, true}
-};
-
-const SoundParams RawZorkStream::_zgiSoundParamLookupTable[5] = {{'a',0x5622, false, false},
- {'k',0x2B11, true, true},
- {'p',0x5622, false, true},
- {'q',0x5622, true, true},
- {'u',0xAC44, true, true}
-};
-
-RawZorkStream::RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream)
- : _rate(rate),
- _stereo(0),
- _stream(stream, disposeStream),
- _endOfData(false) {
+const int16 RawChunkStream::_stepAdjustmentTable[8] = { -1, -1, -1, 1, 4, 7, 10, 12};
+
+const int32 RawChunkStream::_amplitudeLookupTable[89] = {0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E,
+ 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F,
+ 0x0022, 0x0025, 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042,
+ 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, 0x0082, 0x008F,
+ 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
+ 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292,
+ 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583,
+ 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, 0x0BD0,
+ 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954,
+ 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
+ 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF
+ };
+
+RawChunkStream::RawChunkStream(bool stereo) {
if (stereo)
_stereo = 1;
+ else
+ _stereo = 0;
+
+ init();
+}
+void RawChunkStream::init() {
_lastSample[0].index = 0;
_lastSample[0].sample = 0;
_lastSample[1].index = 0;
_lastSample[1].sample = 0;
+}
- // Calculate the total playtime of the stream
- if (stereo)
- _playtime = Audio::Timestamp(0, _stream->size() / 2, rate);
- else
- _playtime = Audio::Timestamp(0, _stream->size(), rate);
+RawChunkStream::RawChunk RawChunkStream::readNextChunk(Common::SeekableReadStream *stream) {
+ RawChunk tmp;
+ tmp.size = 0;
+ tmp.data = NULL;
+
+ if (stream && (stream->size() == 0 || stream->eos()))
+ return tmp;
+
+ tmp.size = (stream->size() - stream->pos()) * 2;
+ tmp.data = (int16 *)calloc(tmp.size, 1);
+
+ readBuffer(tmp.data, stream, stream->size() - stream->pos());
+
+ return tmp;
}
-int RawZorkStream::readBuffer(int16 *buffer, const int numSamples) {
- int bytesRead = 0;
+int RawChunkStream::readBuffer(int16 *buffer, Common::SeekableReadStream *stream, const int numSamples) {
+ int32 bytesRead = 0;
// 0: Left, 1: Right
uint channel = 0;
while (bytesRead < numSamples) {
- byte encodedSample = _stream->readByte();
- if (_stream->eos()) {
- _endOfData = true;
+ byte encodedSample = stream->readByte();
+ if (stream->eos()) {
return bytesRead;
}
bytesRead++;
@@ -140,6 +134,91 @@ int RawZorkStream::readBuffer(int16 *buffer, const int numSamples) {
// Increment and wrap the channel
channel = (channel + 1) & _stereo;
}
+ return bytesRead;
+}
+
+const SoundParams RawZorkStream::_zNemSoundParamLookupTable[32] = {{'0', 0x1F40, false, false, false},
+ {'1', 0x1F40, true, false, false},
+ {'2', 0x1F40, false, false, true},
+ {'3', 0x1F40, true, false, true},
+ {'4', 0x2B11, false, false, false},
+ {'5', 0x2B11, true, false, false},
+ {'6', 0x2B11, false, false, true},
+ {'7', 0x2B11, true, false, true},
+ {'8', 0x5622, false, false, false},
+ {'9', 0x5622, true, false, false},
+ {'a', 0x5622, false, false, true},
+ {'b', 0x5622, true, false, true},
+ {'c', 0xAC44, false, false, false},
+ {'d', 0xAC44, true, false, false},
+ {'e', 0xAC44, false, false, true},
+ {'f', 0xAC44, true, false, true},
+ {'g', 0x1F40, false, true, false},
+ {'h', 0x1F40, true, true, false},
+ {'j', 0x1F40, false, true, true},
+ {'k', 0x1F40, true, true, true},
+ {'l', 0x2B11, false, true, false},
+ {'m', 0x2B11, true, true, false},
+ {'n', 0x2B11, false, true, true},
+ {'p', 0x2B11, true, true, true},
+ {'q', 0x5622, false, true, false},
+ {'r', 0x5622, true, true, false},
+ {'s', 0x5622, false, true, true},
+ {'t', 0x5622, true, true, true},
+ {'u', 0xAC44, false, true, false},
+ {'v', 0xAC44, true, true, false},
+ {'w', 0xAC44, false, true, true},
+ {'x', 0xAC44, true, true, true}
+};
+
+const SoundParams RawZorkStream::_zgiSoundParamLookupTable[24] = {{'4', 0x2B11, false, false, false},
+ {'5', 0x2B11, true, false, false},
+ {'6', 0x2B11, false, false, true},
+ {'7', 0x2B11, true, false, true},
+ {'8', 0x5622, false, false, false},
+ {'9', 0x5622, true, false, false},
+ {'a', 0x5622, false, false, true},
+ {'b', 0x5622, true, false, true},
+ {'c', 0xAC44, false, false, false},
+ {'d', 0xAC44, true, false, false},
+ {'e', 0xAC44, false, false, true},
+ {'f', 0xAC44, true, false, true},
+ {'g', 0x2B11, false, true, false},
+ {'h', 0x2B11, true, true, false},
+ {'j', 0x2B11, false, true, true},
+ {'k', 0x2B11, true, true, true},
+ {'m', 0x5622, false, true, false},
+ {'n', 0x5622, true, true, false},
+ {'p', 0x5622, false, true, true},
+ {'q', 0x5622, true, true, true},
+ {'r', 0xAC44, false, true, false},
+ {'s', 0xAC44, true, true, false},
+ {'t', 0xAC44, false, true, true},
+ {'u', 0xAC44, true, true, true}
+};
+
+RawZorkStream::RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream)
+ : _rate(rate),
+ _stereo(0),
+ _stream(stream, disposeStream),
+ _endOfData(false),
+ _streamReader(stereo) {
+ if (stereo)
+ _stereo = 1;
+
+ // Calculate the total playtime of the stream
+ if (stereo)
+ _playtime = Audio::Timestamp(0, _stream->size() / 2, rate);
+ else
+ _playtime = Audio::Timestamp(0, _stream->size(), rate);
+}
+
+int RawZorkStream::readBuffer(int16 *buffer, const int numSamples) {
+
+ int32 bytesRead = _streamReader.readBuffer(buffer, _stream.get(), numSamples);
+
+ if (_stream->eos())
+ _endOfData = true;
return bytesRead;
}
@@ -148,18 +227,15 @@ bool RawZorkStream::rewind() {
_stream->seek(0, 0);
_stream->clearErr();
_endOfData = false;
- _lastSample[0].index = 0;
- _lastSample[0].sample = 0;
- _lastSample[1].index = 0;
- _lastSample[1].sample = 0;
+ _streamReader.init();
return true;
}
Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stream,
- int rate,
- bool stereo,
- DisposeAfterUse::Flag disposeAfterUse) {
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse) {
if (stereo)
assert(stream->size() % 2 == 0);
@@ -167,46 +243,45 @@ Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stre
}
Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size,
- int rate,
- bool stereo,
- DisposeAfterUse::Flag disposeAfterUse) {
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse) {
return makeRawZorkStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, stereo, DisposeAfterUse::YES);
}
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) {
Common::File *file = new Common::File();
- assert(file->open(filePath));
+ assert(engine->getSearchManager()->openFile(*file, filePath));
+
+ // Get the file name
+ Common::StringTokenizer tokenizer(filePath, "/\\");
+ Common::String fileName;
+ while (!tokenizer.empty()) {
+ fileName = tokenizer.nextToken();
+ }
- Common::String fileName = getFileName(filePath);
fileName.toLowercase();
- SoundParams soundParams = { ' ', 0, false, false };
- bool foundParams = false;
- char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7];
+ SoundParams soundParams = {};
if (engine->getGameId() == GID_NEMESIS) {
- for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zNemSoundParamLookupTable); ++i) {
- if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) {
+ for (int i = 0; i < 32; ++i) {
+ if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (fileName[6]))
soundParams = RawZorkStream::_zNemSoundParamLookupTable[i];
- foundParams = true;
- }
}
} else if (engine->getGameId() == GID_GRANDINQUISITOR) {
- for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zgiSoundParamLookupTable); ++i) {
- if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) {
+ for (int i = 0; i < 24; ++i) {
+ if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (fileName[7]))
soundParams = RawZorkStream::_zgiSoundParamLookupTable[i];
- foundParams = true;
- }
}
}
- if (!foundParams)
- error("Unable to find sound params for file '%s'. File identifier is '%c'", filePath.c_str(), fileIdentifier);
-
if (soundParams.packed) {
return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams.rate, soundParams.stereo, DisposeAfterUse::YES);
} else {
byte flags = 0;
+ if (soundParams.bits16)
+ flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
if (soundParams.stereo)
flags |= Audio::FLAG_STEREO;
diff --git a/engines/zvision/sound/zork_raw.h b/engines/zvision/sound/zork_raw.h
index ef98e3e1ef..0b408d818c 100644
--- a/engines/zvision/sound/zork_raw.h
+++ b/engines/zvision/sound/zork_raw.h
@@ -8,12 +8,12 @@
* 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.
@@ -25,7 +25,6 @@
#include "audio/audiostream.h"
-
namespace Common {
class SeekableReadStream;
}
@@ -39,27 +38,19 @@ struct SoundParams {
uint32 rate;
bool stereo;
bool packed;
+ bool bits16;
};
/**
- * This is a stream, which allows for playing raw ADPCM data from a stream.
+ * This is a ADPCM stream-reader, this class holds context for multi-chunk reading and no buffers.
*/
-class RawZorkStream : public Audio::RewindableAudioStream {
+class RawChunkStream {
public:
- RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream);
+ RawChunkStream(bool stereo);
- ~RawZorkStream() {
+ ~RawChunkStream() {
}
-
-public:
- static const SoundParams _zNemSoundParamLookupTable[6];
- static const SoundParams _zgiSoundParamLookupTable[5];
-
private:
- const int _rate; // Sample rate of stream
- Audio::Timestamp _playtime; // Calculated total play time
- Common::DisposablePtr<Common::SeekableReadStream> _stream; // Stream to read data from
- bool _endOfData; // Whether the stream end has been reached
uint _stereo;
/**
@@ -75,13 +66,58 @@ private:
static const int32 _amplitudeLookupTable[89];
public:
+
+ struct RawChunk {
+ int16 *data;
+ uint32 size;
+ };
+
+ void init();
+ //Read next audio portion in new stream (needed for avi), return structure with buffer
+ RawChunk readNextChunk(Common::SeekableReadStream *stream);
+ //Read numSamples from stream to buffer
+ int readBuffer(int16 *buffer, Common::SeekableReadStream *stream, const int numSamples);
+};
+
+/**
+ * This is a stream, which allows for playing raw ADPCM data from a stream.
+ */
+class RawZorkStream : public Audio::RewindableAudioStream {
+public:
+ RawZorkStream(uint32 rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream);
+
+ ~RawZorkStream() {
+ }
+
+public:
+ static const SoundParams _zNemSoundParamLookupTable[32];
+ static const SoundParams _zgiSoundParamLookupTable[24];
+
+private:
+ const int _rate; // Sample rate of stream
+ Audio::Timestamp _playtime; // Calculated total play time
+ Common::DisposablePtr<Common::SeekableReadStream> _stream; // Stream to read data from
+ bool _endOfData; // Whether the stream end has been reached
+ uint _stereo;
+
+ RawChunkStream _streamReader;
+
+public:
int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return true; }
- bool endOfData() const { return _endOfData; }
+ bool isStereo() const {
+ return _stereo;
+ }
+ bool endOfData() const {
+ return _endOfData;
+ }
- int getRate() const { return _rate; }
- Audio::Timestamp getLength() const { return _playtime; }
+ int getRate() const {
+ return _rate;
+ }
+ Audio::Timestamp getLength() const {
+ return _playtime;
+ }
bool rewind();
};
@@ -96,9 +132,9 @@ public:
* @return The new SeekableAudioStream (or 0 on failure).
*/
Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size,
- int rate,
- bool stereo,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
/**
* Creates an audio stream, which plays from the given stream.
@@ -109,9 +145,9 @@ Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size,
* @return The new SeekableAudioStream (or 0 on failure).
*/
Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stream,
- int rate,
- bool stereo,
- DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+ int rate,
+ bool stereo,
+ DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine);
diff --git a/engines/zvision/strings/string_manager.cpp b/engines/zvision/text/string_manager.cpp
index 22331d8a24..1a04c67988 100644
--- a/engines/zvision/strings/string_manager.cpp
+++ b/engines/zvision/text/string_manager.cpp
@@ -21,18 +21,16 @@
*/
#include "common/scummsys.h"
-
-#include "zvision/strings/string_manager.h"
-
-#include "zvision/fonts/truetype_font.h"
-
#include "common/file.h"
#include "common/tokenizer.h"
#include "common/debug.h"
-
#include "graphics/fontman.h"
#include "graphics/colormasks.h"
+#include "zvision/zvision.h"
+#include "zvision/core/search_manager.h"
+#include "zvision/text/string_manager.h"
+#include "zvision/graphics/truetype_font.h"
namespace ZVision {
@@ -49,10 +47,25 @@ StringManager::~StringManager() {
void StringManager::initialize(ZVisionGameId gameId) {
if (gameId == GID_NEMESIS) {
// TODO: Check this hardcoded filename against all versions of Nemesis
- parseStrFile("nemesis.str");
+ loadStrFile("nemesis.str");
} else if (gameId == GID_GRANDINQUISITOR) {
// TODO: Check this hardcoded filename against all versions of Grand Inquisitor
- parseStrFile("inquis.str");
+ loadStrFile("inquis.str");
+ }
+}
+
+void StringManager::loadStrFile(const Common::String &fileName) {
+ Common::File file;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("%s does not exist. String parsing failed", fileName.c_str());
+ return;
+ }
+ uint lineNumber = 0;
+ while (!file.eos()) {
+ _lines[lineNumber] = readWideLine(file);
+
+ lineNumber++;
+ assert(lineNumber <= NUM_TEXT_LINES);
}
}
@@ -252,4 +265,8 @@ StringManager::TextStyle StringManager::getTextStyle(uint stringNumber) {
return _inGameText[stringNumber].fragments.front().style;
}
+const Common::String StringManager::getTextLine(uint stringNumber) {
+ return _lines[stringNumber];
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/strings/string_manager.h b/engines/zvision/text/string_manager.h
index af8324b890..8d6fbe67a6 100644
--- a/engines/zvision/strings/string_manager.h
+++ b/engines/zvision/text/string_manager.h
@@ -24,8 +24,7 @@
#define ZVISION_STRING_MANAGER_H
#include "zvision/detection.h"
-#include "zvision/fonts/truetype_font.h"
-
+#include "zvision/graphics/truetype_font.h"
namespace Graphics {
class FontManager;
@@ -52,6 +51,13 @@ public:
Common::String text;
};
+ enum {
+ ZVISION_STR_SAVEEXIST = 23,
+ ZVISION_STR_SAVED = 4,
+ ZVISION_STR_SAVEEMPTY = 21,
+ ZVISION_STR_EXITPROMT = 6
+ };
+
private:
struct InGameText {
Common::List<TextFragment> fragments;
@@ -63,6 +69,8 @@ private:
private:
ZVision *_engine;
+ Common::String _lines[NUM_TEXT_LINES];
+
InGameText _inGameText[NUM_TEXT_LINES];
Common::HashMap<Common::String, TruetypeFont *> _fonts;
@@ -71,8 +79,10 @@ private:
public:
void initialize(ZVisionGameId gameId);
StringManager::TextStyle getTextStyle(uint stringNumber);
+ const Common::String getTextLine(uint stringNumber);
private:
+ void loadStrFile(const Common::String &fileName);
void parseStrFile(const Common::String &fileName);
void parseTag(const Common::String &tagString, uint lineNumber);
diff --git a/engines/zvision/text/text.cpp b/engines/zvision/text/text.cpp
new file mode 100644
index 0000000000..0ccca214d7
--- /dev/null
+++ b/engines/zvision/text/text.cpp
@@ -0,0 +1,544 @@
+/* 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/file.h"
+#include "common/tokenizer.h"
+#include "common/debug.h"
+#include "common/rect.h"
+#include "graphics/fontman.h"
+#include "graphics/colormasks.h"
+#include "graphics/surface.h"
+#include "graphics/font.h"
+#include "graphics/fonts/ttf.h"
+
+#include "zvision/text/text.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/graphics/truetype_font.h"
+#include "zvision/scripting/script_manager.h"
+
+namespace ZVision {
+
+cTxtStyle::cTxtStyle() {
+ fontname = "Arial";
+ blue = 255;
+ green = 255;
+ red = 255;
+ bold = false;
+ escapement = 0;
+ italic = false;
+ justify = TXT_JUSTIFY_LEFT;
+ newline = false;
+ size = 12;
+ skipcolor = false;
+ strikeout = false;
+ underline = false;
+ statebox = 0;
+ sharp = false;
+}
+
+txtReturn cTxtStyle::parseStyle(const Common::String &strin, int16 ln) {
+ Common::String buf = Common::String(strin.c_str(), ln);
+
+ int8 retval = TXT_RET_NOTHING;
+
+ Common::StringTokenizer tokenizer(buf, " ");
+ Common::String token;
+
+ while (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+
+ if (token.matchString("font", true)) {
+ token = tokenizer.nextToken();
+ if (token[0] == '"') {
+ Common::String _tmp = Common::String(token.c_str() + 1);
+
+ while (token.lastChar() != '"' && !tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ _tmp += " " + token;
+ }
+
+ if (_tmp.lastChar() == '"')
+ _tmp.deleteLastChar();
+
+ fontname = _tmp;
+ } else {
+ if (!tokenizer.empty())
+ fontname = token;
+ }
+ retval |= TXT_RET_FNTCHG;
+
+ } else if (token.matchString("blue", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ int32 tmp = atoi(token.c_str());
+ if (blue != tmp) {
+ blue = tmp;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ } else if (token.matchString("red", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ int32 tmp = atoi(token.c_str());
+ if (red != tmp) {
+ red = tmp;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ } else if (token.matchString("green", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ int32 tmp = atoi(token.c_str());
+ if (green != tmp) {
+ green = tmp;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ } else if (token.matchString("newline", true)) {
+ if ((retval & TXT_RET_NEWLN) == 0)
+ newline = 0;
+
+ newline++;
+ retval |= TXT_RET_NEWLN;
+ } else if (token.matchString("point", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ int32 tmp = atoi(token.c_str());
+ if (size != tmp) {
+ size = tmp;
+ retval |= TXT_RET_FNTCHG;
+ }
+ }
+ } else if (token.matchString("escapement", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ int32 tmp = atoi(token.c_str());
+ escapement = tmp;
+ }
+ } else if (token.matchString("italic", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", true)) {
+ if (italic != true) {
+ italic = true;
+ retval |= TXT_RET_FNTSTL;
+ }
+ } else if (token.matchString("off", true)) {
+ if (italic != false) {
+ italic = false;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ }
+ } else if (token.matchString("underline", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", true)) {
+ if (underline != true) {
+ underline = true;
+ retval |= TXT_RET_FNTSTL;
+ }
+ } else if (token.matchString("off", true)) {
+ if (underline != false) {
+ underline = false;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ }
+ } else if (token.matchString("strikeout", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", true)) {
+ if (strikeout != true) {
+ strikeout = true;
+ retval |= TXT_RET_FNTSTL;
+ }
+ } else if (token.matchString("off", true)) {
+ if (strikeout != false) {
+ strikeout = false;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ }
+ } else if (token.matchString("bold", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", true)) {
+ if (bold != true) {
+ bold = true;
+ retval |= TXT_RET_FNTSTL;
+ }
+ } else if (token.matchString("off", true)) {
+ if (bold != false) {
+ bold = false;
+ retval |= TXT_RET_FNTSTL;
+ }
+ }
+ }
+ } else if (token.matchString("skipcolor", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("on", true)) {
+ skipcolor = true;
+ } else if (token.matchString("off", true)) {
+ skipcolor = false;
+ }
+ }
+ } else if (token.matchString("image", true)) {
+ // Not used
+ } else if (token.matchString("statebox", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ statebox = atoi(token.c_str());
+ retval |= TXT_RET_HASSTBOX;
+ }
+ } else if (token.matchString("justify", true)) {
+ if (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ if (token.matchString("center", true))
+ justify = TXT_JUSTIFY_CENTER;
+ else if (token.matchString("left", true))
+ justify = TXT_JUSTIFY_LEFT;
+ else if (token.matchString("right", true))
+ justify = TXT_JUSTIFY_RIGHT;
+ }
+ }
+ }
+ return (txtReturn)retval;
+}
+
+void cTxtStyle::readAllStyle(const Common::String &txt) {
+ int16 startTextPosition = -1;
+ int16 endTextPosition = -1;
+
+ for (uint16 i = 0; i < txt.size(); i++) {
+ if (txt[i] == '<')
+ startTextPosition = i;
+ else if (txt[i] == '>') {
+ endTextPosition = i;
+ if (startTextPosition != -1)
+ if ((endTextPosition - startTextPosition - 1) > 0)
+ parseStyle(Common::String(txt.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1);
+ }
+
+ }
+}
+
+void cTxtStyle::setFontStyle(StyledTTFont &font) {
+ uint tempStyle = 0;
+
+ if (bold)
+ tempStyle |= StyledTTFont::STTF_BOLD;
+
+ if (italic)
+ tempStyle |= StyledTTFont::STTF_ITALIC;
+
+ if (underline)
+ tempStyle |= StyledTTFont::STTF_UNDERLINE;
+
+ if (strikeout)
+ tempStyle |= StyledTTFont::STTF_STRIKEOUT;
+
+ if (sharp)
+ tempStyle |= StyledTTFont::STTF_SHARP;
+
+ font.setStyle(tempStyle);
+}
+
+void cTxtStyle::setFont(StyledTTFont &font) {
+ uint tempStyle = 0;
+
+ if (bold)
+ tempStyle |= StyledTTFont::STTF_BOLD;
+
+ if (italic)
+ tempStyle |= StyledTTFont::STTF_ITALIC;
+
+ if (underline)
+ tempStyle |= StyledTTFont::STTF_UNDERLINE;
+
+ if (strikeout)
+ tempStyle |= StyledTTFont::STTF_STRIKEOUT;
+
+ if (sharp)
+ tempStyle |= StyledTTFont::STTF_SHARP;
+
+ font.loadFont(fontname, size, tempStyle);
+}
+
+Graphics::Surface *TextRenderer::render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style) {
+ style.setFontStyle(fnt);
+ uint32 clr = _engine->_pixelFormat.RGBToColor(style.red, style.green, style.blue);
+ return fnt.renderSolidText(txt, clr);
+}
+
+void TextRenderer::drawTxtWithJustify(const Common::String &txt, StyledTTFont &fnt, uint32 color, Graphics::Surface &dst, int lineY, txtJustify justify) {
+ if (justify == TXT_JUSTIFY_LEFT)
+ fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignLeft);
+ else if (justify == TXT_JUSTIFY_CENTER)
+ fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignCenter);
+ else if (justify == TXT_JUSTIFY_RIGHT)
+ fnt.drawString(&dst, txt, 0, lineY, dst.w, color, Graphics::kTextAlignRight);
+}
+
+int32 TextRenderer::drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Graphics::Surface &dst) {
+ StyledTTFont font(_engine);
+ fontStyle.setFont(font);
+
+ dst.fillRect(Common::Rect(dst.w, dst.h), 0);
+
+ uint32 clr = _engine->_pixelFormat.RGBToColor(fontStyle.red, fontStyle.green, fontStyle.blue);
+
+ int16 w;
+
+ w = font.getStringWidth(txt);
+
+ drawTxtWithJustify(txt, font, clr, dst, 0, fontStyle.justify);
+
+ return w;
+}
+
+void TextRenderer::drawTxtInOneLine(const Common::String &text, Graphics::Surface &dst) {
+ const int16 TXT_CFG_TEXTURES_LINES = 256; // For now I don't want remake it
+ const int TXT_CFG_TEXTURES_PER_LINE = 6;
+ cTxtStyle style, style2;
+ int16 startTextPosition = -1;
+ int16 endTextPosition = -1;
+ int16 i = 0;
+ int16 dx = 0, dy = 0;
+ int16 textPixelWidth;
+ int16 textPosition = 0;
+ Common::String buf;
+ Common::String buf2;
+
+ Graphics::Surface *TxtSurfaces[TXT_CFG_TEXTURES_LINES][TXT_CFG_TEXTURES_PER_LINE];
+ int16 currentline = 0, currentlineitm = 0;
+
+ int TxtJustify[TXT_CFG_TEXTURES_LINES];
+ int TxtPoint[TXT_CFG_TEXTURES_LINES];
+
+ for (int16 k = 0; k < TXT_CFG_TEXTURES_LINES; k++) {
+ TxtPoint[k] = 0;
+ for (int j = 0; j < TXT_CFG_TEXTURES_PER_LINE; j++)
+ TxtSurfaces[k][j] = NULL;
+ }
+
+ int16 stringlen = text.size();
+
+ StyledTTFont font(_engine);
+
+ style.setFont(font);
+
+ int16 prevbufspace = 0, prevtxtspace = 0;
+
+ while (i < stringlen) {
+ TxtJustify[currentline] = style.justify;
+ if (text[i] == '<') {
+ int16 ret = 0;
+
+ startTextPosition = i;
+ while (i < stringlen && text[i] != '>')
+ i++;
+ endTextPosition = i;
+ if (startTextPosition != -1)
+ if ((endTextPosition - startTextPosition - 1) > 0) {
+ style2 = style;
+ ret = style.parseStyle(Common::String(text.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1);
+ }
+
+ if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) {
+ if (buf.size() > 0) {
+ textPixelWidth = font.getStringWidth(buf);
+
+ TxtSurfaces[currentline][currentlineitm] = render(font, buf, style2);
+ TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]);
+
+ currentlineitm++;
+
+ buf.clear();
+ prevbufspace = 0;
+ textPosition = 0;
+ dx += textPixelWidth;
+
+ }
+ if (ret & TXT_RET_FNTCHG) {
+ style.setFont(font);
+ }
+ if (ret & TXT_RET_FNTSTL)
+ style.setFontStyle(font);
+
+ if (ret & TXT_RET_NEWLN) {
+ currentline++;
+ currentlineitm = 0;
+ dx = 0;
+ }
+ }
+
+ if (ret & TXT_RET_HASSTBOX) {
+ Common::String buf3;
+ buf3.format("%d", _engine->getScriptManager()->getStateValue(style.statebox));
+ buf += buf3;
+ textPosition += buf3.size();
+ }
+
+ } else {
+
+ buf += text[i];
+ textPosition++;
+
+ if (text[i] == ' ') {
+ prevbufspace = textPosition - 1;
+ prevtxtspace = i;
+ }
+
+ if (font.isLoaded()) {
+ textPixelWidth = font.getStringWidth(buf);
+ if (textPixelWidth + dx > dst.w) {
+ if (prevbufspace == 0) {
+ prevtxtspace = i;
+ prevbufspace = textPosition - 1;
+ }
+ buf2 = Common::String(buf.c_str(), prevbufspace + 1);
+
+ if (buf2.size() > 0) {
+ TxtSurfaces[currentline][currentlineitm] = render(font, buf2, style);
+ TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]);
+ }
+
+ buf.clear();
+ i = prevtxtspace;
+ prevbufspace = 0;
+ textPosition = 0;
+ currentline++;
+ currentlineitm = 0;
+ dx = 0;
+ }
+ }
+ }
+ i++;
+ }
+
+ if (buf.size() > 0) {
+ TxtSurfaces[currentline][currentlineitm] = render(font, buf, style);
+ TxtPoint[currentline] = MAX(font.getFontHeight(), TxtPoint[currentline]);
+ }
+
+ dy = 0;
+ for (i = 0; i <= currentline; i++) {
+ int16 j = 0;
+ int16 width = 0;
+ while (TxtSurfaces[i][j] != NULL) {
+ width += TxtSurfaces[i][j]->w;
+ j++;
+ }
+ dx = 0;
+ for (int32 jj = 0; jj < j; jj++) {
+ if (TxtJustify[i] == TXT_JUSTIFY_LEFT)
+ _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0);
+
+ else if (TxtJustify[i] == TXT_JUSTIFY_CENTER)
+ _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, ((dst.w - width) / 2) + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0);
+
+ else if (TxtJustify[i] == TXT_JUSTIFY_RIGHT)
+ _engine->getRenderManager()->blitSurfaceToSurface(*TxtSurfaces[i][jj], dst, dst.w - width + dx, dy + TxtPoint[i] - TxtSurfaces[i][jj]->h, 0);
+
+ dx += TxtSurfaces[i][jj]->w;
+ }
+
+ dy += TxtPoint[i];
+ }
+
+ for (i = 0; i < TXT_CFG_TEXTURES_LINES; i++)
+ for (int32 j = 0; j < TXT_CFG_TEXTURES_PER_LINE; j++)
+ if (TxtSurfaces[i][j] != NULL) {
+ TxtSurfaces[i][j]->free();
+ delete TxtSurfaces[i][j];
+ }
+}
+
+Common::String readWideLine(Common::SeekableReadStream &stream) {
+ Common::String asciiString;
+
+ while (!stream.eos()) {
+ uint32 value = stream.readUint16LE();
+ // Check for CRLF
+ if (value == 0x0A0D) {
+ // Read in the extra NULL char
+ stream.readByte(); // \0
+ // End of the line. Break
+ break;
+ }
+
+ // Crush each octet pair to a UTF-8 sequence
+ if (value < 0x80) {
+ asciiString += (char)(value & 0x7F);
+ } else if (value >= 0x80 && value < 0x800) {
+ asciiString += (char)(0xC0 | ((value >> 6) & 0x1F));
+ asciiString += (char)(0x80 | (value & 0x3F));
+ } else if (value >= 0x800 && value < 0x10000) {
+ asciiString += (char)(0xE0 | ((value >> 12) & 0xF));
+ asciiString += (char)(0x80 | ((value >> 6) & 0x3F));
+ asciiString += (char)(0x80 | (value & 0x3F));
+ } else if (value >= 0x10000 && value < 0x200000) {
+ asciiString += (char)(0xF0);
+ asciiString += (char)(0x80 | ((value >> 12) & 0x3F));
+ asciiString += (char)(0x80 | ((value >> 6) & 0x3F));
+ asciiString += (char)(0x80 | (value & 0x3F));
+ }
+ }
+
+ return asciiString;
+}
+
+int8 getUtf8CharSize(char chr) {
+ if ((chr & 0x80) == 0)
+ return 1;
+ else if ((chr & 0xE0) == 0xC0)
+ return 2;
+ else if ((chr & 0xF0) == 0xE0)
+ return 3;
+ else if ((chr & 0xF8) == 0xF0)
+ return 4;
+ else if ((chr & 0xFC) == 0xF8)
+ return 5;
+ else if ((chr & 0xFE) == 0xFC)
+ return 6;
+
+ return 1;
+}
+
+uint16 readUtf8Char(const char *chr) {
+ uint16 result = 0;
+ if ((chr[0] & 0x80) == 0)
+ result = chr[0];
+ else if ((chr[0] & 0xE0) == 0xC0)
+ result = ((chr[0] & 0x1F) << 6) | (chr[1] & 0x3F);
+ else if ((chr[0] & 0xF0) == 0xE0)
+ result = ((chr[0] & 0x0F) << 12) | ((chr[1] & 0x3F) << 6) | (chr[2] & 0x3F);
+ else
+ result = chr[0];
+
+ return result;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/text/text.h b/engines/zvision/text/text.h
new file mode 100644
index 0000000000..01c3fd760c
--- /dev/null
+++ b/engines/zvision/text/text.h
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef ZVISION_TEXT_H
+#define ZVISION_TEXT_H
+
+#include "zvision/detection.h"
+#include "zvision/graphics/truetype_font.h"
+#include "zvision/zvision.h"
+
+namespace Graphics {
+class FontManager;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+enum txtJustify {
+ TXT_JUSTIFY_CENTER = 0,
+ TXT_JUSTIFY_LEFT = 1,
+ TXT_JUSTIFY_RIGHT = 2
+};
+
+enum txtReturn {
+ TXT_RET_NOTHING = 0x0,
+ TXT_RET_FNTCHG = 0x1,
+ TXT_RET_FNTSTL = 0x2,
+ TXT_RET_NEWLN = 0x4,
+ TXT_RET_HASSTBOX = 0x8
+};
+
+class cTxtStyle {
+public:
+ cTxtStyle();
+ txtReturn parseStyle(const Common::String &strin, int16 len);
+ void readAllStyle(const Common::String &txt);
+ void setFontStyle(StyledTTFont &font);
+ void setFont(StyledTTFont &font);
+
+public:
+ Common::String fontname;
+ txtJustify justify; // 0 - center, 1-left, 2-right
+ int16 size;
+ uint8 red; // 0-255
+ uint8 green; // 0-255
+ uint8 blue; // 0-255
+ int8 newline;
+ int8 escapement;
+ bool italic;
+ bool bold;
+ bool underline;
+ bool strikeout;
+ bool skipcolor;
+ int32 statebox;
+ bool sharp;
+ // char image ??
+};
+
+class TextRenderer {
+public:
+ TextRenderer(ZVision *engine): _engine(engine) {};
+
+ void drawTxtWithJustify(const Common::String &txt, StyledTTFont &fnt, uint32 color, Graphics::Surface &dst, int lineY, txtJustify justify);
+ int32 drawTxt(const Common::String &txt, cTxtStyle &fontStyle, Graphics::Surface &dst);
+ Graphics::Surface *render(StyledTTFont &fnt, const Common::String &txt, cTxtStyle &style);
+ void drawTxtInOneLine(const Common::String &txt, Graphics::Surface &dst);
+
+private:
+ ZVision *_engine;
+};
+
+Common::String readWideLine(Common::SeekableReadStream &stream);
+int8 getUtf8CharSize(char chr);
+uint16 readUtf8Char(const char *chr);
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/utility/clock.cpp b/engines/zvision/utility/clock.cpp
index 45ab23ab65..0e800a2031 100644
--- a/engines/zvision/utility/clock.cpp
+++ b/engines/zvision/utility/clock.cpp
@@ -26,7 +26,6 @@
#include "common/system.h"
-
namespace ZVision {
Clock::Clock(OSystem *system)
diff --git a/engines/zvision/utility/clock.h b/engines/zvision/utility/clock.h
index 6ae0f86161..cbf52be560 100644
--- a/engines/zvision/utility/clock.h
+++ b/engines/zvision/utility/clock.h
@@ -47,24 +47,31 @@ public:
* when the last update() was called.
*/
void update();
+
/**
* Get the delta time since the last frame. (The time between update() calls)
*
* @return Delta time since the last frame (in milliseconds)
*/
- uint32 getDeltaTime() const { return _deltaTime; }
+ uint32 getDeltaTime() const {
+ return _deltaTime;
+ }
+
/**
* Get the time from the program starting to the last update() call
*
* @return Time from program start to last update() call (in milliseconds)
*/
- uint32 getLastMeasuredTime() { return _lastTime; }
+ uint32 getLastMeasuredTime() {
+ return _lastTime;
+ }
/**
* Pause the clock. Any future delta times will take this pause into account.
* Has no effect if the clock is already paused.
*/
void start();
+
/**
* Un-pause the clock.
* Has no effect if the clock is already un-paused.
diff --git a/engines/zvision/utility/lzss_read_stream.cpp b/engines/zvision/utility/lzss_read_stream.cpp
index e094188ef6..bbe6e35f76 100644
--- a/engines/zvision/utility/lzss_read_stream.cpp
+++ b/engines/zvision/utility/lzss_read_stream.cpp
@@ -24,14 +24,13 @@
#include "zvision/utility/lzss_read_stream.h"
-
namespace ZVision {
LzssReadStream::LzssReadStream(Common::SeekableReadStream *source)
- : _source(source),
- // It's convention to set the starting cursor position to blockSize - 16
- _windowCursor(0x0FEE),
- _eosFlag(false) {
+ : _source(source),
+ // It's convention to set the starting cursor position to blockSize - 16
+ _windowCursor(0x0FEE),
+ _eosFlag(false) {
// Clear the window to null
memset(_window, 0, BLOCK_SIZE);
}
@@ -69,9 +68,9 @@ uint32 LzssReadStream::decompressBytes(byte *destination, uint32 numberOfBytes)
}
uint16 length = (high & 0xF) + 2;
- uint16 offset = low | ((high & 0xF0)<<4);
+ uint16 offset = low | ((high & 0xF0) << 4);
- for(int j = 0; j <= length; ++j) {
+ for (int j = 0; j <= length; ++j) {
byte temp = _window[(offset + j) & 0xFFF];
_window[_windowCursor] = temp;
destination[destinationCursor++] = temp;
diff --git a/engines/zvision/utility/lzss_read_stream.h b/engines/zvision/utility/lzss_read_stream.h
index b51cf3905f..1420621f13 100644
--- a/engines/zvision/utility/lzss_read_stream.h
+++ b/engines/zvision/utility/lzss_read_stream.h
@@ -26,7 +26,6 @@
#include "common/stream.h"
#include "common/array.h"
-
namespace Common {
class SeekableReadStream;
}
@@ -64,7 +63,7 @@ private:
*
* @param numberOfBytes How many bytes to decompress. This is a count of source bytes, not destination bytes
*/
- uint32 decompressBytes(byte* destination, uint32 numberOfBytes);
+ uint32 decompressBytes(byte *destination, uint32 numberOfBytes);
};
}
diff --git a/engines/zvision/utility/single_value_container.cpp b/engines/zvision/utility/single_value_container.cpp
deleted file mode 100644
index e609474285..0000000000
--- a/engines/zvision/utility/single_value_container.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/scummsys.h"
-
-#include "zvision/utility/single_value_container.h"
-
-#include "common/textconsole.h"
-#include "common/str.h"
-
-
-namespace ZVision {
-
-SingleValueContainer::SingleValueContainer(ValueType type) : _objectType(type) { }
-
-SingleValueContainer::SingleValueContainer(bool value) : _objectType(BOOL) {
- _value.boolVal = value;
-}
-
-SingleValueContainer::SingleValueContainer(byte value) : _objectType(BYTE) {
- _value.byteVal = value;
-}
-
-SingleValueContainer::SingleValueContainer(int16 value) : _objectType(INT16) {
- _value.int16Val = value;
-}
-
-SingleValueContainer::SingleValueContainer(uint16 value) : _objectType(UINT16) {
- _value.uint16Val = value;
-}
-
-SingleValueContainer::SingleValueContainer(int32 value) : _objectType(INT32) {
- _value.int32Val = value;
-}
-
-SingleValueContainer::SingleValueContainer(uint32 value) : _objectType(UINT32) {
- _value.uint32Val = value;
-}
-
-SingleValueContainer::SingleValueContainer(float value) : _objectType(FLOAT) {
- _value.floatVal = value;
-}
-
-SingleValueContainer::SingleValueContainer(double value) : _objectType(DOUBLE) {
- _value.doubleVal = value;
-}
-
-SingleValueContainer::SingleValueContainer(Common::String value) : _objectType(BYTE) {
- _value.stringVal = new char[value.size() + 1];
- memcpy(_value.stringVal, value.c_str(), value.size() + 1);
-}
-
-SingleValueContainer::SingleValueContainer(const SingleValueContainer &other) {
- _objectType = other._objectType;
-
- switch (_objectType) {
- case BOOL:
- _value.boolVal = other._value.boolVal;
- break;
- case BYTE:
- _value.byteVal = other._value.byteVal;
- break;
- case INT16:
- _value.int16Val = other._value.int16Val;
- break;
- case UINT16:
- _value.uint16Val = other._value.uint16Val;
- break;
- case INT32:
- _value.int32Val = other._value.int32Val;
- break;
- case UINT32:
- _value.uint32Val = other._value.uint32Val;
- break;
- case FLOAT:
- _value.floatVal = other._value.floatVal;
- break;
- case DOUBLE:
- _value.doubleVal = other._value.doubleVal;
- break;
- case STRING:
- uint32 length = strlen(other._value.stringVal);
- _value.stringVal = new char[length + 1];
- memcpy(_value.stringVal, other._value.stringVal, length + 1);
- break;
- }
-}
-
-SingleValueContainer::~SingleValueContainer() {
- deleteCharPointer();
-}
-
-void SingleValueContainer::deleteCharPointer() {
- if (_objectType == STRING)
- delete[] _value.stringVal;
-}
-
-
-SingleValueContainer &SingleValueContainer::operator=(const bool &rhs) {
- if (_objectType == BOOL) {
- _value.boolVal = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = BOOL;
- _value.boolVal = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const byte &rhs) {
- if (_objectType == BYTE) {
- _value.byteVal = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = BYTE;
- _value.byteVal = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const int16 &rhs) {
- if (_objectType == INT16) {
- _value.int16Val = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = INT16;
- _value.int16Val = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const uint16 &rhs) {
- if (_objectType == UINT16) {
- _value.uint16Val = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = UINT16;
- _value.uint16Val = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const int32 &rhs) {
- if (_objectType == INT32) {
- _value.int32Val = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = INT32;
- _value.int32Val = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const uint32 &rhs) {
- if (_objectType == UINT32) {
- _value.uint32Val = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = UINT32;
- _value.uint32Val = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const float &rhs) {
- if (_objectType == FLOAT) {
- _value.floatVal = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = FLOAT;
- _value.floatVal = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const double &rhs) {
- if (_objectType == DOUBLE) {
- _value.doubleVal = rhs;
- return *this;
- }
-
- deleteCharPointer();
- _objectType = DOUBLE;
- _value.doubleVal = rhs;
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const Common::String &rhs) {
- if (_objectType != STRING) {
- _objectType = STRING;
- _value.stringVal = new char[rhs.size() + 1];
- memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
-
- return *this;
- }
-
- uint32 length = strlen(_value.stringVal);
- if (length <= rhs.size() + 1) {
- memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
- } else {
- delete[] _value.stringVal;
- _value.stringVal = new char[rhs.size() + 1];
- memcpy(_value.stringVal, rhs.c_str(), rhs.size() + 1);
- }
-
- return *this;
-}
-
-SingleValueContainer &SingleValueContainer::operator=(const SingleValueContainer &rhs) {
- switch (_objectType) {
- case BOOL:
- return operator=(rhs._value.boolVal);
- case BYTE:
- return operator=(rhs._value.byteVal);
- case INT16:
- return operator=(rhs._value.int16Val);
- case UINT16:
- return operator=(rhs._value.uint16Val);
- case INT32:
- return operator=(rhs._value.int32Val);
- case UINT32:
- return operator=(rhs._value.uint32Val);
- case FLOAT:
- return operator=(rhs._value.floatVal);
- case DOUBLE:
- return operator=(rhs._value.doubleVal);
- case STRING:
- uint32 length = strlen(rhs._value.stringVal);
-
- _value.stringVal = new char[length + 1];
- memcpy(_value.stringVal, rhs._value.stringVal, length + 1);
-
- return *this;
- }
-
- return *this;
-}
-
-
-bool SingleValueContainer::getBoolValue(bool *returnValue) const {
- if (_objectType != BOOL) {
- warning("'Object' is not storing a bool.");
- return false;
- }
-
- *returnValue = _value.boolVal;
- return true;
-}
-
-bool SingleValueContainer::getByteValue(byte *returnValue) const {
- if (_objectType != BYTE)
- warning("'Object' is not storing a byte.");
-
- *returnValue = _value.byteVal;
- return true;
-}
-
-bool SingleValueContainer::getInt16Value(int16 *returnValue) const {
- if (_objectType != INT16)
- warning("'Object' is not storing an int16.");
-
- *returnValue = _value.int16Val;
- return true;
-}
-
-bool SingleValueContainer::getUInt16Value(uint16 *returnValue) const {
- if (_objectType != UINT16)
- warning("'Object' is not storing a uint16.");
-
- *returnValue = _value.uint16Val;
- return true;
-}
-
-bool SingleValueContainer::getInt32Value(int32 *returnValue) const {
- if (_objectType != INT32)
- warning("'Object' is not storing an int32.");
-
- *returnValue = _value.int32Val;
- return true;
-}
-
-bool SingleValueContainer::getUInt32Value(uint32 *returnValue) const {
- if (_objectType != UINT32)
- warning("'Object' is not storing a uint32.");
-
- *returnValue = _value.uint32Val;
- return true;
-}
-
-bool SingleValueContainer::getFloatValue(float *returnValue) const {
- if (_objectType != FLOAT)
- warning("'Object' is not storing a float.");
-
- *returnValue = _value.floatVal;
- return true;
-}
-
-bool SingleValueContainer::getDoubleValue(double *returnValue) const {
- if (_objectType != DOUBLE)
- warning("'Object' is not storing a double.");
-
- *returnValue = _value.doubleVal;
- return true;
-}
-
-bool SingleValueContainer::getStringValue(Common::String *returnValue) const {
- if (_objectType != STRING)
- warning("'Object' is not storing a Common::String.");
-
- *returnValue = _value.stringVal;
- return true;
-}
-
-} // End of namespace ZVision
diff --git a/engines/zvision/utility/single_value_container.h b/engines/zvision/utility/single_value_container.h
deleted file mode 100644
index 951383661a..0000000000
--- a/engines/zvision/utility/single_value_container.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef ZVISION_SINGLE_VALUE_CONTAINER_H
-#define ZVISION_SINGLE_VALUE_CONTAINER_H
-
-namespace Common {
-class String;
-}
-
-namespace ZVision {
-
-/**
- * A generic single value storage class. It is useful for storing different
- * value types in a single List, Hashmap, etc.
- */
-class SingleValueContainer {
-public:
- enum ValueType {
- BOOL,
- BYTE,
- INT16,
- UINT16,
- INT32,
- UINT32,
- FLOAT,
- DOUBLE,
- STRING
- };
-
- // Constructors
- explicit SingleValueContainer(ValueType type);
- explicit SingleValueContainer(bool value);
- explicit SingleValueContainer(byte value);
- explicit SingleValueContainer(int16 value);
- explicit SingleValueContainer(uint16 value);
- explicit SingleValueContainer(int32 value);
- explicit SingleValueContainer(uint32 value);
- explicit SingleValueContainer(float value);
- explicit SingleValueContainer(double value);
- explicit SingleValueContainer(Common::String value);
-
- // Copy constructor
- explicit SingleValueContainer(const SingleValueContainer& other);
-
- // Destructor
- ~SingleValueContainer();
-
-private:
- ValueType _objectType;
-
- union {
- bool boolVal;
- byte byteVal;
- int16 int16Val;
- uint16 uint16Val;
- int32 int32Val;
- uint32 uint32Val;
- float floatVal;
- double doubleVal;
- char *stringVal;
- } _value;
-
-public:
- SingleValueContainer &operator=(const bool &rhs);
- SingleValueContainer &operator=(const byte &rhs);
- SingleValueContainer &operator=(const int16 &rhs);
- SingleValueContainer &operator=(const uint16 &rhs);
- SingleValueContainer &operator=(const int32 &rhs);
- SingleValueContainer &operator=(const uint32 &rhs);
- SingleValueContainer &operator=(const float &rhs);
- SingleValueContainer &operator=(const double &rhs);
- SingleValueContainer &operator=(const Common::String &rhs);
-
- SingleValueContainer& operator=(const SingleValueContainer &rhs);
-
- /**
- * Retrieve a bool from the container. If the container is not storing a
- * bool, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getBoolValue(bool *returnValue) const;
- /**
- * Retrieve a byte from the container. If the container is not storing a
- * byte, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getByteValue(byte *returnValue) const;
- /**
- * Retrieve an int16 from the container. If the container is not storing an
- * int16, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getInt16Value(int16 *returnValue) const;
- /**
- * Retrieve a uint16 from the container. If the container is not storing a
- * uint16, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getUInt16Value(uint16 *returnValue) const;
- /**
- * Retrieve an int32 from the container. If the container is not storing an
- * int32, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getInt32Value(int32 *returnValue) const;
- /**
- * Retrieve a uint32 from the container. If the container is not storing a
- * uint32, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getUInt32Value(uint32 *returnValue) const;
- /**
- * Retrieve a float from the container. If the container is not storing a
- * float, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getFloatValue(float *returnValue) const;
- /**
- * Retrieve a double from the container. If the container is not storing a
- * double, this will return false and display a warning().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getDoubleValue(double *returnValue) const;
- /**
- * Retrieve a String from the container. If the container is not storing a
- * string, this will return false and display a warning().
- *
- * Caution: Strings are internally stored as char[]. getStringValue uses
- * Common::String::operator=(char *) to do the assigment, which uses both
- * strlen() AND memmove().
- *
- * @param returnValue Pointer to where you want the value stored
- * @return Value indicating whether the value assignment was successful
- */
- bool getStringValue(Common::String *returnValue) const;
-
-private:
- /**
- * Helper method for destruction and assignment. It checks to see
- * if the char pointer is being used, and if so calls delete on it
- */
- void deleteCharPointer();
-};
-
-} // End of namespace ZVision
-
-#endif
diff --git a/engines/zvision/utility/utility.cpp b/engines/zvision/utility/utility.cpp
index 905bc4513a..e09545a90d 100644
--- a/engines/zvision/utility/utility.cpp
+++ b/engines/zvision/utility/utility.cpp
@@ -30,28 +30,8 @@
#include "common/tokenizer.h"
#include "common/file.h"
-
namespace ZVision {
-void writeFileContentsToFile(const Common::String &sourceFile, const Common::String &destFile) {
- Common::File f;
- if (!f.open(sourceFile)) {
- return;
- }
-
- byte* buffer = new byte[f.size()];
- f.read(buffer, f.size());
-
- Common::DumpFile dumpFile;
- dumpFile.open(destFile);
-
- dumpFile.write(buffer, f.size());
- dumpFile.flush();
- dumpFile.close();
-
- delete[] buffer;
-}
-
void trimCommentsAndWhiteSpace(Common::String *string) {
for (int i = string->size() - 1; i >= 0; i--) {
if ((*string)[i] == '#') {
@@ -62,176 +42,4 @@ void trimCommentsAndWhiteSpace(Common::String *string) {
string->trim();
}
-void tryToDumpLine(const Common::String &key,
- Common::String &line,
- Common::HashMap<Common::String, byte> *count,
- Common::HashMap<Common::String, bool> *fileAlreadyUsed,
- Common::DumpFile &output) {
- const byte numberOfExamplesPerType = 8;
-
- if ((*count)[key] < numberOfExamplesPerType && !(*fileAlreadyUsed)[key]) {
- output.writeString(line);
- output.writeByte('\n');
- (*count)[key]++;
- (*fileAlreadyUsed)[key] = true;
- }
-}
-
-void dumpEveryResultAction(const Common::String &destFile) {
- Common::HashMap<Common::String, byte> count;
- Common::HashMap<Common::String, bool> fileAlreadyUsed;
-
- Common::DumpFile output;
- output.open(destFile);
-
- // Find scr files
- Common::ArchiveMemberList list;
- SearchMan.listMatchingMembers(list, "*.scr");
-
- for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
- Common::SeekableReadStream *stream = (*iter)->createReadStream();
-
- Common::String line = stream->readLine();
- trimCommentsAndWhiteSpace(&line);
-
- while (!stream->eos()) {
- if (line.matchString("*:add*", true)) {
- tryToDumpLine("add", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:animplay*", true)) {
- tryToDumpLine("animplay", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:animpreload*", true)) {
- tryToDumpLine("animpreload", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:animunload*", true)) {
- tryToDumpLine("animunload", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:attenuate*", true)) {
- tryToDumpLine("attenuate", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:assign*", true)) {
- tryToDumpLine("assign", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:change_location*", true)) {
- tryToDumpLine("change_location", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:crossfade*", true) && !fileAlreadyUsed["add"]) {
- tryToDumpLine("crossfade", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:debug*", true)) {
- tryToDumpLine("debug", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:delay_render*", true)) {
- tryToDumpLine("delay_render", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:disable_control*", true)) {
- tryToDumpLine("disable_control", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:disable_venus*", true)) {
- tryToDumpLine("disable_venus", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:display_message*", true)) {
- tryToDumpLine("display_message", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:dissolve*", true)) {
- tryToDumpLine("dissolve", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:distort*", true)) {
- tryToDumpLine("distort", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:enable_control*", true)) {
- tryToDumpLine("enable_control", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:flush_mouse_events*", true)) {
- tryToDumpLine("flush_mouse_events", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:inventory*", true)) {
- tryToDumpLine("inventory", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:kill*", true)) {
- tryToDumpLine("kill", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:menu_bar_enable*", true)) {
- tryToDumpLine("menu_bar_enable", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:music*", true)) {
- tryToDumpLine("music", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:pan_track*", true)) {
- tryToDumpLine("pan_track", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:playpreload*", true)) {
- tryToDumpLine("playpreload", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:preferences*", true)) {
- tryToDumpLine("preferences", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:quit*", true)) {
- tryToDumpLine("quit", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:random*", true)) {
- tryToDumpLine("random", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:region*", true)) {
- tryToDumpLine("region", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:restore_game*", true)) {
- tryToDumpLine("restore_game", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:rotate_to*", true)) {
- tryToDumpLine("rotate_to", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:save_game*", true)) {
- tryToDumpLine("save_game", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:set_partial_screen*", true)) {
- tryToDumpLine("set_partial_screen", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:set_screen*", true)) {
- tryToDumpLine("set_screen", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:set_venus*", true)) {
- tryToDumpLine("set_venus", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:stop*", true)) {
- tryToDumpLine("stop", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:streamvideo*", true)) {
- tryToDumpLine("streamvideo", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:syncsound*", true)) {
- tryToDumpLine("syncsound", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:timer*", true)) {
- tryToDumpLine("timer", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:ttytext*", true)) {
- tryToDumpLine("ttytext", line, &count, &fileAlreadyUsed, output);
- } else if (line.matchString("*:universe_music*", true)) {
- tryToDumpLine("universe_music", line, &count, &fileAlreadyUsed, output);
- }
-
- line = stream->readLine();
- trimCommentsAndWhiteSpace(&line);
- }
-
- for (Common::HashMap<Common::String, bool>::iterator fileUsedIter = fileAlreadyUsed.begin(); fileUsedIter != fileAlreadyUsed.end(); ++fileUsedIter) {
- fileUsedIter->_value = false;
- }
- }
-
- output.close();
-}
-
-Common::String getFileName(const Common::String &fullPath) {
- Common::StringTokenizer tokenizer(fullPath, "/\\");
- Common::String token;
- while (!tokenizer.empty()) {
- token = tokenizer.nextToken();
- }
-
- return token;
-}
-
-void convertRawToWav(const Common::String &inputFile, ZVision *engine, const Common::String &outputFile) {
- Common::File file;
- if (!file.open(inputFile))
- return;
-
- Audio::AudioStream *audioStream = makeRawZorkStream(inputFile, engine);
-
- Common::DumpFile output;
- output.open(outputFile);
-
- output.writeUint32BE(MKTAG('R', 'I', 'F', 'F'));
- output.writeUint32LE(file.size() * 2 + 36);
- output.writeUint32BE(MKTAG('W', 'A', 'V', 'E'));
- output.writeUint32BE(MKTAG('f', 'm', 't', ' '));
- output.writeUint32LE(16);
- output.writeUint16LE(1);
- uint16 numChannels;
- if (audioStream->isStereo()) {
- numChannels = 2;
- output.writeUint16LE(2);
- } else {
- numChannels = 1;
- output.writeUint16LE(1);
- }
- output.writeUint32LE(audioStream->getRate());
- output.writeUint32LE(audioStream->getRate() * numChannels * 2);
- output.writeUint16LE(numChannels * 2);
- output.writeUint16LE(16);
- output.writeUint32BE(MKTAG('d', 'a', 't', 'a'));
- output.writeUint32LE(file.size() * 2);
- int16 *buffer = new int16[file.size()];
- audioStream->readBuffer(buffer, file.size());
- output.write(buffer, file.size() * 2);
-
- delete[] buffer;
-}
-
} // End of namespace ZVision
diff --git a/engines/zvision/utility/utility.h b/engines/zvision/utility/utility.h
index 063d4c0663..0ca26b968d 100644
--- a/engines/zvision/utility/utility.h
+++ b/engines/zvision/utility/utility.h
@@ -25,7 +25,6 @@
#include "common/array.h"
-
namespace Common {
class String;
}
@@ -35,15 +34,6 @@ namespace ZVision {
class ZVision;
/**
- * Opens the sourceFile utilizing Common::File (aka SearchMan) and writes the
- * contents to destFile. destFile is created in the working directory
- *
- * @param sourceFile The 'file' you want the contents of
- * @param destFile The name of the file where the content will be written to
- */
-void writeFileContentsToFile(const Common::String &sourceFile, const Common::String &destFile);
-
-/**
* Removes any line comments using '#' as a sequence start.
* Then removes any trailing and leading 'whitespace' using String::trim()
* Note: String::trim uses isspace() to determine what is whitespace and what is not.
@@ -52,63 +42,6 @@ void writeFileContentsToFile(const Common::String &sourceFile, const Common::Str
*/
void trimCommentsAndWhiteSpace(Common::String *string);
-/**
- * Searches through all the .scr files and dumps 'numberOfExamplesPerType' examples of each type of ResultAction
- * ZVision::initialize() must have been called before this function can be used.
- *
- * @param destFile Where to write the examples
- */
-void dumpEveryResultAction(const Common::String &destFile);
-
-/**
- * Removes all duplicate entries from container. Relative order will be preserved.
- *
- * @param container The Array to remove duplicate entries from
- */
-template<class T>
-void removeDuplicateEntries(Common::Array<T> &container) {
- // Length of modified array
- uint newLength = 1;
- uint j;
-
- for(uint i = 1; i < container.size(); i++) {
- for(j = 0; j < newLength; j++) {
- if (container[i] == container[j]) {
- break;
- }
- }
-
- // If none of the values in index[0..j] of container are the same as array[i],
- // then copy the current value to corresponding new position in array
- if (j == newLength) {
- container[newLength++] = container[i];
- }
- }
-
- // Actually remove the unneeded space
- while (container.size() < newLength) {
- container.pop_back();
- }
-}
-
-/**
- * Gets the name of the file (including extension). Forward or back slashes
- * are interpreted as directory changes
- *
- * @param fullPath A full or partial path to the file. Ex: folderOne/folderTwo/file.txt
- * @return The name of the file without any preceding directories. Ex: file.txt
- */
-Common::String getFileName(const Common::String &fullPath);
-
-/**
- * Converts a ZVision .RAW file to a .WAV
- * The .WAV will be created in the working directory and will overwrite any existing file
- *
- * @param inputFile The path to the input .RAW file
- * @param outputFile The name of the output .WAV file
- */
-void convertRawToWav(const Common::String &inputFile, ZVision *engine, const Common::String &outputFile);
-
} // End of namespace ZVision
#endif
diff --git a/engines/zvision/archives/zfs_archive.cpp b/engines/zvision/utility/zfs_archive.cpp
index f5fa6fc9bf..13b0168e1c 100644
--- a/engines/zvision/archives/zfs_archive.cpp
+++ b/engines/zvision/utility/zfs_archive.cpp
@@ -21,13 +21,12 @@
*/
#include "common/scummsys.h"
-
-#include "zvision/archives/zfs_archive.h"
-
#include "common/memstream.h"
#include "common/debug.h"
#include "common/file.h"
+#include "zvision/utility/zfs_archive.h"
+
namespace ZVision {
ZfsArchive::ZfsArchive(const Common::String &fileName) : _fileName(fileName) {
@@ -52,7 +51,7 @@ ZfsArchive::ZfsArchive(const Common::String &fileName, Common::SeekableReadStrea
ZfsArchive::~ZfsArchive() {
debug(1, "ZfsArchive Destructor Called");
ZfsEntryHeaderMap::iterator it = _entryHeaders.begin();
- for ( ; it != _entryHeaders.end(); ++it) {
+ for (; it != _entryHeaders.end(); ++it) {
delete it->_value;
}
}
@@ -79,7 +78,7 @@ void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) {
// Read in each entry header
for (uint32 i = 0; i < _header.filesPerBlock; ++i) {
ZfsEntryHeader entryHeader;
-
+
entryHeader.name = readEntryName(stream);
entryHeader.offset = stream->readUint32LE();
entryHeader.id = stream->readUint32LE();
@@ -138,7 +137,7 @@ Common::SeekableReadStream *ZfsArchive::createReadStreamForMember(const Common::
zfsArchive.seek(entryHeader->offset);
// This *HAS* to be malloc (not new[]) because MemoryReadStream uses free() to free the memory
- byte* buffer = (byte *)malloc(entryHeader->size);
+ byte *buffer = (byte *)malloc(entryHeader->size);
zfsArchive.read(buffer, entryHeader->size);
// Decrypt the data in place
if (_header.xorKey != 0)
@@ -153,5 +152,3 @@ void ZfsArchive::unXor(byte *buffer, uint32 length, const byte *xorKey) const {
}
} // End of namespace ZVision
-
-
diff --git a/engines/zvision/archives/zfs_archive.h b/engines/zvision/utility/zfs_archive.h
index 3509cfee26..571591a6d1 100644
--- a/engines/zvision/archives/zfs_archive.h
+++ b/engines/zvision/utility/zfs_archive.h
@@ -27,7 +27,6 @@
#include "common/hashmap.h"
#include "common/hash-str.h"
-
namespace Common {
class String;
}
@@ -53,7 +52,7 @@ struct ZfsEntryHeader {
uint32 unknown;
};
-typedef Common::HashMap<Common::String, ZfsEntryHeader*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ZfsEntryHeaderMap;
+typedef Common::HashMap<Common::String, ZfsEntryHeader *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ZfsEntryHeaderMap;
class ZfsArchive : public Common::Archive {
public:
diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp
index d1fff30408..db6161bf0c 100644
--- a/engines/zvision/video/video.cpp
+++ b/engines/zvision/video/video.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -21,107 +21,44 @@
*/
#include "common/scummsys.h"
-
-#include "zvision/zvision.h"
-
-#include "zvision/utility/clock.h"
-#include "zvision/graphics/render_manager.h"
-
#include "common/system.h"
-
#include "video/video_decoder.h"
-
#include "engines/util.h"
-
#include "graphics/surface.h"
+#include "zvision/zvision.h"
+#include "zvision/utility/clock.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/graphics/subtitles.h"
namespace ZVision {
-// Taken/modified from SCI
-void scaleBuffer(const byte *src, byte *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint scaleAmount) {
- assert(bytesPerPixel == 1 || bytesPerPixel == 2);
-
- const uint32 newWidth = srcWidth * scaleAmount;
- const uint32 pitch = newWidth * bytesPerPixel;
- const byte *srcPtr = src;
-
- if (bytesPerPixel == 1) {
- for (uint32 y = 0; y < srcHeight; ++y) {
- for (uint32 x = 0; x < srcWidth; ++x) {
- const byte color = *srcPtr++;
-
- for (uint i = 0; i < scaleAmount; ++i) {
- dst[i] = color;
- dst[pitch + i] = color;
- }
- dst += scaleAmount;
- }
- dst += pitch;
- }
- } else if (bytesPerPixel == 2) {
- for (uint32 y = 0; y < srcHeight; ++y) {
- for (uint32 x = 0; x < srcWidth; ++x) {
- const byte color = *srcPtr++;
- const byte color2 = *srcPtr++;
-
- for (uint i = 0; i < scaleAmount; ++i) {
- uint index = i *2;
-
- dst[index] = color;
- dst[index + 1] = color2;
- dst[pitch + index] = color;
- dst[pitch + index + 1] = color2;
- }
- dst += 2 * scaleAmount;
- }
- dst += pitch;
- }
- }
-}
-
-void ZVision::playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect, bool skippable) {
- byte bytesPerPixel = videoDecoder.getPixelFormat().bytesPerPixel;
-
- uint16 origWidth = videoDecoder.getWidth();
- uint16 origHeight = videoDecoder.getHeight();
-
- uint scale = 1;
+void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, bool skippable, Subtitle *sub) {
+ Common::Rect dst = destRect;
// If destRect is empty, no specific scaling was requested. However, we may choose to do scaling anyway
- if (destRect.isEmpty()) {
- // Most videos are very small. Therefore we do a simple 2x scale
- if (origWidth * 2 <= 640 && origHeight * 2 <= 480) {
- scale = 2;
- }
- } else {
- // Assume bilinear scaling. AKA calculate the scale from just the width.
- // Also assume that the scaling is in integral intervals. AKA no 1.5x scaling
- // TODO: Test ^these^ assumptions
- scale = destRect.width() / origWidth;
-
- // TODO: Test if we need to support downscale.
- }
-
- uint16 pitch = origWidth * bytesPerPixel;
+ if (dst.isEmpty())
+ dst = Common::Rect(vid.getWidth(), vid.getHeight());
- uint16 finalWidth = origWidth * scale;
- uint16 finalHeight = origHeight * scale;
+ Graphics::Surface *scaled = NULL;
- byte *scaledVideoFrameBuffer = 0;
- if (scale != 1) {
- scaledVideoFrameBuffer = new byte[finalWidth * finalHeight * bytesPerPixel];
+ if (vid.getWidth() != dst.width() || vid.getHeight() != dst.height()) {
+ scaled = new Graphics::Surface;
+ scaled->create(dst.width(), dst.height(), vid.getPixelFormat());
}
- uint16 x = ((WINDOW_WIDTH - finalWidth) / 2) + destRect.left;
- uint16 y = ((WINDOW_HEIGHT - finalHeight) / 2) + destRect.top;
+ uint16 x = _workingWindow.left + dst.left;
+ uint16 y = _workingWindow.top + dst.top;
+ uint16 finalWidth = dst.width() < _workingWindow.width() ? dst.width() : _workingWindow.width();
+ uint16 finalHeight = dst.height() < _workingWindow.height() ? dst.height() : _workingWindow.height();
_clock.stop();
- videoDecoder.start();
+ vid.start();
+ _videoIsPlaying = true;
// Only continue while the video is still playing
- while (!shouldQuit() && !videoDecoder.endOfVideo() && videoDecoder.isPlaying()) {
+ while (!shouldQuit() && !vid.endOfVideo() && vid.isPlaying()) {
// Check for engine quit and video stop key presses
- while (!videoDecoder.endOfVideo() && videoDecoder.isPlaying() && _eventMan->pollEvent(_event)) {
+ while (_eventMan->pollEvent(_event)) {
switch (_event.type) {
case Common::EVENT_KEYDOWN:
switch (_event.kbd.keycode) {
@@ -131,7 +68,7 @@ void ZVision::playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &d
break;
case Common::KEYCODE_SPACE:
if (skippable) {
- videoDecoder.stop();
+ vid.stop();
}
break;
default:
@@ -142,29 +79,33 @@ void ZVision::playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &d
}
}
- if (videoDecoder.needsUpdate()) {
- const Graphics::Surface *frame = videoDecoder.decodeNextFrame();
+ if (vid.needsUpdate()) {
+ const Graphics::Surface *frame = vid.decodeNextFrame();
+ if (sub)
+ sub->process(vid.getCurFrame());
if (frame) {
- if (scale != 1) {
- scaleBuffer((const byte *)frame->getPixels(), scaledVideoFrameBuffer, origWidth, origHeight, bytesPerPixel, scale);
- _system->copyRectToScreen(scaledVideoFrameBuffer, pitch * 2, x, y, finalWidth, finalHeight);
- } else {
- _system->copyRectToScreen((const byte *)frame->getPixels(), pitch, x, y, finalWidth, finalHeight);
+ if (scaled) {
+ _renderManager->scaleBuffer(frame->getPixels(), scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, scaled->w, scaled->h);
+ frame = scaled;
}
+ _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, x, y, finalWidth, finalHeight);
+ _renderManager->processSubs(0);
}
}
// Always update the screen so the mouse continues to render
_system->updateScreen();
- _system->delayMillis(videoDecoder.getTimeToNextFrame());
+ _system->delayMillis(vid.getTimeToNextFrame() / 2);
}
+ _videoIsPlaying = false;
_clock.start();
- if (scale != 1) {
- delete[] scaledVideoFrameBuffer;
+ if (scaled) {
+ scaled->free();
+ delete scaled;
}
}
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
index f22a4203ab..67fab0a114 100644
--- a/engines/zvision/video/zork_avi_decoder.cpp
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -29,7 +29,7 @@
#include "common/stream.h"
#include "audio/audiostream.h"
-
+#include "audio/decoders/raw.h"
namespace ZVision {
@@ -42,11 +42,19 @@ void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *s
if (_audStream) {
if (_wvInfo.tag == kWaveFormatZorkPCM) {
assert(_wvInfo.size == 8);
- _audStream->queueAudioStream(makeRawZorkStream(stream, _wvInfo.samplesPerSec, _audStream->isStereo(), DisposeAfterUse::YES), DisposeAfterUse::YES);
+ RawChunkStream::RawChunk chunk = decoder->readNextChunk(stream);
+ delete stream;
+
+ if (chunk.data)
+ _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO);
+ } else {
+ AVIAudioTrack::queueSound(stream);
}
- } else {
- delete stream;
}
}
+void ZorkAVIDecoder::ZorkAVIAudioTrack::resetStream() {
+ decoder->init();
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/video/zork_avi_decoder.h b/engines/zvision/video/zork_avi_decoder.h
index c47f007f9b..89c0d1e4b9 100644
--- a/engines/zvision/video/zork_avi_decoder.h
+++ b/engines/zvision/video/zork_avi_decoder.h
@@ -8,41 +8,53 @@
* 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 ZORK_AVI_DECODER_H
#define ZORK_AVI_DECODER_H
#include "video/avi_decoder.h"
-
+#include "zvision/sound/zork_raw.h"
namespace ZVision {
class ZorkAVIDecoder : public Video::AVIDecoder {
public:
ZorkAVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType) :
- Video::AVIDecoder(soundType) {}
+ Video::AVIDecoder(soundType) {}
- virtual ~ZorkAVIDecoder() {}
+ virtual ~ZorkAVIDecoder() {}
private:
class ZorkAVIAudioTrack : public Video::AVIDecoder::AVIAudioTrack {
public:
ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
- Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType) {}
- virtual ~ZorkAVIAudioTrack() {}
+ Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType),
+ decoder(NULL) {
+ if (_audStream) {
+ decoder = new RawChunkStream(_audStream->isStereo());
+ }
+ }
+ virtual ~ZorkAVIAudioTrack() {
+ if (decoder)
+ delete decoder;
+ }
void queueSound(Common::SeekableReadStream *stream);
+ void resetStream();
+ private:
+ RawChunkStream *decoder;
};
Video::AVIDecoder::AVIAudioTrack *createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo);
@@ -50,7 +62,7 @@ private:
private:
// Audio Codecs
enum {
- kWaveFormatZorkPCM = 17 // special Zork PCM audio format (clashes with MS IMA ADPCM)
+ kWaveFormatZorkPCM = 17 // special Zork PCM audio format (clashes with MS IMA ADPCM)
};
};
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
index b464f6ee81..8a44ccebea 100644
--- a/engines/zvision/zvision.cpp
+++ b/engines/zvision/zvision.cpp
@@ -8,12 +8,12 @@
* 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.
@@ -23,17 +23,22 @@
#include "common/scummsys.h"
#include "zvision/zvision.h"
-
#include "zvision/core/console.h"
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/cursors/cursor_manager.h"
#include "zvision/core/save_manager.h"
-#include "zvision/strings/string_manager.h"
-#include "zvision/archives/zfs_archive.h"
+#include "zvision/text/string_manager.h"
#include "zvision/detection.h"
+#include "zvision/core/menu.h"
+#include "zvision/core/search_manager.h"
+#include "zvision/text/text.h"
+#include "zvision/graphics/truetype_font.h"
+#include "zvision/core/midi.h"
+#include "zvision/utility/zfs_archive.h"
#include "common/config-manager.h"
+#include "common/str.h"
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/textconsole.h"
@@ -45,24 +50,58 @@
#include "audio/mixer.h"
-
namespace ZVision {
+#define ZVISION_SETTINGS_KEYS_COUNT 17
+
+struct zvisionIniSettings {
+ const char *name;
+ int16 slot;
+ int16 deflt;
+} settingsKeys[ZVISION_SETTINGS_KEYS_COUNT] = {
+ {"ZVision_KeyboardTurnSpeed", StateKey_KbdRotateSpeed, 5},
+ {"ZVision_PanaRotateSpeed", StateKey_RotateSpeed, 540},
+ {"ZVision_QSoundEnabled", StateKey_Qsound, 1},
+ {"ZVision_VenusEnabled", StateKey_VenusEnable, 1},
+ {"ZVision_HighQuality", StateKey_HighQuality, 1},
+ {"ZVision_Platform", StateKey_Platform, 0},
+ {"ZVision_InstallLevel", StateKey_InstallLevel, 0},
+ {"ZVision_CountryCode", StateKey_CountryCode, 0},
+ {"ZVision_CPU", StateKey_CPU, 1},
+ {"ZVision_MovieCursor", StateKey_MovieCursor, 1},
+ {"ZVision_NoAnimWhileTurning", StateKey_NoTurnAnim, 0},
+ {"ZVision_Win958", StateKey_WIN958, 0},
+ {"ZVision_ShowErrorDialogs", StateKey_ShowErrorDlg, 0},
+ {"ZVision_ShowSubtitles", StateKey_Subtitles, 1},
+ {"ZVision_DebugCheats", StateKey_DebugCheats, 0},
+ {"ZVision_JapaneseFonts", StateKey_JapanFonts, 0},
+ {"ZVision_Brightness", StateKey_Brightness, 0}
+};
+
ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc)
- : Engine(syst),
- _gameDescription(gameDesc),
- _workingWindow(gameDesc->gameId == GID_NEMESIS ? Common::Rect((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZNEM_WORKING_WINDOW_WIDTH) / 2) + ZNEM_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZNEM_WORKING_WINDOW_HEIGHT) / 2) + ZNEM_WORKING_WINDOW_HEIGHT) :
- Common::Rect((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZGI_WORKING_WINDOW_WIDTH) / 2) + ZGI_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZGI_WORKING_WINDOW_HEIGHT) / 2) + ZGI_WORKING_WINDOW_HEIGHT)),
- _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/
- _desiredFrameTime(33), /* ~30 fps */
- _clock(_system),
- _scriptManager(nullptr),
- _renderManager(nullptr),
- _saveManager(nullptr),
- _stringManager(nullptr),
- _cursorManager(nullptr) {
+ : Engine(syst),
+ _gameDescription(gameDesc),
+ _workingWindow_ZGI((WINDOW_WIDTH - WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - WORKING_WINDOW_WIDTH) / 2) + WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - WORKING_WINDOW_HEIGHT) / 2) + WORKING_WINDOW_HEIGHT),
+ _workingWindow_ZNM((WINDOW_WIDTH - ZNM_WORKING_WINDOW_WIDTH) / 2, (WINDOW_HEIGHT - ZNM_WORKING_WINDOW_HEIGHT) / 2, ((WINDOW_WIDTH - ZNM_WORKING_WINDOW_WIDTH) / 2) + ZNM_WORKING_WINDOW_WIDTH, ((WINDOW_HEIGHT - ZNM_WORKING_WINDOW_HEIGHT) / 2) + ZNM_WORKING_WINDOW_HEIGHT),
+ _workingWindow(gameDesc->gameId == GID_NEMESIS ? _workingWindow_ZNM : _workingWindow_ZGI),
+ _pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), /*RGB 565*/
+ _desiredFrameTime(33), /* ~30 fps */
+ _clock(_system),
+ _scriptManager(nullptr),
+ _renderManager(nullptr),
+ _saveManager(nullptr),
+ _stringManager(nullptr),
+ _cursorManager(nullptr),
+ _midiManager(nullptr),
+ _audioId(0),
+ _rendDelay(2),
+ _kbdVelocity(0),
+ _mouseVelocity(0),
+ _videoIsPlaying(false) {
debug(1, "ZVision::ZVision");
+
+ memset(_cheatBuff, 0, sizeof(_cheatBuff));
}
ZVision::~ZVision() {
@@ -76,39 +115,60 @@ ZVision::~ZVision() {
delete _renderManager;
delete _scriptManager;
delete _rnd;
+ delete _midiManager;
// Remove all of our debug levels
DebugMan.clearAllDebugChannels();
}
+void ZVision::registerDefaultSettings() {
+ for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++)
+ ConfMan.registerDefault(settingsKeys[i].name, settingsKeys[i].deflt);
+ ConfMan.registerDefault("doublefps", false);
+}
+
+void ZVision::loadSettings() {
+ for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++)
+ _scriptManager->setStateValue(settingsKeys[i].slot, ConfMan.getInt(settingsKeys[i].name));
+
+ if (getGameId() == GID_NEMESIS)
+ _scriptManager->setStateValue(StateKey_ExecScopeStyle, 1);
+ else
+ _scriptManager->setStateValue(StateKey_ExecScopeStyle, 0);
+}
+
+void ZVision::saveSettings() {
+ for (int i = 0; i < ZVISION_SETTINGS_KEYS_COUNT; i++)
+ ConfMan.setInt(settingsKeys[i].name, _scriptManager->getStateValue(settingsKeys[i].slot));
+ ConfMan.flushToDisk();
+}
+
void ZVision::initialize() {
const Common::FSNode gameDataDir(ConfMan.get("path"));
- // TODO: There are 10 file clashes when we flatten the directories.
- // From a quick look, the files are exactly the same, so it shouldn't matter.
- // But I'm noting it here just in-case it does become a problem.
- SearchMan.addSubDirectoryMatching(gameDataDir, "data1", 0, 4, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "data2", 0, 4, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "data3", 0, 4, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "zassets1", 0, 2, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "zassets2", 0, 2, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "znemmx", 0, 1, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "zgi", 0, 4, true);
- SearchMan.addSubDirectoryMatching(gameDataDir, "fonts", 0, 1, true);
-
- // Find zfs archive files
- Common::ArchiveMemberList list;
- SearchMan.listMatchingMembers(list, "*.zfs");
-
- // Register the file entries within the zfs archives with the SearchMan
- for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
- Common::String name = (*iter)->getName();
- Common::SeekableReadStream *stream = (*iter)->createReadStream();
- ZfsArchive *archive = new ZfsArchive(name, stream);
-
- delete stream;
-
- SearchMan.add(name, archive);
- }
+
+ _searchManager = new SearchManager(ConfMan.get("path"), 6);
+
+ _searchManager->addDir("FONTS");
+ _searchManager->addDir("addon");
+
+ if (_gameDescription->gameId == GID_GRANDINQUISITOR) {
+ _searchManager->loadZix("INQUIS.ZIX");
+ _searchManager->addPatch("C000H01Q.RAW", "C000H01Q.SRC");
+ _searchManager->addPatch("CM00H01Q.RAW", "CM00H01Q.SRC");
+ _searchManager->addPatch("DM00H01Q.RAW", "DM00H01Q.SRC");
+ _searchManager->addPatch("E000H01Q.RAW", "E000H01Q.SRC");
+ _searchManager->addPatch("EM00H50Q.RAW", "EM00H50Q.SRC");
+ _searchManager->addPatch("GJNPH65P.RAW", "GJNPH65P.SRC");
+ _searchManager->addPatch("GJNPH72P.RAW", "GJNPH72P.SRC");
+ _searchManager->addPatch("H000H01Q.RAW", "H000H01Q.SRC");
+ _searchManager->addPatch("M000H01Q.RAW", "M000H01Q.SRC");
+ _searchManager->addPatch("P000H01Q.RAW", "P000H01Q.SRC");
+ _searchManager->addPatch("Q000H01Q.RAW", "Q000H01Q.SRC");
+ _searchManager->addPatch("SW00H01Q.RAW", "SW00H01Q.SRC");
+ _searchManager->addPatch("T000H01Q.RAW", "T000H01Q.SRC");
+ _searchManager->addPatch("U000H01Q.RAW", "U000H01Q.SRC");
+ } else if (_gameDescription->gameId == GID_NEMESIS)
+ _searchManager->loadZix("NEMESIS.ZIX");
initGraphics(WINDOW_WIDTH, WINDOW_HEIGHT, true, &_pixelFormat);
@@ -117,52 +177,150 @@ void ZVision::initialize() {
// Create managers
_scriptManager = new ScriptManager(this);
- _renderManager = new RenderManager(_system, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat);
+ _renderManager = new RenderManager(this, WINDOW_WIDTH, WINDOW_HEIGHT, _workingWindow, _pixelFormat);
_saveManager = new SaveManager(this);
_stringManager = new StringManager(this);
_cursorManager = new CursorManager(this, &_pixelFormat);
+ _textRenderer = new TextRenderer(this);
+ _midiManager = new MidiManager();
+
+ if (_gameDescription->gameId == GID_GRANDINQUISITOR)
+ _menu = new MenuZGI(this);
+ else
+ _menu = new MenuNemesis(this);
// Initialize the managers
_cursorManager->initialize();
_scriptManager->initialize();
_stringManager->initialize(_gameDescription->gameId);
+ registerDefaultSettings();
+
+ loadSettings();
+
// Create debugger console. It requires GFX to be initialized
_console = new Console(this);
+ _halveDelay = ConfMan.getBool("doublefps");
}
Common::Error ZVision::run() {
initialize();
+ // Check if a saved game is to be loaded from the launcher
+ if (ConfMan.hasKey("save_slot"))
+ _saveManager->loadGame(ConfMan.getInt("save_slot"));
+
// Main loop
while (!shouldQuit()) {
_clock.update();
uint32 currentTime = _clock.getLastMeasuredTime();
uint32 deltaTime = _clock.getDeltaTime();
+ _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem));
+
processEvents();
+ updateRotation();
// Call _renderManager->update() first so the background renders
// before anything that puzzles/controls will render
- _renderManager->update(deltaTime);
_scriptManager->update(deltaTime);
+ _menu->process(deltaTime);
// Render the backBuffer to the screen
+ _renderManager->prepareBkg();
+ _renderManager->renderMenuToScreen();
+ _renderManager->processSubs(deltaTime);
_renderManager->renderBackbufferToScreen();
// Update the screen
- _system->updateScreen();
+ if (_rendDelay <= 0)
+ _system->updateScreen();
+ else
+ _rendDelay--;
// Calculate the frame delay based off a desired frame time
int delay = _desiredFrameTime - int32(_system->getMillis() - currentTime);
// Ensure non-negative
delay = delay < 0 ? 0 : delay;
+ if (_halveDelay)
+ delay >>= 1;
_system->delayMillis(delay);
}
return Common::kNoError;
}
+bool ZVision::askQuestion(const Common::String &str) {
+ uint16 msgid = _renderManager->createSubArea();
+ _renderManager->updateSubArea(msgid, str);
+ _renderManager->processSubs(0);
+ _renderManager->renderBackbufferToScreen();
+ _clock.stop();
+
+ int result = 0;
+
+ while (result == 0) {
+ Common::Event evnt;
+ while (_eventMan->pollEvent(evnt)) {
+ if (evnt.type == Common::EVENT_KEYDOWN) {
+ switch (evnt.kbd.keycode) {
+ case Common::KEYCODE_y:
+ result = 2;
+ break;
+ case Common::KEYCODE_n:
+ result = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ _system->updateScreen();
+ if (_halveDelay)
+ _system->delayMillis(33);
+ else
+ _system->delayMillis(66);
+ }
+ _renderManager->deleteSubArea(msgid);
+ _clock.start();
+ return result == 2;
+}
+
+void ZVision::delayedMessage(const Common::String &str, uint16 milsecs) {
+ uint16 msgid = _renderManager->createSubArea();
+ _renderManager->updateSubArea(msgid, str);
+ _renderManager->processSubs(0);
+ _renderManager->renderBackbufferToScreen();
+ _clock.stop();
+
+ uint32 stopTime = _system->getMillis() + milsecs;
+ while (_system->getMillis() < stopTime) {
+ Common::Event evnt;
+ while (_eventMan->pollEvent(evnt)) {
+ if (evnt.type == Common::EVENT_KEYDOWN &&
+ (evnt.kbd.keycode == Common::KEYCODE_SPACE ||
+ evnt.kbd.keycode == Common::KEYCODE_RETURN ||
+ evnt.kbd.keycode == Common::KEYCODE_ESCAPE))
+ break;
+ }
+ _system->updateScreen();
+ if (_halveDelay)
+ _system->delayMillis(33);
+ else
+ _system->delayMillis(66);
+ }
+ _renderManager->deleteSubArea(msgid);
+ _clock.start();
+}
+
+void ZVision::timedMessage(const Common::String &str, uint16 milsecs) {
+ uint16 msgid = _renderManager->createSubArea();
+ _renderManager->updateSubArea(msgid, str);
+ _renderManager->processSubs(0);
+ _renderManager->renderBackbufferToScreen();
+ _renderManager->deleteSubArea(msgid, milsecs);
+}
+
void ZVision::pauseEngineIntern(bool pause) {
_mixer->pauseAll(pause);
@@ -174,11 +332,203 @@ void ZVision::pauseEngineIntern(bool pause) {
}
Common::String ZVision::generateSaveFileName(uint slot) {
- return Common::String::format("%s.%02u", _targetName.c_str(), slot);
+ return Common::String::format("%s.%03u", _targetName.c_str(), slot);
}
Common::String ZVision::generateAutoSaveFileName() {
return Common::String::format("%s.auto", _targetName.c_str());
}
+void ZVision::setRenderDelay(uint delay) {
+ _rendDelay = delay;
+}
+
+bool ZVision::canRender() {
+ return _rendDelay <= 0;
+}
+
+void ZVision::updateRotation() {
+ int16 _velocity = _mouseVelocity + _kbdVelocity;
+
+ if (_halveDelay)
+ _velocity /= 2;
+
+ if (_velocity) {
+ RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState();
+ if (renderState == RenderTable::PANORAMA) {
+ int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos);
+
+ int16 newPosition = startPosition + (_renderManager->getRenderTable()->getPanoramaReverse() ? -_velocity : _velocity);
+
+ int16 zeroPoint = _renderManager->getRenderTable()->getPanoramaZeroPoint();
+ if (startPosition >= zeroPoint && newPosition < zeroPoint)
+ _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) - 1);
+ if (startPosition <= zeroPoint && newPosition > zeroPoint)
+ _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) + 1);
+
+ int16 screenWidth = _renderManager->getBkgSize().x;
+ if (screenWidth)
+ newPosition %= screenWidth;
+
+ if (newPosition < 0)
+ newPosition += screenWidth;
+
+ _renderManager->setBackgroundPosition(newPosition);
+ } else if (renderState == RenderTable::TILT) {
+ int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos);
+
+ int16 newPosition = startPosition + _velocity;
+
+ int16 screenHeight = _renderManager->getBkgSize().y;
+ int16 tiltGap = _renderManager->getRenderTable()->getTiltGap();
+
+ if (newPosition >= (screenHeight - tiltGap))
+ newPosition = screenHeight - tiltGap;
+ if (newPosition <= tiltGap)
+ newPosition = tiltGap;
+
+ _renderManager->setBackgroundPosition(newPosition);
+ }
+ }
+}
+
+void ZVision::checkBorders() {
+ RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState();
+ if (renderState == RenderTable::PANORAMA) {
+ int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos);
+
+ int16 newPosition = startPosition;
+
+ int16 screenWidth = _renderManager->getBkgSize().x;
+
+ if (screenWidth)
+ newPosition %= screenWidth;
+
+ if (newPosition < 0)
+ newPosition += screenWidth;
+
+ if (startPosition != newPosition)
+ _renderManager->setBackgroundPosition(newPosition);
+ } else if (renderState == RenderTable::TILT) {
+ int16 startPosition = _scriptManager->getStateValue(StateKey_ViewPos);
+
+ int16 newPosition = startPosition;
+
+ int16 screenHeight = _renderManager->getBkgSize().y;
+ int16 tiltGap = _renderManager->getRenderTable()->getTiltGap();
+
+ if (newPosition >= (screenHeight - tiltGap))
+ newPosition = screenHeight - tiltGap;
+ if (newPosition <= tiltGap)
+ newPosition = tiltGap;
+
+ if (startPosition != newPosition)
+ _renderManager->setBackgroundPosition(newPosition);
+ }
+}
+
+void ZVision::rotateTo(int16 _toPos, int16 _time) {
+ if (_renderManager->getRenderTable()->getRenderState() != RenderTable::PANORAMA)
+ return;
+
+ if (_time == 0)
+ _time = 1;
+
+ int32 maxX = _renderManager->getBkgSize().x;
+ int32 curX = _renderManager->getCurrentBackgroundOffset();
+ int32 dx = 0;
+
+ if (curX == _toPos)
+ return;
+
+ if (curX > _toPos) {
+ if (curX - _toPos > maxX / 2)
+ dx = (_toPos + (maxX - curX)) / _time;
+ else
+ dx = -(curX - _toPos) / _time;
+ } else {
+ if (_toPos - curX > maxX / 2)
+ dx = -((maxX - _toPos) + curX) / _time;
+ else
+ dx = (_toPos - curX) / _time;
+ }
+
+ _clock.stop();
+
+ for (int16 i = 0; i <= _time; i++) {
+ if (i == _time)
+ curX = _toPos;
+ else
+ curX += dx;
+
+ if (curX < 0)
+ curX = maxX - curX;
+ else if (curX >= maxX)
+ curX %= maxX;
+
+ _renderManager->setBackgroundPosition(curX);
+
+ _renderManager->prepareBkg();
+ _renderManager->renderBackbufferToScreen();
+
+ _system->updateScreen();
+
+ _system->delayMillis(500 / _time);
+ }
+
+ _clock.start();
+}
+
+void ZVision::menuBarEnable(uint16 menus) {
+ if (_menu)
+ _menu->setEnable(menus);
+}
+
+uint16 ZVision::getMenuBarEnable() {
+ if (_menu)
+ return _menu->getEnable();
+ return 0;
+}
+
+bool ZVision::ifQuit() {
+ if (askQuestion(_stringManager->getTextLine(StringManager::ZVISION_STR_EXITPROMT))) {
+ quitGame();
+ return true;
+ }
+ return false;
+}
+
+void ZVision::pushKeyToCheatBuf(uint8 key) {
+ for (int i = 0; i < KEYBUF_SIZE - 1; i++)
+ _cheatBuff[i] = _cheatBuff[i + 1];
+
+ _cheatBuff[KEYBUF_SIZE - 1] = key;
+}
+
+bool ZVision::checkCode(const char *code) {
+ int codeLen = strlen(code);
+
+ if (codeLen > KEYBUF_SIZE)
+ return false;
+
+ for (int i = 0; i < codeLen; i++)
+ if (code[i] != _cheatBuff[KEYBUF_SIZE - codeLen + i] && code[i] != '?')
+ return false;
+
+ return true;
+}
+
+uint8 ZVision::getBufferedKey(uint8 pos) {
+ if (pos >= KEYBUF_SIZE)
+ return 0;
+ else
+ return _cheatBuff[KEYBUF_SIZE - pos - 1];
+}
+
+void ZVision::showDebugMsg(const Common::String &msg, int16 delay) {
+ uint16 msgid = _renderManager->createSubArea();
+ _renderManager->updateSubArea(msgid, msg);
+ _renderManager->deleteSubArea(msgid, delay);
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h
index 0b5a86f370..5850bf66cd 100644
--- a/engines/zvision/zvision.h
+++ b/engines/zvision/zvision.h
@@ -8,24 +8,25 @@
* 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 ZVISION_ZVISION_H
#define ZVISION_ZVISION_H
-#include "zvision/core/console.h"
#include "zvision/detection.h"
#include "zvision/utility/clock.h"
+#include "zvision/core/search_manager.h"
#include "common/random.h"
#include "common/events.h"
@@ -36,7 +37,6 @@
#include "gui/debugger.h"
-
namespace Video {
class VideoDecoder;
}
@@ -44,12 +44,17 @@ class VideoDecoder;
namespace ZVision {
struct ZVisionGameDescription;
+class Console;
class ScriptManager;
class RenderManager;
class CursorManager;
class StringManager;
class SaveManager;
class RlfAnimation;
+class MenuHandler;
+class TextRenderer;
+class Subtitle;
+class MidiManager;
class ZVision : public Engine {
public:
@@ -62,7 +67,7 @@ public:
* are given in this coordinate space. Also, all images are clipped to the
* edges of this Rectangle
*/
- const Common::Rect _workingWindow;
+ const Common::Rect &_workingWindow;
const Graphics::PixelFormat _pixelFormat;
private:
@@ -71,15 +76,17 @@ private:
WINDOW_HEIGHT = 480,
//Zork nemesis working window sizes
- ZNEM_WORKING_WINDOW_WIDTH = 512,
- ZNEM_WORKING_WINDOW_HEIGHT = 320,
+ ZNM_WORKING_WINDOW_WIDTH = 512,
+ ZNM_WORKING_WINDOW_HEIGHT = 320,
//ZGI(and default) working window sizes
- ZGI_WORKING_WINDOW_WIDTH = 640,
- ZGI_WORKING_WINDOW_HEIGHT = 344,
+ WORKING_WINDOW_WIDTH = 640,
+ WORKING_WINDOW_HEIGHT = 344,
ROTATION_SCREEN_EDGE_OFFSET = 60,
- MAX_ROTATION_SPEED = 400 // Pixels per second
+ MAX_ROTATION_SPEED = 400, // Pixels per second
+
+ KEYBUF_SIZE = 20
};
Console *_console;
@@ -96,27 +103,68 @@ private:
CursorManager *_cursorManager;
SaveManager *_saveManager;
StringManager *_stringManager;
+ MenuHandler *_menu;
+ SearchManager *_searchManager;
+ TextRenderer *_textRenderer;
+ MidiManager *_midiManager;
// Clock
Clock _clock;
+ // Audio ID
+ int _audioId;
+
// To prevent allocation every time we process events
Common::Event _event;
+ const Common::Rect _workingWindow_ZGI;
+ const Common::Rect _workingWindow_ZNM;
+
+ int _rendDelay;
+ int16 _mouseVelocity;
+ int16 _kbdVelocity;
+ bool _halveDelay;
+ bool _videoIsPlaying;
+
+ uint8 _cheatBuff[KEYBUF_SIZE];
public:
uint32 getFeatures() const;
Common::Language getLanguage() const;
Common::Error run();
void pauseEngineIntern(bool pause);
- ScriptManager *getScriptManager() const { return _scriptManager; }
- RenderManager *getRenderManager() const { return _renderManager; }
- CursorManager *getCursorManager() const { return _cursorManager; }
- SaveManager *getSaveManager() const { return _saveManager; }
- StringManager *getStringManager() const { return _stringManager; }
- Common::RandomSource *getRandomSource() const { return _rnd; }
- ZVisionGameId getGameId() const { return _gameDescription->gameId; }
- GUI::Debugger *getDebugger() { return _console; }
+ ScriptManager *getScriptManager() const {
+ return _scriptManager;
+ }
+ RenderManager *getRenderManager() const {
+ return _renderManager;
+ }
+ CursorManager *getCursorManager() const {
+ return _cursorManager;
+ }
+ SaveManager *getSaveManager() const {
+ return _saveManager;
+ }
+ StringManager *getStringManager() const {
+ return _stringManager;
+ }
+ SearchManager *getSearchManager() const {
+ return _searchManager;
+ }
+ TextRenderer *getTextRenderer() const {
+ return _textRenderer;
+ }
+ MidiManager *getMidiManager() const {
+ return _midiManager;
+ }
+ Common::RandomSource *getRandomSource() const {
+ return _rnd;
+ }
+ ZVisionGameId getGameId() const {
+ return _gameDescription->gameId;
+ }
+
+ uint8 getZvisionKey(Common::KeyCode scummKeyCode);
/**
* Play a video until it is finished. This is a blocking call. It will call
@@ -127,11 +175,37 @@ public:
* @param destRect Where to put the video. (In working window coords)
* @param skippable If true, the video can be skipped at any time using [Spacebar]
*/
- void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true);
+ void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true, Subtitle *sub = NULL);
+
+ void rotateTo(int16 to, int16 time);
Common::String generateSaveFileName(uint slot);
Common::String generateAutoSaveFileName();
+ bool askQuestion(const Common::String &str);
+ void delayedMessage(const Common::String &str, uint16 milsecs);
+ void timedMessage(const Common::String &str, uint16 milsecs);
+
+ void setRenderDelay(uint);
+ bool canRender();
+
+ void loadSettings();
+ void saveSettings();
+
+ void menuBarEnable(uint16 menus);
+ uint16 getMenuBarEnable();
+
+ bool ifQuit();
+
+ void checkBorders();
+ void showDebugMsg(const Common::String &msg, int16 delay = 3000);
+
+ // Engine features
+ bool hasFeature(EngineFeature f) const;
+ bool canLoadGameStateCurrently();
+ bool canSaveGameStateCurrently();
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const Common::String &desc);
private:
void initialize();
void initFonts();
@@ -141,9 +215,16 @@ private:
/** Called every frame from ZVision::run() to process any events from EventMan */
void processEvents();
- void onMouseDown(const Common::Point &pos);
- void onMouseUp(const Common::Point &pos);
void onMouseMove(const Common::Point &pos);
+ void updateRotation();
+
+ void registerDefaultSettings();
+ void shortKeys(Common::Event);
+
+ void cheatCodes(uint8 key);
+ void pushKeyToCheatBuf(uint8 key);
+ bool checkCode(const char *code);
+ uint8 getBufferedKey(uint8 pos);
};
} // End of namespace ZVision
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 703da68182..6b657f758d 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -105,7 +105,7 @@ VectorRenderer *createRenderer(int mode);
*/
class VectorRenderer {
public:
- VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
+ VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
_disableShadows(false), _strokeWidth(1), _gradientFactor(1) {
}
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index a9594f7dd2..81a0c04441 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -1134,7 +1134,7 @@ void VectorRendererSpec<PixelType>::
drawTabShadow(int x1, int y1, int w, int h, int r) {
int offset = 3;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
-
+
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
uint8 expFactor = 3;
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
@@ -1162,7 +1162,7 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;
-
+
while (x++ < y) {
BE_ALGORITHM();
@@ -1176,7 +1176,7 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
hb |= (1 << y);
}
}
-
+
ptr_fill += pitch * r;
while (short_h--) {
blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
@@ -1189,7 +1189,7 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
alpha = (alpha * (expFactor << 8)) >> 9;
}
}
-
+
/** BEVELED TABS FOR CLASSIC THEME **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1647,7 +1647,7 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
BE_RESET();
r--;
-
+
int alphaStep_tr = ((alpha_t - alpha_r)/(y+1));
int alphaStep_br = ((alpha_r - alpha_b)/(y+1));
int alphaStep_bl = ((alpha_b - alpha_l)/(y+1));
@@ -1657,16 +1657,16 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
while (x++ < (y - 2)) {
BE_ALGORITHM();
- BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
+ BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)));
-
+
BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)));
BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)));
BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)));
BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)));
-
+
if (Base::_strokeWidth > 1) {
BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
@@ -1754,7 +1754,7 @@ void VectorRendererSpec<PixelType>::
drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
const uint8 borderAlpha_t = 0;
const uint8 borderAlpha_r = 127;
- const uint8 borderAlpha_b = 255;
+ const uint8 borderAlpha_b = 255;
const uint8 borderAlpha_l = 63;
const uint8 bevelAlpha_t = 255;
@@ -1876,7 +1876,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
uint8 expFactor = 3;
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
-
+
// These constants ensure a border of 2px on the left and of each rounded square
int xstart = (x1 > 2) ? x1 - 2 : x1;
int ystart = y1;
@@ -1886,7 +1886,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y;
int x, y, px, py;
-
+
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
@@ -1903,14 +1903,14 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;
-
+
while (x++ < y) {
BE_ALGORITHM();
if (((1 << x) & hb) == 0) {
blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
-
+
// Will create a dark line of pixles if left out
if (hb > 0) {
blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
@@ -1924,7 +1924,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
hb |= (1 << y);
}
}
-
+
ptr_fill += pitch * r;
while (short_h--) {
blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
@@ -1936,7 +1936,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
ystart += 1;
width -= 2;
height -= 2;
-
+
if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor
alpha = (alpha * (expFactor << 8)) >> 9;
@@ -2178,14 +2178,14 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
// only when the inside isn't filled
if (sw != strokeWidth || fill_m != Base::kFillDisabled)
a2 = 255;
-
- // inner arc
- WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16));
+
+ // inner arc
+ WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a2) >> 16));
-
- WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16));
+
+ WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a2) >> 16));
WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a2) >> 16));
@@ -2196,8 +2196,8 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a1) >> 16));
WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a1) >> 16));
WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a1) >> 16));
-
- WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16));
+
+ WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16));
WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a1) >> 16));
WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a1) >> 16));
WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a1) >> 16));
@@ -2220,7 +2220,7 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
int x, y;
const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int px, py;
-
+
uint32 rsq = r*r;
frac_t T = 0, oldT;
uint8 a1, a2;
@@ -2318,14 +2318,14 @@ void VectorRendererAA<PixelType>::
drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
const uint8 borderAlpha_t = 0;
const uint8 borderAlpha_r = 127;
- const uint8 borderAlpha_b = 255;
+ const uint8 borderAlpha_b = 255;
const uint8 borderAlpha_l = 63;
const uint8 bevelAlpha_t = 255;
const uint8 bevelAlpha_r = 31;
const uint8 bevelAlpha_b = 0;
const uint8 bevelAlpha_l = 127;
-
+
if (Base::_strokeWidth) {
if (r != 0 && Base::_bevel > 0) {
drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
@@ -2334,7 +2334,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
}
}
-
+
// If only border is visible
if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
if (fill_m == Base::kFillBackground)
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index c035ca0e19..f47cc3997a 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -301,7 +301,7 @@ protected:
virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_l, uint8 alpha_r, uint8 alpha_b);
-
+
virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) {
diff --git a/graphics/surface.h b/graphics/surface.h
index ad15944361..aaa386b168 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -228,7 +228,7 @@ public:
* @param srcSurface The source of the bitmap data
* @param destX The x coordinate of the destination rectangle
* @param destY The y coordinate of the destination rectangle
- * @param subRect The subRect of surface to be blitted
+ * @param subRect The subRect of surface to be blitted
*/
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect);
diff --git a/graphics/transform_struct.h b/graphics/transform_struct.h
index 640daf9f4c..1d37492de4 100644
--- a/graphics/transform_struct.h
+++ b/graphics/transform_struct.h
@@ -48,7 +48,7 @@ const int32 kDefaultHotspotX = 0;
const int32 kDefaultHotspotY = 0;
const int32 kDefaultOffsetX = 0;
const int32 kDefaultOffsetY = 0;
-const int32 kDefaultAngle = 0;
+const int32 kDefaultAngle = 0;
struct TransformStruct {
private:
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index ab284aaa6e..d0371f5e78 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -49,7 +49,6 @@ namespace GUI {
const int kMaxRecordsNames = 0x64;
const int kDefaultScreenshotPeriod = 60000;
-const int kDefaultBPP = 2;
uint32 readTime(Common::ReadStream *inFile) {
uint32 d = inFile->readByte();
diff --git a/gui/about.cpp b/gui/about.cpp
index fe726df750..b25efc1cd0 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -241,7 +241,7 @@ void AboutDialog::drawDialog() {
while (*str && *str == ' ')
str++;
- if (*str)
+ if (*str)
g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
y += _lineHeight;
}
diff --git a/gui/browser_osx.mm b/gui/browser_osx.mm
index 0e80410032..18cbd134f3 100644
--- a/gui/browser_osx.mm
+++ b/gui/browser_osx.mm
@@ -154,7 +154,11 @@ int BrowserDialog::runModal() {
[showHiddenFilesButton setAction:@selector(showHiddenFiles:)];
}
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1090
if ([panel runModal] == NSOKButton) {
+#else
+ if ([panel runModal] == NSModalResponseOK) {
+#endif
NSURL *url = [panel URL];
if ([url isFileURL]) {
const char *filename = [[url path] UTF8String];
diff --git a/gui/credits.h b/gui/credits.h
index e32a0705bf..5b33797a63 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -320,6 +320,7 @@ static const char *credits[] = {
"C1""Wintermute",
"A0""Einar Johan T. Somaaen",
"C0""Einar Johan T. S\370m\345en",
+"C0""Tobia Tesan",
"",
"C1""ZVision",
"C0""Adrian Astley",
@@ -810,7 +811,7 @@ static const char *credits[] = {
"C0""DOSBox Team",
"C2""For their awesome OPL2 and OPL3 emulator",
"C0""Yusuke Kamiyamane",
-"C2""For contributing some GUI icons ",
+"C2""For contributing some GUI icons",
"C0""Till Kresslein",
"C2""For design of modern ScummVM GUI",
"C0""Jezar",
@@ -850,7 +851,7 @@ static const char *credits[] = {
"C0""",
"C0""Neil Dodwell and David Dew from Creative Reality for providing the source of Dreamweb and for their tremendous support.",
"C0""",
-"C0""Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon for providing full source code for Soltys and letting us redistribute the game.",
+"C0""Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon for providing full source code for Soltys and Sfinx and letting us redistribute the games.",
"C0""",
"C0""Jan Nedoma for providing the sources to the Wintermute-engine, and for his support while porting the engine to ScummVM.",
"C0""",
diff --git a/gui/debugger.cpp b/gui/debugger.cpp
index dcdc18d7b9..216bd626fe 100644
--- a/gui/debugger.cpp
+++ b/gui/debugger.cpp
@@ -27,6 +27,13 @@
#include "common/debug-channels.h"
#include "common/system.h"
+#ifndef DISABLE_MD5
+#include "common/md5.h"
+#include "common/archive.h"
+#include "common/macresman.h"
+#include "common/stream.h"
+#endif
+
#include "engines/engine.h"
#include "gui/debugger.h"
@@ -61,6 +68,10 @@ Debugger::Debugger() {
registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
registerCmd("openlog", WRAP_METHOD(Debugger, cmdOpenLog));
+#ifndef DISABLE_MD5
+ registerCmd("md5", WRAP_METHOD(Debugger, cmdMd5));
+ registerCmd("md5mac", WRAP_METHOD(Debugger, cmdMd5Mac));
+#endif
registerCmd("debuglevel", WRAP_METHOD(Debugger, cmdDebugLevel));
registerCmd("debugflag_list", WRAP_METHOD(Debugger, cmdDebugFlagsList));
@@ -502,6 +513,76 @@ bool Debugger::cmdOpenLog(int argc, const char **argv) {
return true;
}
+#ifndef DISABLE_MD5
+struct ArchiveMemberLess {
+ bool operator()(const Common::ArchiveMemberPtr &x, const Common::ArchiveMemberPtr &y) const {
+ return (*x).getDisplayName().compareToIgnoreCase((*y).getDisplayName()) < 0;
+ }
+};
+
+bool Debugger::cmdMd5(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("md5 <filename | pattern>\n");
+ } else {
+ // Assume that spaces are part of a single filename.
+ Common::String filename = argv[1];
+ for (int i = 2; i < argc; i++) {
+ filename = filename + " " + argv[i];
+ }
+ Common::ArchiveMemberList list;
+ SearchMan.listMatchingMembers(list, filename);
+ if (list.empty()) {
+ debugPrintf("File '%s' not found\n", filename.c_str());
+ } else {
+ sort(list.begin(), list.end(), ArchiveMemberLess());
+ for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
+ Common::ReadStream *stream = (*iter)->createReadStream();
+ Common::String md5 = Common::computeStreamMD5AsString(*stream, 0);
+ debugPrintf("%s %s\n", md5.c_str(), (*iter)->getDisplayName().c_str());
+ delete stream;
+ }
+ }
+ }
+ return true;
+}
+
+bool Debugger::cmdMd5Mac(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("md5mac <base filename>\n");
+ } else {
+ // Assume that spaces are part of a single filename.
+ Common::String filename = argv[1];
+ for (int i = 2; i < argc; i++) {
+ filename = filename + " " + argv[i];
+ }
+ Common::MacResManager macResMan;
+ // FIXME: There currently isn't any way to tell the Mac resource
+ // manager to open a specific file. Instead, it takes a "base name"
+ // and constructs a file name out of that. While usually a desirable
+ // thing, it's not ideal here.
+ if (!macResMan.open(filename)) {
+ debugPrintf("Resource file '%s' not found\n", filename.c_str());
+ } else {
+ if (!macResMan.hasResFork() && !macResMan.hasDataFork()) {
+ debugPrintf("'%s' has neither data not resource fork\n", macResMan.getBaseFileName().c_str());
+ } else {
+ // The resource fork is probably the most relevant one.
+ if (macResMan.hasResFork()) {
+ Common::String md5 = macResMan.computeResForkMD5AsString(0);
+ debugPrintf("%s %s (resource)\n", md5.c_str(), macResMan.getBaseFileName().c_str());
+ }
+ if (macResMan.hasDataFork()) {
+ Common::ReadStream *stream = macResMan.getDataFork();
+ Common::String md5 = Common::computeStreamMD5AsString(*stream, 0);
+ debugPrintf("%s %s (data)\n", md5.c_str(), macResMan.getBaseFileName().c_str());
+ }
+ }
+ macResMan.close();
+ }
+ }
+ return true;
+}
+#endif
bool Debugger::cmdDebugLevel(int argc, const char **argv) {
if (argc == 1) { // print level
diff --git a/gui/debugger.h b/gui/debugger.h
index 175eb33960..ef6f900974 100644
--- a/gui/debugger.h
+++ b/gui/debugger.h
@@ -213,6 +213,10 @@ protected:
bool cmdExit(int argc, const char **argv);
bool cmdHelp(int argc, const char **argv);
bool cmdOpenLog(int argc, const char **argv);
+#ifndef DISABLE_MD5
+ bool cmdMd5(int argc, const char **argv);
+ bool cmdMd5Mac(int argc, const char **argv);
+#endif
bool cmdDebugLevel(int argc, const char **argv);
bool cmdDebugFlagsList(int argc, const char **argv);
bool cmdDebugFlagEnable(int argc, const char **argv);
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index e40e8b1e26..c7c585654d 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index b760e15919..7e61d6820e 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -1169,9 +1169,9 @@
height = 'Globals.Line.Height'
/>
<widget name = 'HelpText'
- height = '220'
+ height = '228'
/>
- <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <layout type = 'horizontal' padding = '0, 0, 8, 0'>
<widget name = 'Prev'
type = 'Button'
/>
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index abd745bb2b..bfa33d4feb 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 3e72350c99..550b1bd153 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -94,7 +94,7 @@ void EditTextWidget::drawWidget() {
// Draw the text
adjustOffset();
-
+
const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
setTextDrawableArea(r);
diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h
index a01ee2d9dc..148f164fbb 100644
--- a/gui/widgets/tab.h
+++ b/gui/widgets/tab.h
@@ -28,7 +28,7 @@
#include "common/array.h"
namespace GUI {
-
+
enum {
kTabForwards = 1,
kTabBackwards = -1
diff --git a/image/codecs/mjpeg.cpp b/image/codecs/mjpeg.cpp
index 4ad72f259d..6e7faf1045 100644
--- a/image/codecs/mjpeg.cpp
+++ b/image/codecs/mjpeg.cpp
@@ -87,9 +87,11 @@ static const byte s_mjpegValDC[12] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
+#if 0
static const byte s_mjpegBitsDCChrominance[17] = {
/* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
};
+#endif
static const byte s_mjpegBitsACLuminance[17] = {
/* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
diff --git a/image/codecs/mpeg.h b/image/codecs/mpeg.h
index 6cb10f21ac..82c3ad19ac 100644
--- a/image/codecs/mpeg.h
+++ b/image/codecs/mpeg.h
@@ -62,7 +62,7 @@ namespace Graphics {
struct Surface;
}
-namespace Image {
+namespace Image {
/**
* MPEG 1/2 video decoder.
diff --git a/image/iff.cpp b/image/iff.cpp
index d93e9ff878..d75fffb31f 100644
--- a/image/iff.cpp
+++ b/image/iff.cpp
@@ -31,7 +31,7 @@ namespace Image {
IFFDecoder::IFFDecoder() {
_surface = 0;
_palette = 0;
-
+
// these 2 properties are not reset by destroy(), so the default is set here.
_numRelevantPlanes = 8;
_pixelPacking = false;
diff --git a/image/image_decoder.h b/image/image_decoder.h
index 4d3512e0f6..2018cebd37 100644
--- a/image/image_decoder.h
+++ b/image/image_decoder.h
@@ -48,7 +48,7 @@ public:
/**
* Load an image from the specified stream
- *
+ *
* loadStream() should implicitly call destroy() to free the memory
* of the last loadStream() call.
*
diff --git a/po/nl_NL.po b/po/nl_NL.po
index 43ac274ac5..3a9e6d8172 100644
--- a/po/nl_NL.po
+++ b/po/nl_NL.po
@@ -1,21 +1,21 @@
# LANGUAGE translation for ScummVM.
# Copyright (C) YEAR ScummVM Team
# This file is distributed under the same license as the ScummVM package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# FIRST AUTHOR scummvm@bencastricum.nl, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2014-10-04 00:58+0100\n"
-"PO-Revision-Date: 2014-09-03 07:42+0100\n"
+"POT-Creation-Date: 2014-11-25 20:41+0100\n"
+"PO-Revision-Date: 2014-11-25 20:46+0100\n"
"Last-Translator: Ben Castricum <scummvm@bencastricum.nl>\n"
"Language-Team: Ben Castricum <scummvm@bencastricum.nl>\n"
"Language: Nederlands\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.5.3\n"
+"X-Generator: Poedit 1.6.10\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -34,11 +34,11 @@ msgstr "Beschikbare engines:"
#: gui/browser.cpp:68
msgid "Show hidden files"
-msgstr "Verborgen bestanden weergeven"
+msgstr "Toon verborgen bestanden"
#: gui/browser.cpp:68
msgid "Show files marked with the hidden attribute"
-msgstr "Toon de bestanden die met het verborgen kenmerk hebben."
+msgstr "Toon bestanden die het verborgen kenmerk hebben."
#: gui/browser.cpp:72
msgid "Go up"
@@ -108,7 +108,7 @@ msgstr "Koppel"
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
#: engines/agos/animation.cpp:558 engines/drascula/saveload.cpp:49
-#: engines/groovie/script.cpp:399 engines/parallaction/saveload.cpp:274
+#: engines/groovie/script.cpp:408 engines/parallaction/saveload.cpp:274
#: engines/scumm/dialogs.cpp:193 engines/scumm/scumm.cpp:1825
#: engines/scumm/players/player_v3m.cpp:130
#: engines/scumm/players/player_v5m.cpp:108 engines/sky/compact.cpp:131
@@ -214,7 +214,7 @@ msgstr "Engine"
#: gui/launcher.cpp:245 gui/options.cpp:1073 gui/options.cpp:1090
msgid "Graphics"
-msgstr "Grafisch"
+msgstr "Beeld"
#: gui/launcher.cpp:245 gui/options.cpp:1073 gui/options.cpp:1090
msgid "GFX"
@@ -231,7 +231,7 @@ msgstr "Negeer algemene grafische instellingen"
#: gui/launcher.cpp:257 gui/options.cpp:1096
msgid "Audio"
-msgstr "Audio"
+msgstr "Geluid"
#: gui/launcher.cpp:260
msgid "Override global audio settings"
@@ -319,7 +319,7 @@ msgstr "Extra Pad:"
#: gui/launcher.cpp:339 gui/options.cpp:1134
msgid "Save Path:"
-msgstr "Save Pad:"
+msgstr "Bewaar Pad:"
#: gui/launcher.cpp:339 gui/launcher.cpp:341 gui/launcher.cpp:342
#: gui/options.cpp:1134 gui/options.cpp:1136 gui/options.cpp:1137
@@ -329,7 +329,7 @@ msgstr "Bepaalt waar opgeslagen spellen worden bewaard."
#: gui/launcher.cpp:341 gui/options.cpp:1136
msgctxt "lowres"
msgid "Save Path:"
-msgstr "Save Pad:"
+msgstr "Bewaar Pad:"
#: gui/launcher.cpp:360 gui/launcher.cpp:459 gui/launcher.cpp:517
#: gui/launcher.cpp:571 gui/options.cpp:1145 gui/options.cpp:1153
@@ -604,8 +604,7 @@ msgstr "Geen"
#: gui/options.cpp:389
msgid "Failed to apply some of the graphic options changes:"
-msgstr ""
-"Het is niet gelukt om enkele veranderingen in grafische opties toe te passen:"
+msgstr "Sommige grafische opties konden niet worden toegepast:"
#: gui/options.cpp:401
msgid "the video mode could not be changed."
@@ -781,7 +780,7 @@ msgstr "Geen Roland MT-32 muziek gebruiken"
#: gui/options.cpp:927
msgid "Text and Speech:"
-msgstr "Spraak en/of ondertitels:"
+msgstr "Spraak en/of tekst:"
#: gui/options.cpp:931 gui/options.cpp:941
msgid "Speech"
@@ -789,7 +788,7 @@ msgstr "Spraak"
#: gui/options.cpp:932 gui/options.cpp:942
msgid "Subtitles"
-msgstr "Ondertitels"
+msgstr "Tekst"
#: gui/options.cpp:933
msgid "Both"
@@ -797,7 +796,7 @@ msgstr "Beide"
#: gui/options.cpp:935
msgid "Subtitle speed:"
-msgstr "Snelheid ondertitels:"
+msgstr "Snelheid tekst:"
#: gui/options.cpp:937
msgctxt "lowres"
@@ -819,7 +818,7 @@ msgstr "Beide"
#: gui/options.cpp:943
msgid "Show subtitles and play speech"
-msgstr "Toon ondertitels en speel spraak af"
+msgstr "Toon tekst en speel spraak af"
#: gui/options.cpp:945
msgctxt "lowres"
@@ -1277,17 +1276,17 @@ msgstr "O~v~er"
#: engines/dialogs.cpp:105 engines/dialogs.cpp:181
msgid "~R~eturn to Launcher"
-msgstr "~T~erug naar het startmenu"
+msgstr "Terug naar s~t~artmenu"
#: engines/dialogs.cpp:107 engines/dialogs.cpp:183
msgctxt "lowres"
msgid "~R~eturn to Launcher"
-msgstr "~T~erug naar startmenu"
+msgstr "S~t~artmenu"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:803
#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:873
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:758
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:759
#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Spel opslaan:"
@@ -1300,7 +1299,7 @@ msgstr "Spel opslaan:"
#: engines/agi/saveload.cpp:803 engines/cruise/menu.cpp:212
#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
#: engines/neverhood/menumodule.cpp:873 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:758 engines/scumm/dialogs.cpp:188
+#: engines/sci/engine/kfile.cpp:759 engines/scumm/dialogs.cpp:188
#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Opslaan"
@@ -1540,7 +1539,7 @@ msgstr "~I~ndy vecht besturing"
#: backends/platform/ds/arm9/source/dsoptions.cpp:65
msgid "Show mouse cursor"
-msgstr "Toon muis wijzer"
+msgstr "Toon muiswijzer"
#: backends/platform/ds/arm9/source/dsoptions.cpp:66
msgid "Snap to edges"
@@ -1769,7 +1768,7 @@ msgstr "Video"
#: backends/platform/wii/options.cpp:54
msgid "Current video mode:"
-msgstr "Huidige video modus:"
+msgstr "Huidige videomodus:"
#: backends/platform/wii/options.cpp:56
msgid "Double-strike"
@@ -2113,13 +2112,13 @@ msgstr ""
#: engines/agi/saveload.cpp:816 engines/drascula/saveload.cpp:349
#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:886
-#: engines/sci/engine/kfile.cpp:857 engines/toltecs/menu.cpp:256
+#: engines/sci/engine/kfile.cpp:858 engines/toltecs/menu.cpp:256
msgid "Restore game:"
msgstr "Laad opgeslagen spel:"
#: engines/agi/saveload.cpp:816 engines/drascula/saveload.cpp:349
#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:886
-#: engines/sci/engine/kfile.cpp:857 engines/toltecs/menu.cpp:256
+#: engines/sci/engine/kfile.cpp:858 engines/toltecs/menu.cpp:256
msgid "Restore"
msgstr "Laad"
@@ -2161,14 +2160,13 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Cutscene bestand '%s' niet gevonden!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:81
-#, fuzzy
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:91
msgid "Color Blind Mode"
-msgstr "Klik Modus"
+msgstr "Kleurenblind Modus"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:82
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:92
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Schakel Kleurenblind modus standaard in"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2218,17 +2216,17 @@ msgstr "Film snel afspelen"
msgid "Play movies at an increased speed"
msgstr "Speel films sneller af"
-#: engines/groovie/script.cpp:399
+#: engines/groovie/script.cpp:408
msgid "Failed to save game"
msgstr "Opslaan van spel mislukt."
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Gore Modus"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Gore modus inschakelen waar mogelijk"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2359,6 +2357,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Het volgende originele opgeslagen spel was gevonden in uw spel pad:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Wilt u dit opgeslagen spel gebruiken in ScummVM?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2366,6 +2370,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"Er is al een opgeslagen spel in slot %d. Deze overschrijven?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2377,6 +2383,12 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"%d origneel opgeslagen spellen zijn succesvol geimporteerd in ScummVM.\n"
+"Als u later handmatig origineel opgeslagen spellen wilt importeren dan zult "
+"u de\n"
+"ScummVM debug console moeten openen en het commando 'import_savefile' "
+"gebruiken.\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2433,7 +2445,7 @@ msgstr ""
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
-msgstr "Laden spel..."
+msgstr "Spel laden..."
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
@@ -2510,12 +2522,12 @@ msgstr "Toon/Verberg Pauze-Menu"
#: engines/queen/detection.cpp:56
msgid "Alternative intro"
-msgstr ""
+msgstr "Alternatieve intro"
#: engines/queen/detection.cpp:57
-#, fuzzy
msgid "Use an alternative game intro (CD version only)"
-msgstr "Gebruik de floppy versie van de intro (alleen voor de CD versie)"
+msgstr ""
+"Gebruik een alternatieve versie van de intro (alleen voor de CD versie)"
#: engines/sci/detection.cpp:374
msgid "EGA undithering"
@@ -2598,12 +2610,12 @@ msgstr "Spel is gepauzeerd. Druk op de spatiebalk om verder te gaan."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-msgid "Are you sure you want to restart? (Y/N)"
+msgid "Are you sure you want to restart? (Y/N)Y"
msgstr "Weet u zeker dat u opnieuw wilt beginnen? (J/N)J"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-msgid "Are you sure you want to quit? (Y/N)"
+msgid "Are you sure you want to quit? (Y/N)Y"
msgstr "Weet u zeker dat u wilt stoppen? (J/N)J"
#: engines/scumm/dialogs.cpp:190
@@ -3224,12 +3236,16 @@ msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"De 'Loom' Macintosh executable is niet gevonden om de instrumenten van te "
+"laden. Muziek wordt uitgeschakeld."
#: engines/scumm/players/player_v5m.cpp:107
msgid ""
"Could not find the 'Monkey Island' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"De 'Monkey Island' Macintosh executable is niet gevonden om de instrumenten "
+"van te laden. Muziek wordt uitgeschakeld."
#: engines/sky/compact.cpp:130
msgid ""
@@ -3312,7 +3328,7 @@ msgstr "Houd de nieuwe"
#: engines/sword1/logic.cpp:1633
msgid "This is the end of the Broken Sword 1 Demo"
-msgstr "Dit is het einde van de Broken Sword 1 Demo"
+msgstr "Dit is het einde van de Broken Sword 1 demo."
#: engines/sword2/animation.cpp:425
msgid ""
@@ -3346,8 +3362,8 @@ msgstr ""
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Toon FPS-teller"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
-msgstr ""
+msgstr "Toon de huidige Frames Per Second teller in de linkerbovenhoek"
diff --git a/ports.mk b/ports.mk
index 97b43fe92e..fdab7e23af 100644
--- a/ports.mk
+++ b/ports.mk
@@ -12,6 +12,8 @@ install:
$(INSTALL) -c -m 644 "$(srcdir)/dists/scummvm.6" "$(DESTDIR)$(mandir)/man6/scummvm.6"
$(INSTALL) -d "$(DESTDIR)$(datarootdir)/pixmaps/"
$(INSTALL) -c -m 644 "$(srcdir)/icons/scummvm.xpm" "$(DESTDIR)$(datarootdir)/pixmaps/scummvm.xpm"
+ $(INSTALL) -d "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/"
+ $(INSTALL) -c -m 644 "$(srcdir)/icons/scummvm.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/scummvm.svg"
$(INSTALL) -d "$(DESTDIR)$(docdir)"
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) "$(DESTDIR)$(docdir)"
$(INSTALL) -d "$(DESTDIR)$(datadir)"
@@ -28,6 +30,8 @@ install-strip:
$(INSTALL) -c -m 644 "$(srcdir)/dists/scummvm.6" "$(DESTDIR)$(mandir)/man6/scummvm.6"
$(INSTALL) -d "$(DESTDIR)$(datarootdir)/pixmaps/"
$(INSTALL) -c -m 644 "$(srcdir)/icons/scummvm.xpm" "$(DESTDIR)$(datarootdir)/pixmaps/scummvm.xpm"
+ $(INSTALL) -d "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/"
+ $(INSTALL) -c -m 644 "$(srcdir)/icons/scummvm.svg" "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/scummvm.svg"
$(INSTALL) -d "$(DESTDIR)$(docdir)"
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) "$(DESTDIR)$(docdir)"
$(INSTALL) -d "$(DESTDIR)$(datadir)"
@@ -41,6 +45,7 @@ uninstall:
rm -f "$(DESTDIR)$(bindir)/$(EXECUTABLE)"
rm -f "$(DESTDIR)$(mandir)/man6/scummvm.6"
rm -f "$(DESTDIR)$(datarootdir)/pixmaps/scummvm.xpm"
+ rm -f "$(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/scummvm.svg"
rm -rf "$(DESTDIR)$(docdir)"
rm -rf "$(DESTDIR)$(datadir)"
ifdef DYNAMIC_MODULES
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index d9761e1c38..7119c72f07 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -149,7 +149,7 @@ bool AVIDecoder::parseNextChunk() {
skipChunk(size);
break;
case ID_IDX1:
- readOldIndex(size);
+ readOldIndex(size);
break;
default:
error("Unknown tag \'%s\' found", tag2str(tag));
@@ -319,8 +319,25 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
return false;
}
- // Seek back to the start of the MOVI list
- _fileStream->seek(_movieListStart);
+ // Create the status entries
+ uint32 index = 0;
+ for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, index++) {
+ TrackStatus status;
+ status.track = *it;
+ status.index = index;
+ status.chunkSearchOffset = _movieListStart;
+
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo)
+ _videoTracks.push_back(status);
+ else
+ _audioTracks.push_back(status);
+ }
+
+ if (_videoTracks.size() != 1) {
+ warning("Unhandled AVI video track count: %d", _videoTracks.size());
+ close();
+ return false;
+ }
// Check if this is a special Duck Truemotion video
checkTruemotion1();
@@ -340,79 +357,138 @@ void AVIDecoder::close() {
_indexEntries.clear();
memset(&_header, 0, sizeof(_header));
+
+ _videoTracks.clear();
+ _audioTracks.clear();
}
void AVIDecoder::readNextPacket() {
- if ((uint32)_fileStream->pos() >= _movieListEnd) {
- // Ugh, reached the end premature.
- forceVideoEnd();
+ // Shouldn't get this unless called on a non-open video
+ if (_videoTracks.empty())
return;
- }
- uint32 nextTag = _fileStream->readUint32BE();
- uint32 size = _fileStream->readUint32LE();
+ // Get the video frame first
+ handleNextPacket(_videoTracks[0]);
+
+ // Handle audio tracks next
+ for (uint32 i = 0; i < _audioTracks.size(); i++)
+ handleNextPacket(_audioTracks[i]);
+}
+
+void AVIDecoder::handleNextPacket(TrackStatus &status) {
+ // If there's no more to search, bail out
+ if (status.chunkSearchOffset + 8 >= _movieListEnd) {
+ if (status.track->getTrackType() == Track::kTrackTypeVideo) {
+ // Horrible AVI video has a premature end
+ // Force the frame to be the last frame
+ debug(0, "Forcing end of AVI video");
+ ((AVIVideoTrack *)status.track)->forceTrackEnd();
+ }
- if (_fileStream->eos()) {
- // Also premature end.
- forceVideoEnd();
return;
}
- if (nextTag == ID_LIST) {
- // A list of audio/video chunks
- int32 startPos = _fileStream->pos();
+ // See if audio needs to be buffered and break out if not
+ if (status.track->getTrackType() == Track::kTrackTypeAudio && !shouldQueueAudio(status))
+ return;
- if (_fileStream->readUint32BE() != ID_REC)
- error("Expected 'rec ' LIST");
+ // Seek to where we shall start searching
+ _fileStream->seek(status.chunkSearchOffset);
+
+ for (;;) {
+ // If there's no more to search, bail out
+ if ((uint32)_fileStream->pos() + 8 >= _movieListEnd) {
+ if (status.track->getTrackType() == Track::kTrackTypeVideo) {
+ // Horrible AVI video has a premature end
+ // Force the frame to be the last frame
+ debug(0, "Forcing end of AVI video");
+ ((AVIVideoTrack *)status.track)->forceTrackEnd();
+ }
- size -= 4; // subtract list type
+ break;
+ }
- // Decode chunks in the list
- while (_fileStream->pos() < startPos + (int32)size)
- readNextPacket();
+ uint32 nextTag = _fileStream->readUint32BE();
+ uint32 size = _fileStream->readUint32LE();
- return;
- } else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
- skipChunk(size);
- return;
- }
+ if (nextTag == ID_LIST) {
+ // A list of audio/video chunks
+ if (_fileStream->readUint32BE() != ID_REC)
+ error("Expected 'rec ' LIST");
- Track *track = getTrack(getStreamIndex(nextTag));
+ continue;
+ } else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
+ skipChunk(size);
+ continue;
+ }
- if (!track)
- error("Cannot get track from tag '%s'", tag2str(nextTag));
+ // Only accept chunks for this stream
+ uint32 streamIndex = getStreamIndex(nextTag);
+ if (streamIndex != status.index) {
+ skipChunk(size);
+ continue;
+ }
- Common::SeekableReadStream *chunk = 0;
+ Common::SeekableReadStream *chunk = 0;
- if (size != 0) {
- chunk = _fileStream->readStream(size);
- _fileStream->skip(size & 1);
- }
+ if (size != 0) {
+ chunk = _fileStream->readStream(size);
+ _fileStream->skip(size & 1);
+ }
- if (track->getTrackType() == Track::kTrackTypeAudio) {
- if (getStreamType(nextTag) != kStreamTypeAudio)
- error("Invalid audio track tag '%s'", tag2str(nextTag));
+ if (status.track->getTrackType() == Track::kTrackTypeAudio) {
+ if (getStreamType(nextTag) != kStreamTypeAudio)
+ error("Invalid audio track tag '%s'", tag2str(nextTag));
- assert(chunk);
- ((AVIAudioTrack *)track)->queueSound(chunk);
- } else {
- AVIVideoTrack *videoTrack = (AVIVideoTrack *)track;
+ assert(chunk);
+ ((AVIAudioTrack *)status.track)->queueSound(chunk);
- if (getStreamType(nextTag) == kStreamTypePaletteChange) {
- // Palette Change
- videoTrack->loadPaletteFromChunk(chunk);
+ // Break out if we have enough audio
+ if (!shouldQueueAudio(status))
+ break;
} else {
- // Otherwise, assume it's a compressed frame
- videoTrack->decodeFrame(chunk);
+ AVIVideoTrack *videoTrack = (AVIVideoTrack *)status.track;
+
+ if (getStreamType(nextTag) == kStreamTypePaletteChange) {
+ // Palette Change
+ videoTrack->loadPaletteFromChunk(chunk);
+ } else {
+ // Otherwise, assume it's a compressed frame
+ videoTrack->decodeFrame(chunk);
+ break;
+ }
}
}
+
+ // Start us off in this position next time
+ status.chunkSearchOffset = _fileStream->pos();
+}
+
+bool AVIDecoder::shouldQueueAudio(TrackStatus& status) {
+ // Sanity check:
+ if (status.track->getTrackType() != Track::kTrackTypeAudio)
+ return false;
+
+ // If video is done, make sure that the rest of the audio is queued
+ // (I guess this is also really a sanity check)
+ AVIVideoTrack *videoTrack = (AVIVideoTrack *)_videoTracks[0].track;
+ if (videoTrack->endOfTrack())
+ return true;
+
+ // Being three frames ahead should be enough for any video.
+ return ((AVIAudioTrack *)status.track)->getCurChunk() < (uint32)(videoTrack->getCurFrame() + 3);
}
bool AVIDecoder::rewind() {
if (!VideoDecoder::rewind())
return false;
- _fileStream->seek(_movieListStart);
+ for (uint32 i = 0; i < _videoTracks.size(); i++)
+ _videoTracks[i].chunkSearchOffset = _movieListStart;
+
+ for (uint32 i = 0; i < _audioTracks.size(); i++)
+ _audioTracks[i].chunkSearchOffset = _movieListStart;
+
return true;
}
@@ -421,29 +497,9 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
if (time > getDuration())
return false;
- // Track down our video track.
- // We only support seeking with one video track right now.
- AVIVideoTrack *videoTrack = 0;
- int videoIndex = -1;
- uint trackID = 0;
-
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, trackID++) {
- if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
- if (videoTrack) {
- // Already have one
- // -> Not supported
- return false;
- }
-
- videoTrack = (AVIVideoTrack *)*it;
- videoIndex = trackID;
- }
- }
-
- // Need a video track to go forwards
- // If there isn't a video track, why would anyone be using AVI then?
- if (!videoTrack)
- return false;
+ // Get our video
+ AVIVideoTrack *videoTrack = (AVIVideoTrack *)_videoTracks[0].track;
+ uint32 videoIndex = _videoTracks[0].index;
// If we seek directly to the end, just mark the tracks as over
if (time == getDuration()) {
@@ -464,7 +520,6 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
int lastKeyFrame = -1;
int frameIndex = -1;
- int lastRecord = -1;
uint curFrame = 0;
// Go through and figure out where we should be
@@ -472,40 +527,40 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
for (uint32 i = 0; i < _indexEntries.size(); i++) {
const OldIndex &index = _indexEntries[i];
- if (index.id == ID_REC) {
- // Keep track of any records we find
- lastRecord = i;
- } else {
- if (getStreamIndex(index.id) != videoIndex)
- continue;
+ // We don't care about RECs
+ if (index.id == ID_REC)
+ continue;
- uint16 streamType = getStreamType(index.id);
+ // We're only looking at entries for this track
+ if (getStreamIndex(index.id) != videoIndex)
+ continue;
- if (streamType == kStreamTypePaletteChange) {
- // We need to handle any palette change we see since there's no
- // flag to tell if this is a "key" palette.
- // Decode the palette
- _fileStream->seek(_indexEntries[i].offset + 8);
- Common::SeekableReadStream *chunk = 0;
+ uint16 streamType = getStreamType(index.id);
- if (_indexEntries[i].size != 0)
- chunk = _fileStream->readStream(_indexEntries[i].size);
+ if (streamType == kStreamTypePaletteChange) {
+ // We need to handle any palette change we see since there's no
+ // flag to tell if this is a "key" palette.
+ // Decode the palette
+ _fileStream->seek(_indexEntries[i].offset + 8);
+ Common::SeekableReadStream *chunk = 0;
- videoTrack->loadPaletteFromChunk(chunk);
- } else {
- // Check to see if this is a keyframe
- // The first frame has to be a keyframe
- if ((_indexEntries[i].flags & AVIIF_INDEX) || curFrame == 0)
- lastKeyFrame = i;
-
- // Did we find the target frame?
- if (frame == curFrame) {
- frameIndex = i;
- break;
- }
+ if (_indexEntries[i].size != 0)
+ chunk = _fileStream->readStream(_indexEntries[i].size);
- curFrame++;
+ videoTrack->loadPaletteFromChunk(chunk);
+ } else {
+ // Check to see if this is a keyframe
+ // The first frame has to be a keyframe
+ if ((_indexEntries[i].flags & AVIIF_INDEX) || curFrame == 0)
+ lastKeyFrame = i;
+
+ // Did we find the target frame?
+ if (frame == curFrame) {
+ frameIndex = i;
+ break;
}
+
+ curFrame++;
}
}
@@ -513,57 +568,36 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
return false;
// Update all the audio tracks
- uint audioIndex = 0;
-
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++, audioIndex++) {
- if ((*it)->getTrackType() != Track::kTrackTypeAudio)
- continue;
-
- AVIAudioTrack *audioTrack = (AVIAudioTrack *)*it;
-
- // We need to find where the start of audio should be.
- // Which is exactly 'initialFrames' audio chunks back from where
- // our found frame is.
+ for (uint32 i = 0; i < _audioTracks.size(); i++) {
+ AVIAudioTrack *audioTrack = (AVIAudioTrack *)_audioTracks[i].track;
// Recreate the audio stream
audioTrack->resetStream();
- uint framesNeeded = _header.initialFrames;
- if (framesNeeded == 0)
- framesNeeded = 1;
+ // Set the chunk index for the track
+ audioTrack->setCurChunk(frame);
- uint startAudioChunk = 0;
- int startAudioSearch = (lastRecord < 0) ? (frameIndex - 1) : (lastRecord - 1);
+ uint32 chunksFound = 0;
+ for (uint32 j = 0; j < _indexEntries.size(); j++) {
+ const OldIndex &index = _indexEntries[j];
- for (int i = startAudioSearch; i >= 0; i--) {
- if (getStreamIndex(_indexEntries[i].id) != audioIndex)
+ // Continue ignoring RECs
+ if (index.id == ID_REC)
continue;
- assert(getStreamType(_indexEntries[i].id) == kStreamTypeAudio);
-
- framesNeeded--;
+ if (getStreamIndex(index.id) == _audioTracks[i].index) {
+ if (chunksFound == frame) {
+ _fileStream->seek(index.offset + 8);
+ Common::SeekableReadStream *audioChunk = _fileStream->readStream(index.size);
+ audioTrack->queueSound(audioChunk);
+ _audioTracks[i].chunkSearchOffset = (j == _indexEntries.size() - 1) ? _movieListEnd : _indexEntries[j + 1].offset;
+ break;
+ }
- if (framesNeeded == 0) {
- startAudioChunk = i;
- break;
+ chunksFound++;
}
}
- // Now go forward and queue them all
- for (int i = startAudioChunk; i <= startAudioSearch; i++) {
- if (_indexEntries[i].id == ID_REC)
- continue;
-
- if (getStreamIndex(_indexEntries[i].id) != audioIndex)
- continue;
-
- assert(getStreamType(_indexEntries[i].id) == kStreamTypeAudio);
-
- _fileStream->seek(_indexEntries[i].offset + 8);
- Common::SeekableReadStream *chunk = _fileStream->readStream(_indexEntries[i].size);
- audioTrack->queueSound(chunk);
- }
-
// Skip any audio to bring us to the right time
audioTrack->skipAudio(time, videoTrack->getFrameTime(frame));
}
@@ -592,15 +626,11 @@ bool AVIDecoder::seekIntern(const Audio::Timestamp &time) {
videoTrack->decodeFrame(chunk);
}
- // Seek to the right spot
- // To the beginning of the last record, or frame if that doesn't exist
- if (lastRecord >= 0)
- _fileStream->seek(_indexEntries[lastRecord].offset);
- else
- _fileStream->seek(_indexEntries[frameIndex].offset);
-
+ // Set the video track's frame
videoTrack->setCurFrame((int)frame - 1);
+ // Set the video track's search offset to the right spot
+ _videoTracks[0].chunkSearchOffset = _indexEntries[frameIndex].offset;
return true;
}
@@ -623,7 +653,7 @@ void AVIDecoder::readOldIndex(uint32 size) {
OldIndex firstEntry;
firstEntry.id = _fileStream->readUint32BE();
firstEntry.flags = _fileStream->readUint32LE();
- firstEntry.offset = _fileStream->readUint32LE();
+ firstEntry.offset = _fileStream->readUint32LE();
firstEntry.size = _fileStream->readUint32LE();
// Check if the offset is already absolute
@@ -654,45 +684,22 @@ void AVIDecoder::readOldIndex(uint32 size) {
}
}
-void AVIDecoder::forceVideoEnd() {
- // Horrible AVI video has a premature end
- // Force the frame to be the last frame
- debug(0, "Forcing end of AVI video");
-
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
- if ((*it)->getTrackType() == Track::kTrackTypeVideo)
- ((AVIVideoTrack *)*it)->forceTrackEnd();
-}
-
void AVIDecoder::checkTruemotion1() {
- AVIVideoTrack *track = 0;
-
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) {
- if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
- if (track) {
- // Multiple tracks; isn't going to be truemotion 1
- return;
- }
+ // If we got here from loadStream(), we know the track is valid
+ assert(!_videoTracks.empty());
- track = (AVIVideoTrack *)*it;
- }
- }
-
- // No track found?
- if (!track)
- return;
+ TrackStatus &status = _videoTracks[0];
+ AVIVideoTrack *track = (AVIVideoTrack *)status.track;
// Ignore non-truemotion tracks
if (!track->isTruemotion1())
return;
- // Search for a non-empty frame
- const Graphics::Surface *frame = 0;
- for (int i = 0; i < 10 && !frame; i++)
- frame = decodeNextFrame();
+ // Read the next video packet
+ handleNextPacket(status);
+ const Graphics::Surface *frame = track->decodeNextFrame();
if (!frame) {
- // Probably shouldn't happen
rewind();
return;
}
@@ -809,7 +816,7 @@ void AVIDecoder::AVIVideoTrack::forceTrackEnd() {
}
AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType)
- : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType) {
+ : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType), _curChunk(0) {
_audStream = createAudioStream();
}
@@ -836,12 +843,12 @@ void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
_audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
} else if (_wvInfo.tag == kWaveFormatDK3) {
_audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
- } else if (_wvInfo.tag == kWaveFormatMP3) {
- warning("AVI: MP3 audio stream is not supported");
}
} else {
delete stream;
}
+
+ _curChunk++;
}
void AVIDecoder::AVIAudioTrack::skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime) {
@@ -862,6 +869,7 @@ void AVIDecoder::AVIAudioTrack::skipAudio(const Audio::Timestamp &time, const Au
void AVIDecoder::AVIAudioTrack::resetStream() {
delete _audStream;
_audStream = createAudioStream();
+ _curChunk = 0;
}
bool AVIDecoder::AVIAudioTrack::rewind() {
@@ -874,12 +882,17 @@ Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const {
}
Audio::QueuingAudioStream *AVIDecoder::AVIAudioTrack::createAudioStream() {
- if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3 || _wvInfo.tag == kWaveFormatMP3)
+ if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3)
return Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
+ else if (_wvInfo.tag == kWaveFormatMP3)
+ warning("Unsupported AVI MP3 tracks");
else if (_wvInfo.tag != kWaveFormatNone) // No sound
warning("Unsupported AVI audio format %d", _wvInfo.tag);
return 0;
}
+AVIDecoder::TrackStatus::TrackStatus() : track(0), chunkSearchOffset(0) {
+}
+
} // End of namespace Video
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 4461e537c5..8941ff4e75 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -215,7 +215,9 @@ protected:
virtual void queueSound(Common::SeekableReadStream *stream);
Audio::Mixer::SoundType getSoundType() const { return _soundType; }
void skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime);
- void resetStream();
+ virtual void resetStream();
+ uint32 getCurChunk() const { return _curChunk; }
+ void setCurChunk(uint32 chunk) { _curChunk = chunk; }
bool isRewindable() const { return true; }
bool rewind();
@@ -238,6 +240,15 @@ protected:
Audio::Mixer::SoundType _soundType;
Audio::QueuingAudioStream *_audStream;
Audio::QueuingAudioStream *createAudioStream();
+ uint32 _curChunk;
+ };
+
+ struct TrackStatus {
+ TrackStatus();
+
+ Track *track;
+ uint32 index;
+ uint32 chunkSearchOffset;
};
AVIHeader _header;
@@ -260,9 +271,12 @@ protected:
void handleStreamHeader(uint32 size);
uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; }
byte getStreamIndex(uint32 tag) const;
- void forceVideoEnd();
void checkTruemotion1();
+ void handleNextPacket(TrackStatus& status);
+ bool shouldQueueAudio(TrackStatus& status);
+ Common::Array<TrackStatus> _videoTracks, _audioTracks;
+
public:
virtual AVIAudioTrack *createAudioTrack(AVIStreamHeader sHeader, PCMWaveFormat wvInfo);
};