aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--COPYRIGHT1
-rw-r--r--NEWS93
-rw-r--r--README7
-rw-r--r--audio/mods/maxtrax.cpp2
-rw-r--r--audio/softsynth/mt32.cpp18
-rw-r--r--backends/events/dinguxsdl/dinguxsdl-events.cpp5
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp15
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h16
-rw-r--r--backends/midi/windows.cpp3
-rw-r--r--backends/platform/android/gfx.cpp2
-rw-r--r--backends/platform/dc/vmsave.cpp29
-rw-r--r--backends/platform/dingux/README.GCW026
-rwxr-xr-xbackends/platform/dingux/build.gcw0.sh6
-rw-r--r--backends/platform/dingux/dingux.mk16
-rw-r--r--backends/platform/ios7/ios7_osys_main.cpp32
-rw-r--r--backends/platform/ios7/ios7_osys_main.h4
-rw-r--r--backends/platform/maemo/debian/changelog10
-rwxr-xr-xbackends/platform/maemo/debian/rules4
-rw-r--r--backends/platform/sdl/amigaos/amigaos.mk14
-rw-r--r--backends/platform/sdl/sdl-sys.h32
-rw-r--r--backends/platform/sdl/win32/win32-main.cpp7
-rw-r--r--backends/platform/tizen/system.cpp49
-rw-r--r--backends/platform/wince/wince-sdl.cpp4
-rw-r--r--backends/plugins/win32/win32-provider.cpp2
-rw-r--r--backends/saves/default/default-saves.cpp155
-rw-r--r--backends/saves/default/default-saves.h25
-rw-r--r--backends/taskbar/win32/win32-taskbar.cpp16
-rw-r--r--base/commandLine.cpp6
-rw-r--r--common/archive.cpp29
-rw-r--r--common/array.h14
-rw-r--r--common/dcl.cpp2
-rw-r--r--common/macresman.cpp111
-rw-r--r--common/macresman.h19
-rw-r--r--common/rational.h2
-rw-r--r--common/rect.h3
-rw-r--r--common/savefile.h45
-rw-r--r--common/taskbar.h2
-rwxr-xr-xconfigure90
-rw-r--r--devtools/create_project/create_project.cpp2
-rw-r--r--devtools/create_project/msbuild.cpp37
-rw-r--r--devtools/create_project/scripts/postbuild.cmd2
-rw-r--r--devtools/create_project/scripts/prebuild.cmd2
-rwxr-xr-xdevtools/create_wage/create_wage.sh119
-rwxr-xr-xdevtools/credits.pl14
-rw-r--r--dists/gcw0/default.gcw0.desktop4
-rw-r--r--dists/ios7/Info.plist5
-rw-r--r--dists/ios7/Info.plist.in5
-rw-r--r--dists/macosx/DS_Storebin12292 -> 15364 bytes
-rwxr-xr-xdists/openpandora/pnd_make.sh13
-rw-r--r--dists/samsungtv/README-SamsungTV2
-rw-r--r--dists/win32/ScummVM.iss2
-rw-r--r--doc/cz/PrectiMe1031
-rw-r--r--doc/de/Liesmich402
-rw-r--r--doc/de/Neues104
-rw-r--r--engines/access/access.cpp17
-rw-r--r--engines/access/asurface.cpp196
-rw-r--r--engines/access/asurface.h24
-rw-r--r--engines/access/detection.cpp3
-rw-r--r--engines/access/detection_tables.h2
-rw-r--r--engines/access/events.cpp5
-rw-r--r--engines/access/events.h2
-rw-r--r--engines/access/files.cpp21
-rw-r--r--engines/access/files.h6
-rw-r--r--engines/access/font.cpp5
-rw-r--r--engines/access/screen.cpp87
-rw-r--r--engines/access/screen.h30
-rw-r--r--engines/access/scripts.cpp5
-rw-r--r--engines/access/video.cpp2
-rw-r--r--engines/access/video/movie_decoder.cpp2
-rw-r--r--engines/advancedDetector.cpp79
-rw-r--r--engines/advancedDetector.h15
-rw-r--r--engines/agi/agi.cpp158
-rw-r--r--engines/agi/agi.h68
-rw-r--r--engines/agi/appleIIgs_timedelay_overwrite.h91
-rw-r--r--engines/agi/checks.cpp2
-rw-r--r--engines/agi/console.cpp55
-rw-r--r--engines/agi/console.h1
-rw-r--r--engines/agi/cycle.cpp81
-rw-r--r--engines/agi/detection.cpp34
-rw-r--r--engines/agi/detection_tables.h20
-rw-r--r--engines/agi/font.cpp209
-rw-r--r--engines/agi/font.h3
-rw-r--r--engines/agi/global.cpp159
-rw-r--r--engines/agi/graphics.cpp779
-rw-r--r--engines/agi/graphics.h105
-rw-r--r--engines/agi/inv.cpp2
-rw-r--r--engines/agi/keyboard.cpp36
-rw-r--r--engines/agi/menu.cpp48
-rw-r--r--engines/agi/menu.h4
-rw-r--r--engines/agi/motion.cpp54
-rw-r--r--engines/agi/op_cmd.cpp115
-rw-r--r--engines/agi/opcodes.cpp10
-rw-r--r--engines/agi/palette.h19
-rw-r--r--engines/agi/picture.cpp17
-rw-r--r--engines/agi/preagi.cpp4
-rw-r--r--engines/agi/preagi_mickey.cpp2
-rw-r--r--engines/agi/saveload.cpp94
-rw-r--r--engines/agi/sound_2gs.cpp2
-rw-r--r--engines/agi/sprite.cpp27
-rw-r--r--engines/agi/systemui.cpp157
-rw-r--r--engines/agi/systemui.h9
-rw-r--r--engines/agi/text.cpp170
-rw-r--r--engines/agi/text.h6
-rw-r--r--engines/agi/view.cpp46
-rw-r--r--engines/agi/view.h6
-rw-r--r--engines/agi/words.cpp2
-rw-r--r--engines/agi/words.h2
-rw-r--r--engines/agos/configure.engine2
-rw-r--r--engines/agos/detection.cpp9
-rw-r--r--engines/agos/sound.cpp2
-rw-r--r--engines/avalanche/POTFILES1
-rw-r--r--engines/avalanche/configure.engine2
-rw-r--r--engines/avalanche/detection.cpp5
-rw-r--r--engines/avalanche/parser.cpp5
-rw-r--r--engines/bbvs/bbvs.cpp33
-rw-r--r--engines/bbvs/detection.cpp9
-rw-r--r--engines/bbvs/dialogs.cpp2
-rw-r--r--engines/cge/POTFILES1
-rw-r--r--engines/cge/detection.cpp5
-rw-r--r--engines/cge/events.cpp5
-rw-r--r--engines/cge2/POTFILES1
-rw-r--r--engines/cge2/detection.cpp5
-rw-r--r--engines/cge2/events.cpp5
-rw-r--r--engines/cge2/vga13h.cpp4
-rw-r--r--engines/cine/anim.cpp2
-rw-r--r--engines/cine/detection.cpp11
-rw-r--r--engines/cine/saveload.cpp5
-rw-r--r--engines/cine/script_fw.cpp4
-rw-r--r--engines/composer/configure.engine2
-rw-r--r--engines/composer/detection.cpp8
-rw-r--r--engines/cruise/detection.cpp9
-rw-r--r--engines/draci/detection.cpp5
-rw-r--r--engines/drascula/detection.cpp7
-rw-r--r--engines/dreamweb/detection.cpp7
-rw-r--r--engines/engine.cpp2
-rw-r--r--engines/fullpipe/configure.engine2
-rw-r--r--engines/fullpipe/detection.cpp7
-rw-r--r--engines/game.cpp6
-rw-r--r--engines/game.h4
-rw-r--r--engines/gob/detection/detection.cpp10
-rw-r--r--engines/gob/script.cpp2
-rw-r--r--engines/gob/sound/adlib.cpp7
-rw-r--r--engines/groovie/configure.engine2
-rw-r--r--engines/groovie/detection.cpp4
-rw-r--r--engines/groovie/groovie.cpp2
-rw-r--r--engines/hopkins/configure.engine2
-rw-r--r--engines/hopkins/detection.cpp3
-rw-r--r--engines/hugo/POTFILES1
-rw-r--r--engines/hugo/detection.cpp5
-rw-r--r--engines/hugo/file.cpp5
-rw-r--r--engines/kyra/debugger.cpp4
-rw-r--r--engines/kyra/detection.cpp3
-rw-r--r--engines/kyra/detection_tables.h16
-rw-r--r--engines/kyra/gui_lol.cpp2
-rw-r--r--engines/kyra/gui_v1.cpp2
-rw-r--r--engines/kyra/sound.cpp18
-rw-r--r--engines/lab/configure.engine2
-rw-r--r--engines/lab/detection.cpp32
-rw-r--r--engines/lab/lab.cpp10
-rw-r--r--engines/lab/processroom.cpp6
-rw-r--r--engines/lab/savegame.cpp21
-rw-r--r--engines/lastexpress/configure.engine2
-rw-r--r--engines/lastexpress/detection.cpp4
-rw-r--r--engines/lure/detection.cpp7
-rw-r--r--engines/made/detection.cpp2
-rw-r--r--engines/mads/debugger.cpp2
-rw-r--r--engines/mads/detection.cpp3
-rw-r--r--engines/mads/dialogs.cpp50
-rw-r--r--engines/mads/dragonsphere/dragonsphere_scenes.cpp2
-rw-r--r--engines/mads/events.cpp6
-rw-r--r--engines/mads/font.cpp21
-rw-r--r--engines/mads/game.cpp5
-rw-r--r--engines/mads/mads.cpp13
-rw-r--r--engines/mads/mads.h2
-rw-r--r--engines/mads/menu_views.cpp30
-rw-r--r--engines/mads/msurface.cpp343
-rw-r--r--engines/mads/msurface.h144
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp32
-rw-r--r--engines/mads/nebular/game_nebular.cpp76
-rw-r--r--engines/mads/nebular/menu_nebular.cpp4
-rw-r--r--engines/mads/nebular/nebular_scenes.cpp4
-rw-r--r--engines/mads/nebular/nebular_scenes3.cpp18
-rw-r--r--engines/mads/nebular/nebular_scenes5.cpp2
-rw-r--r--engines/mads/phantom/phantom_scenes.cpp2
-rw-r--r--engines/mads/rails.cpp2
-rw-r--r--engines/mads/scene.cpp9
-rw-r--r--engines/mads/scene_data.cpp13
-rw-r--r--engines/mads/screen.cpp106
-rw-r--r--engines/mads/screen.h36
-rw-r--r--engines/mads/sequence.cpp4
-rw-r--r--engines/mads/sprites.cpp26
-rw-r--r--engines/mads/user_interface.cpp46
-rw-r--r--engines/mads/user_interface.h2
-rw-r--r--engines/metaengine.h3
-rw-r--r--engines/mohawk/configure.engine4
-rw-r--r--engines/mohawk/console.cpp42
-rw-r--r--engines/mohawk/console.h1
-rw-r--r--engines/mohawk/detection.cpp62
-rw-r--r--engines/mohawk/detection_tables.h41
-rw-r--r--engines/mohawk/dialogs.cpp92
-rw-r--r--engines/mohawk/dialogs.h18
-rw-r--r--engines/mohawk/myst.cpp581
-rw-r--r--engines/mohawk/myst.h124
-rw-r--r--engines/mohawk/myst_areas.cpp411
-rw-r--r--engines/mohawk/myst_areas.h162
-rw-r--r--engines/mohawk/myst_graphics.cpp24
-rw-r--r--engines/mohawk/myst_graphics.h4
-rw-r--r--engines/mohawk/myst_scripts.cpp129
-rw-r--r--engines/mohawk/myst_scripts.h28
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp59
-rw-r--r--engines/mohawk/myst_stacks/channelwood.h14
-rw-r--r--engines/mohawk/myst_stacks/credits.cpp5
-rw-r--r--engines/mohawk/myst_stacks/credits.h6
-rw-r--r--engines/mohawk/myst_stacks/demo.h4
-rw-r--r--engines/mohawk/myst_stacks/dni.h6
-rw-r--r--engines/mohawk/myst_stacks/intro.cpp2
-rw-r--r--engines/mohawk/myst_stacks/intro.h10
-rw-r--r--engines/mohawk/myst_stacks/makingof.h4
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp94
-rw-r--r--engines/mohawk/myst_stacks/mechanical.h26
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp191
-rw-r--r--engines/mohawk/myst_stacks/myst.h56
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp6
-rw-r--r--engines/mohawk/myst_stacks/preview.h8
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp98
-rw-r--r--engines/mohawk/myst_stacks/selenitic.h61
-rw-r--r--engines/mohawk/myst_stacks/slides.h4
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp38
-rw-r--r--engines/mohawk/myst_stacks/stoneship.h20
-rw-r--r--engines/mohawk/myst_state.cpp209
-rw-r--r--engines/mohawk/myst_state.h37
-rw-r--r--engines/mohawk/sound.cpp33
-rw-r--r--engines/mohawk/sound.h2
-rw-r--r--engines/mohawk/video.cpp135
-rw-r--r--engines/mohawk/video.h4
-rw-r--r--engines/mortevielle/configure.engine2
-rw-r--r--engines/mortevielle/detection.cpp2
-rw-r--r--engines/neverhood/configure.engine2
-rw-r--r--engines/neverhood/detection.cpp9
-rw-r--r--engines/parallaction/detection.cpp5
-rw-r--r--engines/parallaction/saveload.cpp4
-rw-r--r--engines/pegasus/configure.engine2
-rw-r--r--engines/pegasus/detection.cpp2
-rw-r--r--engines/prince/configure.engine2
-rw-r--r--engines/prince/detection.cpp2
-rw-r--r--engines/prince/detection.h2
-rw-r--r--engines/prince/graphics.cpp2
-rw-r--r--engines/queen/detection.cpp30
-rw-r--r--engines/saga/configure.engine4
-rw-r--r--engines/saga/detection.cpp9
-rw-r--r--engines/saga/interface.cpp9
-rw-r--r--engines/saga/music.cpp3
-rw-r--r--engines/saga/puzzle.cpp3
-rw-r--r--engines/saga/render.cpp3
-rw-r--r--engines/saga/saga.cpp8
-rw-r--r--engines/savestate.h9
-rw-r--r--engines/sci/configure.engine2
-rw-r--r--engines/sci/console.cpp112
-rw-r--r--engines/sci/console.h3
-rw-r--r--engines/sci/decompressor.cpp2
-rw-r--r--engines/sci/detection.cpp27
-rw-r--r--engines/sci/detection_tables.h124
-rw-r--r--engines/sci/engine/kernel.cpp2
-rw-r--r--engines/sci/engine/kernel.h53
-rw-r--r--engines/sci/engine/kernel_tables.h157
-rw-r--r--engines/sci/engine/kevent.cpp27
-rw-r--r--engines/sci/engine/kfile.cpp57
-rw-r--r--engines/sci/engine/kgraphics.cpp47
-rw-r--r--engines/sci/engine/kgraphics32.cpp931
-rw-r--r--engines/sci/engine/kmisc.cpp19
-rw-r--r--engines/sci/engine/kpathing.cpp12
-rw-r--r--engines/sci/engine/ksound.cpp42
-rw-r--r--engines/sci/engine/kstring.cpp20
-rw-r--r--engines/sci/engine/object.cpp9
-rw-r--r--engines/sci/engine/object.h39
-rw-r--r--engines/sci/engine/savegame.cpp111
-rw-r--r--engines/sci/engine/savegame.h3
-rw-r--r--engines/sci/engine/script_patches.cpp674
-rw-r--r--engines/sci/engine/script_patches.h21
-rw-r--r--engines/sci/engine/scriptdebug.cpp4
-rw-r--r--engines/sci/engine/seg_manager.cpp9
-rw-r--r--engines/sci/engine/segment.h2
-rw-r--r--engines/sci/engine/selector.cpp29
-rw-r--r--engines/sci/engine/selector.h18
-rw-r--r--engines/sci/engine/state.cpp1
-rw-r--r--engines/sci/engine/state.h2
-rw-r--r--engines/sci/engine/vm.cpp14
-rw-r--r--engines/sci/engine/vm_types.cpp38
-rw-r--r--engines/sci/engine/vm_types.h17
-rw-r--r--engines/sci/engine/workarounds.cpp11
-rw-r--r--engines/sci/engine/workarounds.h1
-rw-r--r--engines/sci/event.cpp56
-rw-r--r--engines/sci/event.h18
-rw-r--r--engines/sci/graphics/animate.cpp92
-rw-r--r--engines/sci/graphics/animate.h10
-rw-r--r--engines/sci/graphics/cache.cpp4
-rw-r--r--engines/sci/graphics/cache.h2
-rw-r--r--engines/sci/graphics/celobj32.cpp1050
-rw-r--r--engines/sci/graphics/celobj32.h581
-rw-r--r--engines/sci/graphics/compare.cpp74
-rw-r--r--engines/sci/graphics/compare.h3
-rw-r--r--engines/sci/graphics/controls16.cpp2
-rw-r--r--engines/sci/graphics/controls32.cpp426
-rw-r--r--engines/sci/graphics/controls32.h83
-rw-r--r--engines/sci/graphics/cursor.cpp12
-rw-r--r--engines/sci/graphics/cursor.h12
-rw-r--r--engines/sci/graphics/frameout.cpp2005
-rw-r--r--engines/sci/graphics/frameout.h504
-rw-r--r--engines/sci/graphics/helpers.h106
-rw-r--r--engines/sci/graphics/lists32.h192
-rw-r--r--engines/sci/graphics/palette.cpp90
-rw-r--r--engines/sci/graphics/palette.h21
-rw-r--r--engines/sci/graphics/palette32.cpp108
-rw-r--r--engines/sci/graphics/palette32.h392
-rw-r--r--engines/sci/graphics/picture.cpp6
-rw-r--r--engines/sci/graphics/picture.h3
-rw-r--r--engines/sci/graphics/plane32.cpp907
-rw-r--r--engines/sci/graphics/plane32.h485
-rw-r--r--engines/sci/graphics/remap.cpp386
-rw-r--r--engines/sci/graphics/remap.h154
-rw-r--r--engines/sci/graphics/screen.cpp278
-rw-r--r--engines/sci/graphics/screen.h315
-rw-r--r--engines/sci/graphics/screen_item32.cpp647
-rw-r--r--engines/sci/graphics/screen_item32.h288
-rw-r--r--engines/sci/graphics/text32.cpp822
-rw-r--r--engines/sci/graphics/text32.h457
-rw-r--r--engines/sci/graphics/view.cpp45
-rw-r--r--engines/sci/graphics/view.h2
-rw-r--r--engines/sci/module.mk4
-rw-r--r--engines/sci/parser/vocabulary.cpp14
-rw-r--r--engines/sci/parser/vocabulary.h2
-rw-r--r--engines/sci/resource.cpp75
-rw-r--r--engines/sci/resource.h9
-rw-r--r--engines/sci/resource_audio.cpp8
-rw-r--r--engines/sci/sci.cpp76
-rw-r--r--engines/sci/sci.h13
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp2
-rw-r--r--engines/sci/sound/soundcmd.cpp2
-rw-r--r--engines/sci/util.cpp9
-rw-r--r--engines/sci/util.h3
-rw-r--r--engines/scumm/actor.cpp2
-rw-r--r--engines/scumm/charset-fontdata.cpp31
-rw-r--r--engines/scumm/configure.engine2
-rw-r--r--engines/scumm/detection.cpp3
-rw-r--r--engines/scumm/he/sound_he.cpp4
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.cpp4
-rw-r--r--engines/scumm/players/player_ad.cpp30
-rw-r--r--engines/scumm/players/player_ad.h2
-rw-r--r--engines/scumm/players/player_v4a.cpp4
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/scumm.cpp8
-rw-r--r--engines/scumm/scumm_v4.h2
-rw-r--r--engines/scumm/sound.cpp2
-rw-r--r--engines/sherlock/POTFILES3
-rw-r--r--engines/sherlock/animation.cpp6
-rw-r--r--engines/sherlock/events.cpp8
-rw-r--r--engines/sherlock/fixed_text.cpp184
-rw-r--r--engines/sherlock/fixed_text.h47
-rw-r--r--engines/sherlock/fonts.cpp4
-rw-r--r--engines/sherlock/fonts.h2
-rw-r--r--engines/sherlock/image_file.h5
-rw-r--r--engines/sherlock/journal.cpp154
-rw-r--r--engines/sherlock/module.mk2
-rw-r--r--engines/sherlock/objects.cpp26
-rw-r--r--engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp286
-rw-r--r--engines/sherlock/scalpel/3do/scalpel_3do_screen.h76
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp107
-rw-r--r--engines/sherlock/scalpel/scalpel_darts.cpp36
-rw-r--r--engines/sherlock/scalpel/scalpel_fixed_text.cpp29
-rw-r--r--engines/sherlock/scalpel/scalpel_fixed_text.h8
-rw-r--r--engines/sherlock/scalpel/scalpel_inventory.cpp8
-rw-r--r--engines/sherlock/scalpel/scalpel_map.cpp43
-rw-r--r--engines/sherlock/scalpel/scalpel_scene.cpp44
-rw-r--r--engines/sherlock/scalpel/scalpel_screen.cpp251
-rw-r--r--engines/sherlock/scalpel/scalpel_screen.h38
-rw-r--r--engines/sherlock/scalpel/scalpel_user_interface.cpp165
-rw-r--r--engines/sherlock/scalpel/tsage/logo.cpp8
-rw-r--r--engines/sherlock/scene.cpp11
-rw-r--r--engines/sherlock/screen.cpp121
-rw-r--r--engines/sherlock/screen.h48
-rw-r--r--engines/sherlock/sherlock.h6
-rw-r--r--engines/sherlock/sound.cpp4
-rw-r--r--engines/sherlock/surface.cpp260
-rw-r--r--engines/sherlock/surface.h152
-rw-r--r--engines/sherlock/tattoo/tattoo_darts.cpp165
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.cpp105
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.h40
-rw-r--r--engines/sherlock/tattoo/tattoo_journal.cpp222
-rw-r--r--engines/sherlock/tattoo/tattoo_journal.h12
-rw-r--r--engines/sherlock/tattoo/tattoo_map.cpp30
-rw-r--r--engines/sherlock/tattoo/tattoo_people.cpp7
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.cpp22
-rw-r--r--engines/sherlock/tattoo/tattoo_screen.cpp37
-rw-r--r--engines/sherlock/tattoo/tattoo_screen.h44
-rw-r--r--engines/sherlock/tattoo/tattoo_talk.cpp5
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.cpp16
-rw-r--r--engines/sherlock/tattoo/widget_base.cpp40
-rw-r--r--engines/sherlock/tattoo/widget_credits.cpp17
-rw-r--r--engines/sherlock/tattoo/widget_files.cpp28
-rw-r--r--engines/sherlock/tattoo/widget_foolscap.cpp4
-rw-r--r--engines/sherlock/tattoo/widget_inventory.cpp22
-rw-r--r--engines/sherlock/tattoo/widget_options.cpp32
-rw-r--r--engines/sherlock/tattoo/widget_password.cpp6
-rw-r--r--engines/sherlock/tattoo/widget_quit.cpp20
-rw-r--r--engines/sherlock/tattoo/widget_talk.cpp4
-rw-r--r--engines/sherlock/tattoo/widget_text.cpp5
-rw-r--r--engines/sherlock/tattoo/widget_tooltip.cpp4
-rw-r--r--engines/sherlock/tattoo/widget_verbs.cpp6
-rw-r--r--engines/sky/detection.cpp7
-rw-r--r--engines/sword1/configure.engine2
-rw-r--r--engines/sword1/detection.cpp15
-rw-r--r--engines/sword1/objectman.cpp6
-rw-r--r--engines/sword1/objectman.h2
-rw-r--r--engines/sword1/router.cpp2
-rw-r--r--engines/sword2/configure.engine2
-rw-r--r--engines/sword2/router.cpp2
-rw-r--r--engines/sword2/sword2.cpp3
-rw-r--r--engines/sword25/POTFILES1
-rw-r--r--engines/sword25/configure.engine2
-rw-r--r--engines/sword25/detection.cpp17
-rw-r--r--engines/sword25/detection_tables.h29
-rw-r--r--engines/sword25/fmv/movieplayer.cpp2
-rw-r--r--engines/sword25/fmv/movieplayer.h2
-rw-r--r--engines/sword25/gfx/animationresource.cpp5
-rw-r--r--engines/sword25/gfx/fontresource.cpp5
-rw-r--r--engines/sword25/gfx/text.cpp3
-rw-r--r--engines/sword25/kernel/kernel_script.cpp1
-rw-r--r--engines/sword25/package/packagemanager.cpp45
-rw-r--r--engines/sword25/package/packagemanager.h3
-rw-r--r--engines/sword25/script/luacallback.cpp2
-rw-r--r--engines/sword25/script/luascript.cpp2
-rw-r--r--engines/sword25/sword25.cpp2
-rw-r--r--engines/sword25/util/lua/lbaselib.cpp2
-rw-r--r--engines/sword25/util/lua/ldo.cpp7
-rw-r--r--engines/sword25/util/lua/luaconf.h2
-rw-r--r--engines/teenagent/detection.cpp5
-rw-r--r--engines/testbed/detection.cpp2
-rw-r--r--engines/tinsel/detection.cpp13
-rw-r--r--engines/tinsel/graphics.cpp2
-rw-r--r--engines/tinsel/music.cpp20
-rw-r--r--engines/tinsel/tinsel.cpp2
-rw-r--r--engines/toltecs/configure.engine2
-rw-r--r--engines/toltecs/detection.cpp5
-rw-r--r--engines/tony/configure.engine2
-rw-r--r--engines/tony/detection.cpp3
-rw-r--r--engines/toon/POTFILES1
-rw-r--r--engines/toon/configure.engine2
-rw-r--r--engines/toon/detection.cpp5
-rw-r--r--engines/toon/toon.cpp5
-rw-r--r--engines/touche/configure.engine2
-rw-r--r--engines/touche/detection.cpp2
-rw-r--r--engines/tsage/blue_force/blueforce_dialogs.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_logic.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_scenes6.cpp4
-rw-r--r--engines/tsage/converse.cpp2
-rw-r--r--engines/tsage/core.cpp10
-rw-r--r--engines/tsage/detection.cpp7
-rw-r--r--engines/tsage/detection_tables.h4
-rw-r--r--engines/tsage/events.cpp4
-rw-r--r--engines/tsage/globals.cpp4
-rw-r--r--engines/tsage/globals.h3
-rw-r--r--engines/tsage/graphics.cpp292
-rw-r--r--engines/tsage/graphics.h30
-rw-r--r--engines/tsage/module.mk1
-rw-r--r--engines/tsage/ringworld/ringworld_dialogs.cpp6
-rw-r--r--engines/tsage/ringworld/ringworld_logic.cpp2
-rw-r--r--engines/tsage/ringworld/ringworld_scenes3.cpp6
-rw-r--r--engines/tsage/ringworld/ringworld_scenes5.cpp4
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp35
-rw-r--r--engines/tsage/ringworld2/ringworld2_outpost.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp6
-rw-r--r--engines/tsage/saveload.cpp4
-rw-r--r--engines/tsage/scenes.cpp6
-rw-r--r--engines/tsage/screen.cpp46
-rw-r--r--engines/tsage/screen.h59
-rw-r--r--engines/tsage/tsage.h6
-rw-r--r--engines/tsage/user_interface.cpp12
-rw-r--r--engines/tucker/detection.cpp4
-rw-r--r--engines/tucker/resource.cpp8
-rw-r--r--engines/tucker/sequences.cpp23
-rw-r--r--engines/tucker/tucker.cpp4
-rw-r--r--engines/tucker/tucker.h1
-rw-r--r--engines/voyeur/animation.cpp7
-rw-r--r--engines/voyeur/data.cpp16
-rw-r--r--engines/voyeur/debugger.cpp2
-rw-r--r--engines/voyeur/detection.cpp3
-rw-r--r--engines/voyeur/events.cpp58
-rw-r--r--engines/voyeur/files.cpp115
-rw-r--r--engines/voyeur/files.h6
-rw-r--r--engines/voyeur/files_threads.cpp74
-rw-r--r--engines/voyeur/module.mk2
-rw-r--r--engines/voyeur/screen.cpp (renamed from engines/voyeur/graphics.cpp)127
-rw-r--r--engines/voyeur/screen.h (renamed from engines/voyeur/graphics.h)22
-rw-r--r--engines/voyeur/voyeur.cpp165
-rw-r--r--engines/voyeur/voyeur.h4
-rw-r--r--engines/voyeur/voyeur_game.cpp306
-rw-r--r--engines/wage/combat.cpp916
-rw-r--r--engines/wage/configure.engine3
-rw-r--r--engines/wage/debugger.cpp97
-rw-r--r--engines/wage/debugger.h47
-rw-r--r--engines/wage/design.cpp599
-rw-r--r--engines/wage/design.h119
-rw-r--r--engines/wage/detection.cpp151
-rw-r--r--engines/wage/detection_tables.h121
-rw-r--r--engines/wage/dialog.cpp241
-rw-r--r--engines/wage/dialog.h101
-rw-r--r--engines/wage/entities.cpp514
-rw-r--r--engines/wage/entities.h336
-rw-r--r--engines/wage/gui-console.cpp430
-rw-r--r--engines/wage/gui.cpp675
-rw-r--r--engines/wage/gui.h189
-rw-r--r--engines/wage/menu.cpp571
-rw-r--r--engines/wage/menu.h139
-rw-r--r--engines/wage/module.mk29
-rw-r--r--engines/wage/randomhat.cpp83
-rw-r--r--engines/wage/randomhat.h77
-rw-r--r--engines/wage/script.cpp1175
-rw-r--r--engines/wage/script.h161
-rw-r--r--engines/wage/sound.cpp86
-rw-r--r--engines/wage/sound.h64
-rw-r--r--engines/wage/util.cpp125
-rw-r--r--engines/wage/wage.cpp515
-rw-r--r--engines/wage/wage.h239
-rw-r--r--engines/wage/world.cpp523
-rw-r--r--engines/wage/world.h138
-rw-r--r--engines/wintermute/ad/ad_actor.cpp4
-rw-r--r--engines/wintermute/base/base_engine.h2
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp12
-rw-r--r--engines/wintermute/base/base_persistence_manager.h4
-rw-r--r--engines/wintermute/base/base_sub_frame.cpp2
-rw-r--r--engines/wintermute/base/file/base_disk_file.cpp27
-rw-r--r--engines/wintermute/configure.engine2
-rw-r--r--engines/wintermute/detection.cpp10
-rw-r--r--engines/wintermute/detection_tables.h5
-rw-r--r--engines/wintermute/wintermute.cpp2
-rw-r--r--engines/zvision/configure.engine2
-rw-r--r--engines/zvision/detection.cpp26
-rw-r--r--graphics/VectorRendererSpec.cpp66
-rw-r--r--graphics/VectorRendererSpec.h4
-rw-r--r--graphics/font.cpp11
-rw-r--r--graphics/font.h3
-rw-r--r--graphics/managed_surface.cpp260
-rw-r--r--graphics/managed_surface.h376
-rw-r--r--graphics/module.mk2
-rw-r--r--graphics/primitives.cpp349
-rw-r--r--graphics/primitives.h11
-rw-r--r--graphics/screen.cpp129
-rw-r--r--graphics/screen.h118
-rw-r--r--graphics/thumbnail.cpp2
-rw-r--r--gui/credits.h3
-rw-r--r--gui/predictivedialog.cpp5
-rw-r--r--gui/predictivedialog.h1
-rw-r--r--gui/themes/translations.datbin498009 -> 562190 bytes
-rw-r--r--image/codecs/indeo3.cpp95
-rw-r--r--image/codecs/rpza.cpp1
-rw-r--r--po/be_BY.po596
-rw-r--r--po/ca_ES.po136
-rw-r--r--po/cs_CZ.po1591
-rw-r--r--po/da_DK.po (renamed from po/da_DA.po)352
-rw-r--r--po/de_DE.po141
-rw-r--r--po/es_ES.po344
-rw-r--r--po/eu.po564
-rw-r--r--po/fi_FI.po136
-rw-r--r--po/fr_FR.po147
-rw-r--r--po/gl_ES.po142
-rw-r--r--po/hu_HU.po142
-rw-r--r--po/it_IT.po139
-rw-r--r--po/nb_NO.po335
-rw-r--r--po/nl_NL.po145
-rw-r--r--po/nn_NO.po570
-rw-r--r--po/pl_PL.po362
-rw-r--r--po/pt_BR.po138
-rw-r--r--po/ru_RU.po190
-rw-r--r--po/scummvm.pot134
-rw-r--r--po/sv_SE.po (renamed from po/se_SE.po)356
-rw-r--r--po/uk_UA.po136
-rw-r--r--po/zh-Latn_CN.po3730
-rw-r--r--ports.mk10
-rw-r--r--test/common/array.h42
-rw-r--r--test/common/rational.h11
-rw-r--r--video/qt_decoder.cpp4
583 files changed, 37609 insertions, 11453 deletions
diff --git a/AUTHORS b/AUTHORS
index df8fb678b0..eff485cdc1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -285,6 +285,9 @@ ScummVM Team
Dreamcast:
Marcus Comstedt
+ GCW0:
+ Eugene Sandulenko
+
GPH Devices (GP2X, GP2XWiz & Caanoo):
John Willis
diff --git a/COPYRIGHT b/COPYRIGHT
index f2db1a5aed..a4807f936a 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -66,6 +66,7 @@ Edward Rudd
Eugene Sandulenko
Johannes Schickel
Keith Scroggins
+Tarek Soliman
Won Star
Ludvig Strigeus
Fedor Strizhniou
diff --git a/NEWS b/NEWS
index da67360550..84cf170bb2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,63 @@
For a more comprehensive changelog of the latest experimental code, see:
https://github.com/scummvm/scummvm/commits/
-1.8.0 (????-??-??)
+1.9.0 (XXXX-XX-XX)
+ AGI:
+ - Added support for Hercules rendering. Both green and amber modes are
+ supported.
+ - Added support for the Hercules high resolution font. The font is also
+ usable outside of Hercules rendering.
+ - Added optional "pause, when entering commands" feature, that was only
+ available in the original interpreter for Hercules rendering.
+
+1.8.1 (XXXX-XX-XX)
+ General:
+ - Removed TESTING flag from several supported games.
+ - Added Chinese Pinyin translation.
+
+ BBVS:
+ - Fixed game restart.
+
+ CinE:
+ - Fixed sound effect loading.
+
+ Gob:
+ - Fixed lock up for some games during sound initialization.
+
+ Lab:
+ - Fixed lock-up during ending sequence.
+ - Improved internal game controls.
+
+ SAGA:
+ - Fixed user interface colors in the French and German versions of I Have No
+ Mouth and I Must Scream.
+
+ SCUMM:
+ - Fixed detection of Maniac Mansion from Day of the Tentacle in the Windows
+ version of ScummVM.
+ - Fixed a sound effect not stopping in Loom EGA with AdLib.
+
+ Broken Sword 2.5:
+ - Added option to use English speech instead of German one when no speech is
+ available for the selected language.
+ - Fixed resource releasing on game exit.
+ - Fixed game restart after language change in-game.
+ - Fixed flickering in main Menu.
+
+ Windows port:
+ - Fixed bug in MIDI device listing affecting cases where MIDI devices were
+ not usable.
+
+1.8.0 (2016-03-04)
New Games:
- Added support for Rex Nebular and the Cosmic Gender Bender.
- Added support for Sfinx.
- Added support for Zork Nemesis: The Forbidden Lands.
- Added support for Zork: Grand Inquisitor.
- - Added support for The Lost Files of Sherlock Holmes: The Case of the Serrated Scalpel.
- - Added support for The Lost Files of Sherlock Holmes: The Case of the Rose Tattoo.
+ - Added support for The Lost Files of Sherlock Holmes: The Case of the
+ Serrated Scalpel.
+ - Added support for The Lost Files of Sherlock Holmes: The Case of the Rose
+ Tattoo.
- Added support for Beavis and Butthead in Virtual Stupidity.
- Added support for Amazon: Guardians of Eden.
- Added support for Broken Sword 2.5: The Return of the Templars.
@@ -16,13 +65,13 @@ For a more comprehensive changelog of the latest experimental code, see:
New Ports:
- Added Raspberry Pi port.
+ - Added GCW0 port.
General:
- Updated Munt MT-32 emulation code to version 1.5.0.
SDL:
- - Alt-x no longer quits ScummVM on platforms exhibiting this behavior
- before. A notable example is our Windows port.
+ - Alt-x no longer quits ScummVM. Use Cmd-q/Ctrl-q/Ctrl-z instead; see README.
- On POSIX systems we now follow the XDG Base Directory Specification for
placement of files for users. This effectively results in new locations
for our configuration file, our log file, and our default savegame path.
@@ -36,15 +85,17 @@ For a more comprehensive changelog of the latest experimental code, see:
AGI:
- It is now possible to disable mouse support (except for Amiga versions
and fanmade games, that require a mouse).
- - Fix incorrect volume attenuation in PCjr sound code (bug #6858).
+ - Fixed PCjr sound volumes.
- Major rewrite of graphics subsystem.
- - Support for Apple IIgs, Amiga + Atari ST transitions, fonts and mouse cursors.
- (Atari ST 8x8 system font is not included with ScummVM)
- - Added ability to make for example a PC version look like an Apple IIgs version.
- (includes palette, cursor, transition and even font). Just set corresponding render mode.
- - Support for simplified automatic saving/restoring (used by Mixed Up Mother Goose).
- - Removed forced 2 second delay on every room change, replaced with heuristic.
- - Now saving controllers (key bindings by scripts) when saving games (bug #5858).
+ - Support for Apple IIgs, Amiga + Atari ST transitions, fonts and mouse
+ cursors. The Atari ST 8x8 system font is not included with ScummVM.
+ - Added ability to make for example a PC version look like an Apple IIgs
+ version. This includes palette, cursor, transition and even font. Just
+ set corresponding render mode.
+ - Fixed Apple IIgs game versions running too fast.
+ - Added support for automatic saving/restoring used by Mixed Up Mother Goose.
+ - Removed forced two second delay on room changes; replaced with heuristic.
+ - Fixed certain key bindings breaking after saving/reloading.
AGOS:
- Fixed arpeggio effect used in music of Amiga version of Elvira 1.
@@ -56,11 +107,8 @@ For a more comprehensive changelog of the latest experimental code, see:
output and makes it closer to the original.
Broken Sword 1:
- - Fix speech endianness detection on big endian systems for the Macintosh
- version (bug #6720).
- - Fix crash when reloading a game from the Main Menu while in the bull's
- head scene (bug #6728). It may have been happening in other scenes as
- well.
+ - Fixed Macintosh version speech when running on big endian systems.
+ - Fixed loading from Main Menu in bull's head scene, and maybe other scenes.
CinE:
- Added support for music in CD version of Future Wars.
@@ -74,10 +122,12 @@ For a more comprehensive changelog of the latest experimental code, see:
SCI:
- Handling of music priority has been greatly improved.
- A lot of fixes for original game script bugs that also occurred when
- using the original interpreter.
- KQ6 (Dual Mode), LSL5, QfG1 (EGA), QfG1 (VGA), QfG2, QfG3, SQ1, SQ4 (CD)
+ using the original interpreter. This affects the following games:
+ KQ6 (Dual Mode), LSL5, PQ1, QfG1 (EGA), QfG1 (VGA), QfG2, QfG3, SQ1,
+ SQ4 (CD).
- Restoring from the ScummVM in-game menu should now work all the time.
- - Improve support for Japanese PC-9801 games.
+ - Improved support for Japanese PC-9801 games.
+ - Default to hi res version of KQ6, changeable using engine option.
SCUMM:
- Major improvements to Korean versions text rendering.
@@ -85,6 +135,7 @@ For a more comprehensive changelog of the latest experimental code, see:
- It is now possible to play Maniac Mansion from within Day of the
Tentacle, with a few caveats. See README for details.
- Alt-x can now be used to quit SCUMM games on all platforms.
+ - Improved lip sync animation in later HE games.
Tinsel:
- Improved AdLib music support in Discworld 1.
diff --git a/README b/README
index 996eca2a5c..3d181695c6 100644
--- a/README
+++ b/README
@@ -48,10 +48,10 @@ Table of Contents:
4.0) Supported Platforms
5.0) Running ScummVM
* 5.1 Command Line Options
- * 5.2 Language Options
+ * 5.2 Global Menu
* 5.3 Graphics Filters
- * 5.4 Global Menu
- * 5.5 Hotkeys
+ * 5.4 Hotkeys
+ * 5.5 Language Options
6.0) Saved Games
* 6.1 Autosaves
* 6.2 Converting saved games
@@ -1487,6 +1487,7 @@ other games.
Ctrl-F5 - Displays the Global Menu
Cmd-q - Quit (Mac OS X)
Ctrl-q - Quit (other unices including Linux)
+ Alt-F4 - Quit (Windows)
Ctrl-z - Quit (other platforms)
Ctrl-u - Mute all sounds
Ctrl-m - Toggle mouse capture
diff --git a/audio/mods/maxtrax.cpp b/audio/mods/maxtrax.cpp
index c18812ee54..f5754a5f96 100644
--- a/audio/mods/maxtrax.cpp
+++ b/audio/mods/maxtrax.cpp
@@ -54,7 +54,7 @@ void nullFunc(int) {}
// Function to calculate 2^x, where x is a fixedpoint number with 16 fraction bits
// using exp would be more accurate and needs less space if mathlibrary is already linked
-// but this function should be faster and doesnt use floats
+// but this function should be faster and doesn't use floats
#if 1
inline uint32 pow2Fixed(int32 val) {
static const uint16 tablePow2[] = {
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index 4420657854..d514e64fe9 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -140,10 +140,7 @@ MidiDriver_MT32::MidiDriver_MT32(Audio::Mixer *mixer) : MidiDriver_Emulated(mixe
}
_reportHandler = NULL;
_synth = NULL;
- // Unfortunately bugs in the emulator cause inaccurate tuning
- // at rates other than 32KHz, thus we produce data at 32KHz and
- // rely on Mixer to convert.
- _outputRate = 32000; //_mixer->getOutputRate();
+ _outputRate = 0;
_initializing = false;
// Initialized in open()
@@ -180,7 +177,6 @@ int MidiDriver_MT32::open() {
if (_isOpen)
return MERR_ALREADY_OPEN;
- MidiDriver_Emulated::open();
_reportHandler = new MT32Emu::ReportHandlerScummVM();
_synth = new MT32Emu::Synth(_reportHandler);
@@ -212,6 +208,18 @@ int MidiDriver_MT32::open() {
double gain = (double)ConfMan.getInt("midi_gain") / 100.0;
_synth->setOutputGain(1.0f * gain);
_synth->setReverbOutputGain(0.68f * gain);
+ // We let the synthesizer play MIDI messages immediately. Our MIDI
+ // handling is synchronous to sample generation. This makes delaying MIDI
+ // events result in odd sound output in some cases. For example, the
+ // shattering window in the Indiana Jones and the Fate of Atlantis intro
+ // will sound like a bell if we use any delay here.
+ // Bug #6242 "AUDIO: Built-In MT-32 MUNT Produces Wrong Sounds".
+ _synth->setMIDIDelayMode(MT32Emu::MIDIDelayMode_IMMEDIATE);
+
+ // We need to report the sample rate MUNT renders at as sample rate of our
+ // AudioStream.
+ _outputRate = _synth->getStereoOutputSampleRate();
+ MidiDriver_Emulated::open();
_initializing = false;
diff --git a/backends/events/dinguxsdl/dinguxsdl-events.cpp b/backends/events/dinguxsdl/dinguxsdl-events.cpp
index cc15f2666c..0492c569e1 100644
--- a/backends/events/dinguxsdl/dinguxsdl-events.cpp
+++ b/backends/events/dinguxsdl/dinguxsdl-events.cpp
@@ -175,7 +175,10 @@ bool DINGUXSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
return true;
} else if (ev.key.keysym.sym == BUT_SELECT) { // virtual keyboard
#ifdef ENABLE_VKEYBD
- event.type = Common::EVENT_VIRTUAL_KEYBOARD;
+ if (ev.type == SDL_KEYDOWN)
+ event.type = Common::EVENT_VIRTUAL_KEYBOARD;
+
+ return true;
#endif
} else if (ev.key.keysym.sym == BUT_START) { // F5, menu in some games
ev.key.keysym.sym = SDLK_F5;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 2b9d3aa100..21345515bc 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -127,7 +127,8 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#if SDL_VERSION_ATLEAST(2, 0, 0)
_renderer(nullptr), _screenTexture(nullptr),
_viewport(), _windowWidth(1), _windowHeight(1),
-#else
+#endif
+#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
_originalBitsPerPixel(0),
#endif
_screen(0), _tmpscreen(0),
@@ -801,8 +802,9 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
} else
#endif
{
- // Save the original bpp to be able to restore the video mode on unload
-#if !SDL_VERSION_ATLEAST(2, 0, 0)
+#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
+ // Save the original bpp to be able to restore the video mode on
+ // unload. See _originalBitsPerPixel documentation.
if (_originalBitsPerPixel == 0) {
const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
_originalBitsPerPixel = videoInfo->vfmt->BitsPerPixel;
@@ -947,9 +949,10 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
#endif
DestroyScalers();
-#if !SDL_VERSION_ATLEAST(2, 0, 0)
- // Reset video mode to original
- // This will ensure that any new graphic manager will use the initial BPP when listing available modes
+#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
+ // Reset video mode to original.
+ // This will ensure that any new graphic manager will use the initial BPP
+ // when listing available modes. See _originalBitsPerPixel documentation.
if (_originalBitsPerPixel != 0)
SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, _originalBitsPerPixel, _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_SWSURFACE) : SDL_SWSURFACE);
#endif
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index c4f7346525..25d6ff041c 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -251,8 +251,22 @@ protected:
};
VideoState _videoMode, _oldVideoMode;
- // Original BPP to restore the video mode on unload
+#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
+ /**
+ * Original BPP to restore the video mode on unload.
+ *
+ * This is required to make listing video modes for the OpenGL output work
+ * on Windows 8+. On these systems OpenGL modes are only available for
+ * 32bit formats. However, we setup a 16bit format and thus mode listings
+ * for OpenGL will return an empty list afterwards.
+ *
+ * In theory we might require this behavior on non-Win32 platforms too.
+ * However, SDL sometimes gives us invalid pixel formats for X11 outputs
+ * causing crashes when trying to setup the original pixel format.
+ * See bug #7038 "IRIX: X BadMatch when trying to start any 640x480 game".
+ */
uint8 _originalBitsPerPixel;
+#endif
/** Force full redraw on next updateScreen */
bool _forceFull;
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index e2b327ffa7..52a46200cb 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -185,6 +185,9 @@ MusicDevices WindowsMusicPlugin::getDevices() const {
deviceNames.push_back(tmp.szPname);
}
+ // Limit us to the number of actually retrieved devices.
+ numDevs = deviceNames.size();
+
// Check for non-unique device names. This may happen if someone has devices with identical
// names (e. g. more than one USB device of the exact same hardware type). It seems that this
// does happen in reality sometimes. We generate index numbers for these devices.
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index d7713f99d8..f847296892 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -469,7 +469,7 @@ void OSystem_Android::updateScreen() {
GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
}
-// TODO this doesnt work on those sucky drivers, do it differently
+// TODO this doesn't work on those sucky drivers, do it differently
// if (_show_overlay)
// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp
index 5f5cdff24f..75fc1ed0df 100644
--- a/backends/platform/dc/vmsave.cpp
+++ b/backends/platform/dc/vmsave.cpp
@@ -165,30 +165,7 @@ static bool tryDelete(const char *filename, int vm)
return true;
}
-static bool matches(const char *glob, const char *name)
-{
- while(*glob)
- if(*glob == '*') {
- while(*glob == '*')
- glob++;
- do {
- if((*name == *glob || *glob == '?') &&
- matches(glob, name))
- return true;
- } while(*name++);
- return false;
- } else if(!*name)
- return false;
- else if(*glob == '?' || *glob == *name) {
- glob++;
- name++;
- }
- else
- return false;
- return !*name;
-}
-
-static void tryList(const char *glob, int vm, Common::StringArray &list)
+static void tryList(const Common::String &glob, int vm, Common::StringArray &list)
{
struct vmsinfo info;
struct superblock super;
@@ -205,7 +182,7 @@ static void tryList(const char *glob, int vm, Common::StringArray &list)
char buf[16];
strncpy(buf, (char *)de.entry+4, 12);
buf[12] = 0;
- if (matches(glob, buf))
+ if (Common::matchString(buf, glob.c_str()))
list.push_back(buf);
}
}
@@ -425,7 +402,7 @@ Common::StringArray VMSaveManager::listSavefiles(const Common::String &pattern)
Common::StringArray list;
for (int i=0; i<24; i++)
- tryList(pattern.c_str(), i, list);
+ tryList(pattern, i, list);
return list;
}
diff --git a/backends/platform/dingux/README.GCW0 b/backends/platform/dingux/README.GCW0
new file mode 100644
index 0000000000..1875e5323a
--- /dev/null
+++ b/backends/platform/dingux/README.GCW0
@@ -0,0 +1,26 @@
+[ScummVM-GCW0 README]
+
+Controls
+========
+- Dpad/analog joy: move mouse cursor
+- A: left mouse button click
+- B: right mouse button click
+- X: '0' key
+- Y: '.' key (skips dialogue line in some engines)
+- Left Trigger: open global menu
+- Right Trigger: opens virtual keyboard
+- Select: ESC button, scene skip in some engines
+- Start: F5 key, game menu in some engines
+
+Installation from binaries
+==========================
+Copy over scummvm.opk file
+
+Building from binaries
+======================
+It's pretty simple if you are running Linux on an x86/amd64 machine:
+1. Download and install the GCW0 toolchain (http://www.gcw-zero.com/develop)
+2. Download ScummVM sources and uncompress them
+3. Run backends/platform/dingux/build.gcw0.sh script
+4. Copy the resulting file scummvm.opk to your device
+5. Enjoy
diff --git a/backends/platform/dingux/build.gcw0.sh b/backends/platform/dingux/build.gcw0.sh
new file mode 100755
index 0000000000..c1a4fa29c2
--- /dev/null
+++ b/backends/platform/dingux/build.gcw0.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+export PATH=/opt/gcw0-toolchain/usr/bin:$PATH
+
+# Disable high resolution engines since we have 320x240 hardware
+./configure --host=gcw0 --enable-plugins --default-dynamic --enable-release --disable-mt32emu --disable-hq-scalers && make -j6 gcw-opk && ls -l scummvm.opk
diff --git a/backends/platform/dingux/dingux.mk b/backends/platform/dingux/dingux.mk
index 1333e89ff8..56c26c3be1 100644
--- a/backends/platform/dingux/dingux.mk
+++ b/backends/platform/dingux/dingux.mk
@@ -55,6 +55,13 @@ endif
$(CP) $(srcdir)/dists/gcw0/default.gcw0.desktop $(gcw0_bundle)/
$(CP) $(srcdir)/dists/gcw0/scummvmrc $(gcw0_bundle)/
$(CP) $(srcdir)/dists/gcw0/scummvm.sh $(gcw0_bundle)/
+ $(CP) $(srcdir)/backends/platform/dingux/README.GCW0 $(gcw0_bundle)/README.man.txt
+ echo >> $(gcw0_bundle)/README.man.txt
+ echo '[General README]' >> $(gcw0_bundle)/README.man.txt
+ echo >> $(gcw0_bundle)/README.man.txt
+ cat README >> $(gcw0_bundle)/README.man.txt
+
+# $(CP) GeneralUser\ GS\ FluidSynth\ v1.44.sf2 $(gcw0_bundle)/
gcw0-opk-unstripped: $(gcw0_bundle)
$(CP) $(PLUGINS) $(gcw0_bundle)/plugins/
@@ -65,3 +72,12 @@ gcw-opk: $(gcw0_bundle)
$(STRIP) $(gcw0_bundle)/plugins/*
$(STRIP) $(gcw0_bundle)/scummvm
./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm
+
+GeneralUser_GS_1.44-FluidSynth.zip:
+ curl -s http://www.scummvm.org/frs/extras/SoundFont/GeneralUser_GS_1.44-FluidSynth.zip -o GeneralUser_GS_1.44-FluidSynth.zip
+
+GeneralUser\ GS\ FluidSynth\ v1.44.sf2: GeneralUser_GS_1.44-FluidSynth.zip
+ unzip -n GeneralUser_GS_1.44-FluidSynth.zip
+ mv "GeneralUser GS 1.44 FluidSynth/GeneralUser GS FluidSynth v1.44.sf2" .
+ mv "GeneralUser GS 1.44 FluidSynth/README.txt" README.soundfont
+ mv "GeneralUser GS 1.44 FluidSynth/LICENSE.txt" LICENSE.soundfont
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index c1280a2969..25d9cbed15 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -79,6 +79,33 @@ AQCallbackStruct OSystem_iOS7::s_AudioQueue;
SoundProc OSystem_iOS7::s_soundCallback = NULL;
void *OSystem_iOS7::s_soundParam = NULL;
+#ifdef IPHONE_SANDBOXED
+class SandboxedSaveFileManager : public DefaultSaveFileManager {
+ Common::String _sandboxRootPath;
+public:
+
+ SandboxedSaveFileManager(Common::String sandboxRootPath, Common::String defaultSavepath)
+ : DefaultSaveFileManager(defaultSavepath), _sandboxRootPath(sandboxRootPath) {
+ }
+
+ virtual bool removeSavefile(const Common::String &filename) override {
+ Common::String chrootedFile = getSavePath() + "/" + filename;
+ Common::String realFilePath = _sandboxRootPath + chrootedFile;
+
+ if (remove(realFilePath.c_str()) != 0) {
+ if (errno == EACCES)
+ setError(Common::kWritePermissionDenied, "Search or write permission denied: "+chrootedFile);
+
+ if (errno == ENOENT)
+ setError(Common::kPathDoesNotExist, "removeSavefile: '"+chrootedFile+"' does not exist or path is invalid");
+ return false;
+ } else {
+ return true;
+ }
+ }
+};
+#endif
+
OSystem_iOS7::OSystem_iOS7() :
_mixer(NULL), _lastMouseTap(0), _queuedEventTime(0),
_mouseNeedTextureUpdate(false), _secondaryTapped(false), _lastSecondaryTap(0),
@@ -89,7 +116,8 @@ OSystem_iOS7::OSystem_iOS7() :
_queuedInputEvent.type = Common::EVENT_INVALID;
_touchpadModeEnabled = !iOS7_isBigDevice();
#ifdef IPHONE_SANDBOXED
- _fsFactory = new ChRootFilesystemFactory(iOS7_getDocumentsDir());
+ _chrootBasePath = iOS7_getDocumentsDir();
+ _fsFactory = new ChRootFilesystemFactory(_chrootBasePath);
#else
_fsFactory = new POSIXFilesystemFactory();
#endif
@@ -124,7 +152,7 @@ int OSystem_iOS7::timerHandler(int t) {
void OSystem_iOS7::initBackend() {
#ifdef IPHONE_SANDBOXED
- _savefileManager = new DefaultSaveFileManager("/Savegames");
+ _savefileManager = new SandboxedSaveFileManager(_chrootBasePath, "/Savegames");
#else
_savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
#endif
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index cc2f1ccc06..174c160bd6 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -111,6 +111,10 @@ protected:
char *_lastErrorMessage;
+#ifdef IPHONE_SANDBOXED
+ Common::String _chrootBasePath;
+#endif
+
public:
OSystem_iOS7();
diff --git a/backends/platform/maemo/debian/changelog b/backends/platform/maemo/debian/changelog
index 8975871203..6b6d1aebd8 100644
--- a/backends/platform/maemo/debian/changelog
+++ b/backends/platform/maemo/debian/changelog
@@ -1,8 +1,14 @@
-scummvm (1.8.0~git) unstable; urgency=low
+scummvm (1.9.0~git) unstable; urgency=low
* Development snapshot
- -- Tarek Soliman <tsoliman@scummvm.org> Mon, 01 Feb 2016 22:37:44 -0600
+ -- Tarek Soliman <tsoliman@scummvm.org> Fri, 26 Feb 2016 21:11:20 -0600
+
+scummvm (1.8.0) unstable; urgency=low
+
+ * 1.8.0 release
+
+ -- Tarek Soliman <tsoliman@scummvm.org> Fri, 26 Feb 2016 21:11:20 -0600
scummvm (1.7.0) unstable; urgency=low
diff --git a/backends/platform/maemo/debian/rules b/backends/platform/maemo/debian/rules
index 70f52aac8f..0e72c8aa9a 100755
--- a/backends/platform/maemo/debian/rules
+++ b/backends/platform/maemo/debian/rules
@@ -6,8 +6,8 @@ build: scummvm
scummvm:
dh_testdir
- ./configure --host=maemo
- $(MAKE)
+ ./configure --host=maemo $(CONFIGURE_EXTRA_ARGS)
+ $(MAKE) $(MAKE_EXTRA_ARGS)
clean:
dh_testdir
diff --git a/backends/platform/sdl/amigaos/amigaos.mk b/backends/platform/sdl/amigaos/amigaos.mk
index 0c3c467965..15a2e9f93f 100644
--- a/backends/platform/sdl/amigaos/amigaos.mk
+++ b/backends/platform/sdl/amigaos/amigaos.mk
@@ -11,8 +11,14 @@ ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) $(AMIGAOSPATH)/extras/
endif
cat ${srcdir}/README | sed -f ${srcdir}/dists/amiga/convertRM.sed > README.conv
- rx dists/amiga/RM2AG.rx README.conv
- cp ${srcdir}/README.guide $(AMIGAOSPATH)
- rm ${srcdir}/README.conv
- rm ${srcdir}/README.guide
+# AmigaOS's shell is not happy with indented comments, thus don't do it.
+# AREXX seems to have problems when ${srcdir} is '.'. It will break with a
+# "Program not found" error. Therefore we copy the script to the cwd and
+# remove it again, once it has finished.
+ cp ${srcdir}/dists/amiga/RM2AG.rx .
+ rx RM2AG.rx README.conv
+ cp README.guide $(AMIGAOSPATH)
+ rm RM2AG.rx
+ rm README.conv
+ rm README.guide
cp $(DIST_FILES_DOCS) $(AMIGAOSPATH)
diff --git a/backends/platform/sdl/sdl-sys.h b/backends/platform/sdl/sdl-sys.h
index 67ad84efd3..551605a4b4 100644
--- a/backends/platform/sdl/sdl-sys.h
+++ b/backends/platform/sdl/sdl-sys.h
@@ -52,6 +52,21 @@ typedef struct { int FAKE; } FAKE_FILE;
#define strncasecmp FAKE_strncasecmp
#endif
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
+#undef exit
+#define exit FAKE_exit
+#endif
+
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
+#undef abort
+#define abort FAKE_abort
+#endif
+
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
+#undef system
+#define system FAKE_system
+#endif
+
// HACK: SDL might include windows.h which defines its own ARRAYSIZE.
// However, we want to use the version from common/util.h. Thus, we make sure
// that we actually have this definition after including the SDL headers.
@@ -112,7 +127,7 @@ typedef struct { int FAKE; } FAKE_FILE;
#endif
// In a moment of brilliance Xlib.h included by SDL_syswm.h #defines the
-// following names. In a moment of mental breakdown, which occured upon
+// following names. In a moment of mental breakdown, which occurred upon
// gazing at Xlib.h, LordHoto decided to undefine them to prevent havoc.
#ifdef Status
#undef Status
@@ -146,6 +161,21 @@ typedef struct { int FAKE; } FAKE_FILE;
#define strncasecmp FORBIDDEN_SYMBOL_REPLACEMENT
#endif
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
+#undef exit
+#define exit(a) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
+#undef abort
+#define abort() FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
+#undef system
+#define system(a) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
// SDL 2 has major API changes. We redefine constants which got renamed to
// ease the transition. This is sometimes dangerous because the values changed
// too!
diff --git a/backends/platform/sdl/win32/win32-main.cpp b/backends/platform/sdl/win32/win32-main.cpp
index c6339f0c8c..4864347d81 100644
--- a/backends/platform/sdl/win32/win32-main.cpp
+++ b/backends/platform/sdl/win32/win32-main.cpp
@@ -44,7 +44,12 @@ int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpC
SDL_SetModuleHandle(GetModuleHandle(NULL));
#endif
// HACK: __argc, __argv are broken and return zero when using mingwrt 4.0+ on MinGW
-#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
+// HACK: MinGW-w64 based toolchains neither feature _argc nor _argv. The 32 bit
+// incarnation only defines __MINGW32__. This leads to build breakage due to
+// missing declarations. Luckily MinGW-w64 based toolchains define
+// __MINGW64_VERSION_foo macros inside _mingw.h, which is included from all
+// system headers. Thus we abuse that to detect them.
+#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
return main(_argc, _argv);
#else
return main(__argc, __argv);
diff --git a/backends/platform/tizen/system.cpp b/backends/platform/tizen/system.cpp
index a235456670..1820a28791 100644
--- a/backends/platform/tizen/system.cpp
+++ b/backends/platform/tizen/system.cpp
@@ -81,36 +81,41 @@ struct TizenSaveFileManager : public DefaultSaveFileManager {
};
bool TizenSaveFileManager::removeSavefile(const Common::String &filename) {
- Common::String savePathName = getSavePath();
+ // Assure the savefile name cache is up-to-date.
+ assureCached(getSavePath());
+ if (getError().getCode() != Common::kNoError)
+ return false;
- checkPath(Common::FSNode(savePathName));
- if (getError().getCode() != Common::kNoError) {
+ // Obtain node if exists.
+ SaveFileCache::const_iterator file = _saveFileCache.find(filename);
+ if (file == _saveFileCache.end()) {
return false;
- }
+ } else {
+ const Common::FSNode fileNode = file->_value;
+ // Remove from cache, this invalidates the 'file' iterator.
+ _saveFileCache.erase(file);
+ file = _saveFileCache.end();
- // recreate FSNode since checkPath may have changed/created the directory
- Common::FSNode savePath(savePathName);
- Common::FSNode file = savePath.getChild(filename);
+ String unicodeFileName;
+ StringUtil::Utf8ToString(fileNode.getPath().c_str(), unicodeFileName);
- String unicodeFileName;
- StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName);
+ switch (Tizen::Io::File::Remove(unicodeFileName)) {
+ case E_SUCCESS:
+ return true;
- switch (Tizen::Io::File::Remove(unicodeFileName)) {
- case E_SUCCESS:
- return true;
+ case E_ILLEGAL_ACCESS:
+ setError(Common::kWritePermissionDenied, "Search or write permission denied: " +
+ file.getName());
+ break;
- case E_ILLEGAL_ACCESS:
- setError(Common::kWritePermissionDenied, "Search or write permission denied: " +
- file.getName());
- break;
+ default:
+ setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() +
+ "' does not exist or path is invalid");
+ break;
+ }
- default:
- setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() +
- "' does not exist or path is invalid");
- break;
+ return false;
}
-
- return false;
}
//
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index c1b0c7f692..02853b548e 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -645,7 +645,7 @@ Common::String OSystem_WINCE3::getSystemLanguage() const {
const char *posixMappingTable[][3] = {
{"CAT", "ESP", "ca_ES"},
{"CSY", "CZE", "cs_CZ"},
- {"DAN", "DNK", "da_DA"},
+ {"DAN", "DNK", "da_DK"},
{"DEU", "DEU", "de_DE"},
{"ESN", "ESP", "es_ES"},
{"ESP", "ESP", "es_ES"},
@@ -657,7 +657,7 @@ Common::String OSystem_WINCE3::getSystemLanguage() const {
{"PLK", "POL", "pl_PL"},
{"PTB", "BRA", "pt_BR"},
{"RUS", "RUS", "ru_RU"},
- {"SVE", "SWE", "se_SE"},
+ {"SVE", "SWE", "sv_SE"},
{"UKR", "UKR", "uk_UA"},
{NULL, NULL, NULL}
};
diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp
index 5f4d405da4..ae8a5f0472 100644
--- a/backends/plugins/win32/win32-provider.cpp
+++ b/backends/plugins/win32/win32-provider.cpp
@@ -77,7 +77,7 @@ public:
debug("Failed loading plugin '%s' (error code %d)", _filename.c_str(), (int32) GetLastError());
return false;
} else {
- debug(1, "Success loading plugin '%s', handle %08X", _filename.c_str(), (uint32) _dlHandle);
+ debug(1, "Success loading plugin '%s', handle %p", _filename.c_str(), _dlHandle);
}
return DynamicPlugin::loadPlugin();
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 4f7013724a..daec36ae72 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -60,22 +60,15 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
}
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
- Common::String savePathName = getSavePath();
- checkPath(Common::FSNode(savePathName));
+ // Assure the savefile name cache is up-to-date.
+ assureCached(getSavePath());
if (getError().getCode() != Common::kNoError)
return Common::StringArray();
- // recreate FSNode since checkPath may have changed/created the directory
- Common::FSNode savePath(savePathName);
-
- Common::FSDirectory dir(savePath);
- Common::ArchiveMemberList savefiles;
Common::StringArray results;
- Common::String search(pattern);
-
- if (dir.listMatchingMembers(savefiles, search) > 0) {
- for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
- results.push_back((*file)->getName());
+ for (SaveFileCache::const_iterator file = _saveFileCache.begin(), end = _saveFileCache.end(); file != end; ++file) {
+ if (file->_key.matchString(pattern, true)) {
+ results.push_back(file->_key);
}
}
@@ -83,68 +76,81 @@ Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &
}
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) {
- // Ensure that the savepath is valid. If not, generate an appropriate error.
- Common::String savePathName = getSavePath();
- checkPath(Common::FSNode(savePathName));
+ // Assure the savefile name cache is up-to-date.
+ assureCached(getSavePath());
if (getError().getCode() != Common::kNoError)
- return 0;
-
- // recreate FSNode since checkPath may have changed/created the directory
- Common::FSNode savePath(savePathName);
+ return nullptr;
- Common::FSNode file = savePath.getChild(filename);
- if (!file.exists())
- return 0;
-
- // Open the file for reading
- Common::SeekableReadStream *sf = file.createReadStream();
-
- return Common::wrapCompressedReadStream(sf);
+ SaveFileCache::const_iterator file = _saveFileCache.find(filename);
+ if (file == _saveFileCache.end()) {
+ return nullptr;
+ } else {
+ // Open the file for loading.
+ Common::SeekableReadStream *sf = file->_value.createReadStream();
+ return Common::wrapCompressedReadStream(sf);
+ }
}
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename, bool compress) {
- // Ensure that the savepath is valid. If not, generate an appropriate error.
- Common::String savePathName = getSavePath();
- checkPath(Common::FSNode(savePathName));
+ // Assure the savefile name cache is up-to-date.
+ const Common::String savePathName = getSavePath();
+ assureCached(savePathName);
if (getError().getCode() != Common::kNoError)
- return 0;
+ return nullptr;
- // recreate FSNode since checkPath may have changed/created the directory
- Common::FSNode savePath(savePathName);
+ // Obtain node.
+ SaveFileCache::const_iterator file = _saveFileCache.find(filename);
+ Common::FSNode fileNode;
- Common::FSNode file = savePath.getChild(filename);
+ // If the file did not exist before, we add it to the cache.
+ if (file == _saveFileCache.end()) {
+ const Common::FSNode savePath(savePathName);
+ fileNode = savePath.getChild(filename);
+ } else {
+ fileNode = file->_value;
+ }
- // Open the file for saving
- Common::WriteStream *sf = file.createWriteStream();
+ // Open the file for saving.
+ Common::WriteStream *const sf = fileNode.createWriteStream();
+ Common::OutSaveFile *const result = compress ? Common::wrapCompressedWriteStream(sf) : sf;
- return compress ? Common::wrapCompressedWriteStream(sf) : sf;
+ // Add file to cache now that it exists.
+ _saveFileCache[filename] = Common::FSNode(fileNode.getPath());
+
+ return result;
}
bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
- Common::String savePathName = getSavePath();
- checkPath(Common::FSNode(savePathName));
+ // Assure the savefile name cache is up-to-date.
+ assureCached(getSavePath());
if (getError().getCode() != Common::kNoError)
return false;
- // recreate FSNode since checkPath may have changed/created the directory
- Common::FSNode savePath(savePathName);
-
- Common::FSNode file = savePath.getChild(filename);
-
- // FIXME: remove does not exist on all systems. If your port fails to
- // compile because of this, please let us know (scummvm-devel or Fingolfin).
- // There is a nicely portable workaround, too: Make this method overloadable.
- if (remove(file.getPath().c_str()) != 0) {
+ // Obtain node if exists.
+ SaveFileCache::const_iterator file = _saveFileCache.find(filename);
+ if (file == _saveFileCache.end()) {
+ return false;
+ } else {
+ const Common::FSNode fileNode = file->_value;
+ // Remove from cache, this invalidates the 'file' iterator.
+ _saveFileCache.erase(file);
+ file = _saveFileCache.end();
+
+ // FIXME: remove does not exist on all systems. If your port fails to
+ // compile because of this, please let us know (scummvm-devel).
+ // There is a nicely portable workaround, too: Make this method overloadable.
+ if (remove(fileNode.getPath().c_str()) != 0) {
#ifndef _WIN32_WCE
- if (errno == EACCES)
- setError(Common::kWritePermissionDenied, "Search or write permission denied: "+file.getName());
+ if (errno == EACCES)
+ setError(Common::kWritePermissionDenied, "Search or write permission denied: "+fileNode.getName());
- if (errno == ENOENT)
- setError(Common::kPathDoesNotExist, "removeSavefile: '"+file.getName()+"' does not exist or path is invalid");
+ if (errno == ENOENT)
+ setError(Common::kPathDoesNotExist, "removeSavefile: '"+fileNode.getName()+"' does not exist or path is invalid");
#endif
- return false;
- } else {
- return true;
+ return false;
+ } else {
+ return true;
+ }
}
}
@@ -171,4 +177,43 @@ Common::String DefaultSaveFileManager::getSavePath() const {
return dir;
}
+void DefaultSaveFileManager::assureCached(const Common::String &savePathName) {
+ // Check that path exists and is usable.
+ checkPath(Common::FSNode(savePathName));
+
+ if (_cachedDirectory == savePathName) {
+ return;
+ }
+
+ _saveFileCache.clear();
+ _cachedDirectory.clear();
+
+ if (getError().getCode() != Common::kNoError) {
+ warning("DefaultSaveFileManager::assureCached: Can not cache path '%s': '%s'", savePathName.c_str(), getErrorDesc().c_str());
+ return;
+ }
+
+ // FSNode can cache its members, thus create it after checkPath to reflect
+ // actual file system state.
+ const Common::FSNode savePath(savePathName);
+
+ Common::FSList children;
+ if (!savePath.getChildren(children, Common::FSNode::kListFilesOnly)) {
+ return;
+ }
+
+ // Build the savefile name cache.
+ for (Common::FSList::const_iterator file = children.begin(), end = children.end(); file != end; ++file) {
+ if (_saveFileCache.contains(file->getName())) {
+ warning("DefaultSaveFileManager::assureCached: Name clash when building cache, ignoring file '%s'", file->getName().c_str());
+ } else {
+ _saveFileCache[file->getName()] = *file;
+ }
+ }
+
+ // Only now store that we cached 'savePathName' to indicate we successfully
+ // cached the directory.
+ _cachedDirectory = savePathName;
+}
+
#endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h
index 81f45f96b8..bf4ca0229d 100644
--- a/backends/saves/default/default-saves.h
+++ b/backends/saves/default/default-saves.h
@@ -27,6 +27,7 @@
#include "common/savefile.h"
#include "common/str.h"
#include "common/fs.h"
+#include "common/hashmap.h"
/**
* Provides a default savefile manager implementation for common platforms.
@@ -54,6 +55,30 @@ protected:
* Sets the internal error and error message accordingly.
*/
virtual void checkPath(const Common::FSNode &dir);
+
+ /**
+ * Assure that the given save path is cached.
+ *
+ * @param savePathName String representation of save path to cache.
+ */
+ void assureCached(const Common::String &savePathName);
+
+ typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SaveFileCache;
+
+ /**
+ * Cache of all the save files in the currently cached directory.
+ *
+ * Modify with caution because we only re-cache when the save path changed!
+ * This needs to be updated inside at least openForSaving and
+ * removeSavefile.
+ */
+ SaveFileCache _saveFileCache;
+
+private:
+ /**
+ * The currently cached directory.
+ */
+ Common::String _cachedDirectory;
};
#endif
diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp
index 0192b1dc03..f3339fb917 100644
--- a/backends/taskbar/win32/win32-taskbar.cpp
+++ b/backends/taskbar/win32/win32-taskbar.cpp
@@ -28,8 +28,22 @@
#if defined(WIN32) && defined(USE_TASKBAR)
+// HACK: To get __MINGW64_VERSION_foo defines we need to manually include
+// _mingw.h in this file because we do not include any system headers at this
+// point on purpose. The defines are required to detect whether this is a
+// classic MinGW toolchain or a MinGW-w64 based one.
+#if defined(__MINGW32__)
+#include <_mingw.h>
+#endif
+
// Needed for taskbar functions
-#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
+// HACK: MinGW-w64 based toolchains include the symbols we require in their
+// headers. The 32 bit incarnation only defines __MINGW32__. This leads to
+// build breakage due to clashes with our compat header. Luckily MinGW-w64
+// based toolchains define __MINGW64_VERSION_foo macros inside _mingw.h,
+// which is included from all system headers. Thus we abuse that to detect
+// them.
+#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
#include "backends/taskbar/win32/mingw-compat.h"
#else
// We use functionality introduced with Win7 in this file.
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 19702ea36d..105d810460 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -373,6 +373,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
// We defer checking whether this is a valid target to a later point.
return s;
} else {
+ // On MacOS X prior to 10.9 the OS is sometimes adding a -psn_X_XXXXXX argument (where X are digits)
+ // to pass the process serial number. We need to ignore it to avoid an error.
+#ifdef MACOSX
+ if (strncmp(s, "-psn_", 5) == 0)
+ continue;
+#endif
bool isLongCmd = (s[0] == '-' && s[1] == '-');
diff --git a/common/archive.cpp b/common/archive.cpp
index 36d420561f..5a339900b6 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -48,7 +48,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)
int matches = 0;
ArchiveMemberList::const_iterator it = allNames.begin();
- for ( ; it != allNames.end(); ++it) {
+ for (; it != allNames.end(); ++it) {
// TODO: We match case-insenstivie for now, our API does not define whether that's ok or not though...
// For our use case case-insensitive is probably what we want to have though.
if ((*it)->getName().matchString(pattern, true, true)) {
@@ -64,7 +64,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)
SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
ArchiveNodeList::iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
if (it->_name == name)
break;
}
@@ -73,7 +73,7 @@ SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
SearchSet::ArchiveNodeList::const_iterator SearchSet::find(const String &name) const {
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
if (it->_name == name)
break;
}
@@ -81,13 +81,13 @@ SearchSet::ArchiveNodeList::const_iterator SearchSet::find(const String &name) c
}
/*
- Keep the nodes sorted according to descending priorities.
- In case two or node nodes have the same priority, insertion
- order prevails.
+ Keep the nodes sorted according to descending priorities.
+ In case two or node nodes have the same priority, insertion
+ order prevails.
*/
void SearchSet::insert(const Node &node) {
ArchiveNodeList::iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
if (it->_priority < node._priority)
break;
}
@@ -131,8 +131,7 @@ void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPa
++sep;
if (sep != origPattern.end())
nextPattern = String(sep, origPattern.end());
- }
- else {
+ } else {
pattern = origPattern;
}
@@ -211,7 +210,7 @@ bool SearchSet::hasFile(const String &name) const {
return false;
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
if (it->_arc->hasFile(name))
return true;
}
@@ -223,7 +222,7 @@ int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &patter
int matches = 0;
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it)
+ for (; it != _list.end(); ++it)
matches += it->_arc->listMatchingMembers(list, pattern);
return matches;
@@ -233,7 +232,7 @@ int SearchSet::listMembers(ArchiveMemberList &list) const {
int matches = 0;
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it)
+ for (; it != _list.end(); ++it)
matches += it->_arc->listMembers(list);
return matches;
@@ -244,7 +243,7 @@ const ArchiveMemberPtr SearchSet::getMember(const String &name) const {
return ArchiveMemberPtr();
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
if (it->_arc->hasFile(name))
return it->_arc->getMember(name);
}
@@ -257,7 +256,7 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
return 0;
ArchiveNodeList::const_iterator it = _list.begin();
- for ( ; it != _list.end(); ++it) {
+ for (; it != _list.end(); ++it) {
SeekableReadStream *stream = it->_arc->createReadStreamForMember(name);
if (stream)
return stream;
@@ -268,7 +267,7 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
SearchManager::SearchManager() {
- clear(); // Force a reset
+ clear(); // Force a reset
}
void SearchManager::clear() {
diff --git a/common/array.h b/common/array.h
index f240a9c2f5..db1a62ba34 100644
--- a/common/array.h
+++ b/common/array.h
@@ -141,6 +141,12 @@ public:
insert_aux(_storage + idx, array.begin(), array.end());
}
+ /**
+ * Inserts element before pos.
+ */
+ void insert(iterator pos, const T &element) {
+ insert_aux(pos, &element, &element + 1);
+ }
T remove_at(size_type idx) {
assert(idx < _size);
@@ -187,6 +193,14 @@ public:
_capacity = 0;
}
+ iterator erase(iterator pos) {
+ copy(pos + 1, _storage + _size, pos);
+ _size--;
+ // We also need to destroy the last object properly here.
+ _storage[_size].~T();
+ return pos;
+ }
+
bool empty() const {
return (_size == 0);
}
diff --git a/common/dcl.cpp b/common/dcl.cpp
index 66dfb76b2a..75a533aa9d 100644
--- a/common/dcl.cpp
+++ b/common/dcl.cpp
@@ -470,7 +470,7 @@ bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpack
// Read source into memory
src->read(sourceBufferPtr, packedSize);
- Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::NO);
+ Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::YES);
Common::MemoryWriteStream *targetStream = new MemoryWriteStream(dest, unpackedSize);
success = dcl.unpack(sourceStream, targetStream, unpackedSize, true);
diff --git a/common/macresman.cpp b/common/macresman.cpp
index d83bde8fd8..adca1ea10b 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -29,6 +29,7 @@
#include "common/md5.h"
#include "common/substream.h"
#include "common/textconsole.h"
+#include "common/archive.h"
#ifdef MACOSX
#include "common/config-manager.h"
@@ -261,6 +262,76 @@ bool MacResManager::exists(const String &fileName) {
return false;
}
+void MacResManager::listFiles(StringArray &files, const String &pattern) {
+ // Base names discovered so far.
+ typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet;
+ BaseNameSet baseNames;
+
+ // List files itself.
+ ArchiveMemberList memberList;
+ SearchMan.listMatchingMembers(memberList, pattern);
+ SearchMan.listMatchingMembers(memberList, pattern + ".rsrc");
+ SearchMan.listMatchingMembers(memberList, pattern + ".bin");
+ SearchMan.listMatchingMembers(memberList, constructAppleDoubleName(pattern));
+
+ for (ArchiveMemberList::const_iterator i = memberList.begin(), end = memberList.end(); i != end; ++i) {
+ String filename = (*i)->getName();
+
+ // For raw resource forks and MacBinary files we strip the extension
+ // here to obtain a valid base name.
+ int lastDotPos = filename.size() - 1;
+ for (; lastDotPos >= 0; --lastDotPos) {
+ if (filename[lastDotPos] == '.') {
+ break;
+ }
+ }
+
+ if (lastDotPos != -1) {
+ const char *extension = filename.c_str() + lastDotPos + 1;
+ bool removeExtension = false;
+
+ // TODO: Should we really keep filenames suggesting raw resource
+ // forks or MacBinary files but not being such around? This might
+ // depend on the pattern the client requests...
+ if (!scumm_stricmp(extension, "rsrc")) {
+ SeekableReadStream *stream = (*i)->createReadStream();
+ removeExtension = stream && isRawFork(*stream);
+ delete stream;
+ } else if (!scumm_stricmp(extension, "bin")) {
+ SeekableReadStream *stream = (*i)->createReadStream();
+ removeExtension = stream && isMacBinary(*stream);
+ delete stream;
+ }
+
+ if (removeExtension) {
+ filename.erase(lastDotPos);
+ }
+ }
+
+ // Strip AppleDouble '._' prefix if applicable.
+ bool isAppleDoubleName = false;
+ const String filenameAppleDoubleStripped = disassembleAppleDoubleName(filename, &isAppleDoubleName);
+
+ if (isAppleDoubleName) {
+ SeekableReadStream *stream = (*i)->createReadStream();
+ if (stream->readUint32BE() == 0x00051607) {
+ filename = filenameAppleDoubleStripped;
+ }
+ // TODO: Should we really keep filenames suggesting AppleDouble
+ // but not being AppleDouble around? This might depend on the
+ // pattern the client requests...
+ delete stream;
+ }
+
+ baseNames[filename] = true;
+ }
+
+ // Append resulting base names to list to indicate found files.
+ for (BaseNameSet::const_iterator i = baseNames.begin(), end = baseNames.end(); i != end; ++i) {
+ files.push_back(i->_key);
+ }
+}
+
bool MacResManager::loadFromAppleDouble(SeekableReadStream &stream) {
if (stream.readUint32BE() != 0x00051607) // tag
return false;
@@ -314,6 +385,18 @@ bool MacResManager::isMacBinary(SeekableReadStream &stream) {
return true;
}
+bool MacResManager::isRawFork(SeekableReadStream &stream) {
+ // TODO: Is there a better way to detect whether this is a raw fork?
+ const uint32 dataOffset = stream.readUint32BE();
+ const uint32 mapOffset = stream.readUint32BE();
+ const uint32 dataLength = stream.readUint32BE();
+ const uint32 mapLength = stream.readUint32BE();
+
+ return !stream.eos() && !stream.err()
+ && dataOffset < (uint32)stream.size() && dataOffset + dataLength <= (uint32)stream.size()
+ && mapOffset < (uint32)stream.size() && mapOffset + mapLength <= (uint32)stream.size();
+}
+
bool MacResManager::loadFromMacBinary(SeekableReadStream &stream) {
byte infoHeader[MBI_INFOHDR];
stream.read(infoHeader, MBI_INFOHDR);
@@ -592,4 +675,32 @@ String MacResManager::constructAppleDoubleName(String name) {
return name;
}
+String MacResManager::disassembleAppleDoubleName(String name, bool *isAppleDouble) {
+ if (isAppleDouble) {
+ *isAppleDouble = false;
+ }
+
+ // Remove "._" before the last portion of a path name.
+ for (int i = name.size() - 1; i >= 0; --i) {
+ if (i == 0) {
+ if (name.size() > 2 && name[0] == '.' && name[1] == '_') {
+ name.erase(0, 2);
+ if (isAppleDouble) {
+ *isAppleDouble = true;
+ }
+ }
+ } else if (name[i] == '/') {
+ if ((uint)(i + 2) < name.size() && name[i + 1] == '.' && name[i + 2] == '_') {
+ name.erase(i + 1, 2);
+ if (isAppleDouble) {
+ *isAppleDouble = true;
+ }
+ }
+ break;
+ }
+ }
+
+ return name;
+}
+
} // End of namespace Common
diff --git a/common/macresman.h b/common/macresman.h
index 43ec8d8e2c..05b2a875f4 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -33,6 +33,7 @@
#include "common/array.h"
#include "common/fs.h"
#include "common/str.h"
+#include "common/str-array.h"
#ifndef COMMON_MACRESMAN_H
#define COMMON_MACRESMAN_H
@@ -82,6 +83,16 @@ public:
static bool exists(const String &fileName);
/**
+ * List all filenames matching pattern for opening with open().
+ *
+ * @param files Array containing all matching filenames discovered. Only
+ * adds to the list.
+ * @param pattern Pattern to match against. Taking String::matchPattern's
+ * format.
+ */
+ static void listFiles(StringArray &files, const String &pattern);
+
+ /**
* Close the Mac data/resource fork pair.
*/
void close();
@@ -176,6 +187,7 @@ private:
bool loadFromAppleDouble(SeekableReadStream &stream);
static String constructAppleDoubleName(String name);
+ static String disassembleAppleDoubleName(String name, bool *isAppleDouble);
/**
* Check if the given stream is in the MacBinary format.
@@ -183,6 +195,13 @@ private:
*/
static bool isMacBinary(SeekableReadStream &stream);
+ /**
+ * Do a sanity check whether the given stream is a raw resource fork.
+ *
+ * @param stream Stream object to check. Will not preserve its position.
+ */
+ static bool isRawFork(SeekableReadStream &stream);
+
enum {
kResForkNone = 0,
kResForkRaw,
diff --git a/common/rational.h b/common/rational.h
index 55fb361774..89caaf25b4 100644
--- a/common/rational.h
+++ b/common/rational.h
@@ -84,6 +84,8 @@ public:
int getNumerator() const { return _num; }
int getDenominator() const { return _denom; }
+ bool isOne() const { return _num == _denom; }
+
void debugPrint(int debuglevel = 0, const char *caption = "Rational:") const;
private:
diff --git a/common/rect.h b/common/rect.h
index 32424d3e6a..e6534e55d3 100644
--- a/common/rect.h
+++ b/common/rect.h
@@ -163,7 +163,8 @@ struct Rect {
*
* @param r the rectangle to check
*
- * @return true if the given rectangle is inside the rectangle, false otherwise
+ * @return true if the given rectangle has a non-empty intersection with
+ * this rectangle, false otherwise
*/
bool intersects(const Rect &r) const {
return (left < r.right) && (r.left < right) && (top < r.bottom) && (r.top < bottom);
diff --git a/common/savefile.h b/common/savefile.h
index b0c4d31f53..9fca07f9d5 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -56,6 +56,12 @@ typedef WriteStream OutSaveFile;
* i.e. typically save states, but also configuration files and similar
* things.
*
+ * Savefile names represent SaveFiles. These names are case insensitive, that
+ * means a name of "Kq1.000" represents the same savefile as "kq1.000". In
+ * addition, SaveFileManager does not allow for names which contain path
+ * separators like '/' or '\'. This is because we do not support directories
+ * in SaveFileManager.
+ *
* While not declared as a singleton, it is effectively used as such,
* with OSystem::getSavefileManager returning a pointer to the single
* SaveFileManager instances to be used.
@@ -115,49 +121,56 @@ public:
* exports from the Quest for Glory series. QfG5 is a 3D game and won't be
* supported by ScummVM.
*
- * @param name the name of the savefile
- * @param compress toggles whether to compress the resulting save file
- * (default) or not.
- * @return pointer to an OutSaveFile, or NULL if an error occurred.
+ * @param name The name of the savefile.
+ * @param compress Toggles whether to compress the resulting save file
+ * (default) or not.
+ * @return Pointer to an OutSaveFile, or NULL if an error occurred.
*/
virtual OutSaveFile *openForSaving(const String &name, bool compress = true) = 0;
/**
* Open the file with the specified name in the given directory for loading.
- * @param name the name of the savefile
- * @return pointer to an InSaveFile, or NULL if an error occurred.
+ *
+ * @param name The name of the savefile.
+ * @return Pointer to an InSaveFile, or NULL if an error occurred.
*/
virtual InSaveFile *openForLoading(const String &name) = 0;
/**
* Removes the given savefile from the system.
- * @param name the name of the savefile to be removed.
+ *
+ * @param name The name of the savefile to be removed.
* @return true if no error occurred, false otherwise.
*/
virtual bool removeSavefile(const String &name) = 0;
/**
* Renames the given savefile.
- * @param oldName Old name.
- * @param newName New name.
+ *
+ * @param oldName Old name.
+ * @param newName New name.
* @return true if no error occurred. false otherwise.
*/
virtual bool renameSavefile(const String &oldName, const String &newName);
/**
* Copy the given savefile.
- * @param oldName Old name.
- * @param newName New name.
+ *
+ * @param oldName Old name.
+ * @param newName New name.
* @return true if no error occurred. false otherwise.
*/
virtual bool copySavefile(const String &oldName, const String &newName);
/**
- * Request a list of available savegames with a given DOS-style pattern,
- * also known as "glob" in the POSIX world. Refer to the Common::matchString()
- * function to learn about the precise pattern format.
- * @param pattern Pattern to match. Wildcards like * or ? are available.
- * @return list of strings for all present file names.
+ * List available savegames matching a given pattern.
+ *
+ * Our pattern format is based on DOS paterns, also known as "glob" in the
+ * POSIX world. Please refer to the Common::matchString() function to learn
+ * about the precise pattern format.
+ *
+ * @param pattern Pattern to match. Wildcards like * or ? are available.
+ * @return List of strings for all present file names.
* @see Common::matchString()
*/
virtual StringArray listSavefiles(const String &pattern) = 0;
diff --git a/common/taskbar.h b/common/taskbar.h
index b4ec673739..f1a9adb2d9 100644
--- a/common/taskbar.h
+++ b/common/taskbar.h
@@ -123,7 +123,7 @@ public:
virtual void addRecent(const String &name, const String &description) {}
/**
- * Notifies the user an error occured through the taskbar icon
+ * Notifies the user an error occurred through the taskbar icon
*
* This will for example show the taskbar icon as red (using progress of 100% and an error state)
* on Windows, and set the launcher icon in the urgent state on Unity
diff --git a/configure b/configure
index 2a2357caa2..0e7a5a9b56 100755
--- a/configure
+++ b/configure
@@ -162,6 +162,7 @@ _translation=yes
# Default platform settings
_backend=sdl
_16bit=auto
+_highres=auto
_savegame_timestamp=auto
_dynamic_modules=no
_elf_loader=no
@@ -181,6 +182,7 @@ _stagingpath="staging"
_win32path="c:/scummvm"
_amigaospath="Games:ScummVM"
_staticlibpath=
+_xcodetoolspath=
_sdlconfig=sdl-config
_freetypeconfig=freetype-config
_sdlpath="$PATH"
@@ -201,6 +203,7 @@ add_feature 16bit "16bit color" "_16bit"
add_feature faad "libfaad" "_faad"
add_feature flac "FLAC" "_flac"
add_feature freetype2 "FreeType2" "_freetype2"
+add_feature highres "high resolution" "_highres"
add_feature mad "MAD" "_mad"
add_feature jpeg "JPEG" "_jpeg"
add_feature png "PNG" "_png"
@@ -593,7 +596,7 @@ engine_enable() {
parent=`get_subengine_parent ${engine}`
if test `get_engine_build ${parent}` = "no" ; then
set_var _engine_${parent}_build "yes"
- fi
+ fi
fi
if test "$opt" = "static" -o "$opt" = "dynamic" -o "$opt" = "yes" ; then
@@ -903,7 +906,7 @@ Game engines:
--disable-all-engines disable all engines
--enable-engine=<engine name>[,<engine name>...] enable engine(s) listed
--disable-engine=<engine name>[,<engine name>...] disable engine(s) listed
- --enable-engine-static=<engine name>[,<engine name>...]
+ --enable-engine-static=<engine name>[,<engine name>...]
enable engine(s) listed as static builtin (when plugins are enabled)
--enable-engine-dynamic=<engine name>[,<engine name>...]
enable engine(s) listed as dynamic plugin (when plugins are enabled)
@@ -922,6 +925,7 @@ Optional Features:
--default-dynamic make plugins dynamic by default
--disable-mt32emu don't enable the integrated MT-32 emulator
--disable-16bit don't enable 16bit color support
+ --disable-highres don't enable support for high resolution engines >320x240
--disable-savegame-timestamp don't use timestamps for blank savegame descriptions
--disable-scalers exclude scalers
--disable-hq-scalers exclude HQ2x and HQ3x scalers
@@ -1019,6 +1023,8 @@ done # for parm in ...
for ac_option in $@; do
case "$ac_option" in
--disable-16bit) _16bit=no ;;
+ --enable-highres) _highres=yes ;;
+ --disable-highres) _highres=no ;;
--disable-savegame-timestamp) _savegame_timestamp=no ;;
--disable-scalers) _build_scalers=no ;;
--disable-hq-scalers) _build_hq_scalers=no ;;
@@ -1230,6 +1236,9 @@ for ac_option in $@; do
--with-staticlib-prefix=*)
_staticlibpath=`echo $ac_option | cut -d '=' -f 2`
;;
+ --with-xcodetools-path=*)
+ _xcodetoolspath=`echo $ac_option | cut -d '=' -f 2`
+ ;;
--host=*)
_host=`echo $ac_option | cut -d '=' -f 2`
;;
@@ -1318,7 +1327,7 @@ raspberrypi)
_host_cpu=arm
# This tuple is the one used by the official Rpi toolchain.
# It may change in the future.
- _host_alias=bcm2708hardfp
+ _host_alias=arm-linux-gnueabihf
;;
caanoo)
_host_os=gph-linux
@@ -2283,7 +2292,7 @@ case $_host_os in
LDFLAGS="-L${macport_prefix}/lib $LDFLAGS"
CXXFLAGS="-I${macport_prefix}/include $CXXFLAGS"
-
+
if test -z "$_staticlibpath"; then
_staticlibpath=${macport_prefix}
echo "Set staticlib-prefix to ${_staticlibpath}"
@@ -2345,6 +2354,17 @@ case $_host_os in
echo "Could not determine prefix for static libraries"
fi
fi
+
+ # If _xcodetoolspath is not set yet use xcode-select to get the path
+ if test -z "$_xcodetoolspath"; then
+ _xcodetoolspath=`xcode-select -print-path`/Tools
+ if test -d "$_xcodetoolspath"; then
+ echo "Set xcodetools-path to ${_xcodetoolspath}"
+ else
+ _xcodetoolspath=
+ echo "Could not determine path for Xcode Tools"
+ fi
+ fi
;;
dreamcast)
append_var DEFINES "-D__DC__"
@@ -2438,6 +2458,10 @@ case $_host_os in
mint*)
append_var DEFINES "-DSYSTEM_NOT_SUPPORTING_D_TYPE"
;;
+ msys)
+ echo ERROR: Using the MSYS shell in msys mode is not supported. Please use the MSYS shell in mingw mode instead.
+ exit 1
+ ;;
n64)
append_var DEFINES "-D__N64__"
append_var DEFINES "-DLIMIT_FPS"
@@ -2604,7 +2628,7 @@ if test -n "$_host"; then
_mt32emu=no
_optimization_level=-O3
# Disable alsa midi to get the port build on OpenDingux toolchain
- _alsa=no
+ _alsa=no
_vkeybd=yes
_build_hq_scalers=no
_keymapper=no
@@ -2631,7 +2655,7 @@ if test -n "$_host"; then
_eventrec=no
_build_scalers=no
_build_hq_scalers=no
- # We prefer SDL2 on the Raspberry Pi: acceleration now depends on it
+ # We prefer SDL2 on the Raspberry Pi: acceleration now depends on it
# since SDL2 manages dispmanx/GLES2 very well internally.
# SDL1 is bit-rotten on this platform.
_sdlconfig=sdl2-config
@@ -2659,7 +2683,11 @@ if test -n "$_host"; then
_build_scalers=no
_mad=yes
_zlib=yes
- add_line_to_config_mk 'ronindir = /usr/local/ronin'
+ if test -z "$RONINDIR"; then
+ add_line_to_config_mk "ronindir := /usr/local/ronin"
+ else
+ add_line_to_config_mk "ronindir := $RONINDIR"
+ fi
_port_mk="backends/platform/dc/dreamcast.mk"
;;
ds)
@@ -2692,7 +2720,9 @@ if test -n "$_host"; then
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
add_line_to_config_h "#define USE_WII_DI"
;;
- gcw0)
+ gcw0)
+ _sysroot=`$CXX --print-sysroot`
+ _sdlpath=$_sysroot/usr/bin
append_var DEFINES "-DDINGUX -DGCW0"
append_var DEFINES "-DREDUCE_MEMORY_USAGE"
append_var CXXFLAGS "-mips32"
@@ -2749,11 +2779,8 @@ if test -n "$_host"; then
;;
ios7)
append_var DEFINES "-DIPHONE"
- append_var CFLAGS "-Wno-shift-count-overflow"
- append_var CXXFLAGS "-Wno-shift-count-overflow"
_backend="ios7"
_build_scalers=no
- _mt32emu=no
_seq_midi=no
_timidity=no
;;
@@ -2770,7 +2797,7 @@ if test -n "$_host"; then
append_var INCLUDES "-I/usr/X11R6/include"
append_var LIBS "-lX11"
append_var LIBS "-L/usr/lib"
-
+
_backend="maemo"
_vkeybd=yes
_keymapper=yes
@@ -3207,6 +3234,26 @@ case $_backend in
esac
#
+# Enable High resolution engines (>320x240) support only for backends which support it
+#
+case $_host in
+ gcw0)
+ if test "$_highres" = yes ; then
+ _highres=yes
+ else
+ _highres=no
+ fi
+ ;;
+ *)
+ if test "$_highres" = no ; then
+ _highres=no
+ else
+ _highres=yes
+ fi
+ ;;
+esac
+
+#
# Enable Event Recorder only for backends that support it
#
case $_backend in
@@ -3519,6 +3566,11 @@ define_in_config_if_yes "$_mt32emu" 'USE_MT32EMU'
define_in_config_if_yes "$_16bit" 'USE_RGB_COLOR'
#
+# Check whether High resolution graphics support is requested
+#
+define_in_config_if_yes "$_highres" 'USE_HIGHRES'
+
+#
# Check whether save games use the current time as default description
#
define_in_config_if_yes "$_savegame_timestamp" 'USE_SAVEGAME_TIMESTAMP'
@@ -3898,17 +3950,14 @@ fi
echo "$_sparkle"
#
-# Check for FluidSynth
+# Check for FluidSynth
#
echocheck "FluidSynth"
append_var FLUIDSYNTH_LIBS "-lfluidsynth"
case $_host_os in
mingw*)
- # NOTE: Windows builds use an older FluidSynth version (1.0.9)
- # which doesn't require glib, to avoid bundling the complete glib
- # libraries with Windows builds.
- FLUIDSYNTH_STATIC_LIBS="$FLUIDSYNTH_LIBS -ldsound -lwinmm"
+ FLUIDSYNTH_STATIC_LIBS="$FLUIDSYNTH_LIBS -lglib-2.0 -lintl -liconv -lws2_32 -lole32 -lshlwapi -lpcre -ldsound -lwinmm"
;;
darwin*)
@@ -4421,6 +4470,10 @@ if test "$_16bit" = yes ; then
echo_n ", 16bit color"
fi
+if test "$_highres" = yes ; then
+ echo_n ", high resolution"
+fi
+
if test "$_savegame_timestamp" = yes ; then
echo_n ", savegame timestamp"
fi
@@ -4434,7 +4487,7 @@ if test "$_build_scalers" = yes ; then
fi
if test "$_mt32emu" = yes ; then
- echo_n ", MT-32 emu"
+ echo_n ", MT-32 emulator"
fi
if test "$_text_console" = yes ; then
@@ -4691,6 +4744,7 @@ STAGINGPATH=$_stagingpath
WIN32PATH=$_win32path
AMIGAOSPATH=$_amigaospath
STATICLIBPATH=$_staticlibpath
+XCODETOOLSPATH=$_xcodetoolspath
SDLCONFIG=$_sdlconfig
ABI := $ABI
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 65b7601a54..aa450f1461 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -939,7 +939,7 @@ const Feature s_features[] = {
{ "mad", "USE_MAD", "libmad", true, "libmad (MP3) support" },
{ "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", true, "Ogg Vorbis support" },
{ "flac", "USE_FLAC", "libFLAC_static win_utf8_io_static", true, "FLAC support" },
- { "png", "USE_PNG", "libpng", true, "libpng support" },
+ { "png", "USE_PNG", "libpng16", true, "libpng support" },
{ "faad", "USE_FAAD", "libfaad", false, "AAC support" },
{ "mpeg2", "USE_MPEG2", "libmpeg2", false, "MPEG-2 support" },
{ "theora", "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index a326bd721a..a804205c42 100644
--- a/devtools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
@@ -319,12 +319,6 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
libraries += *i + ".lib;";
- if (_version == 14) {
- std::string debug = isRelease ? "" : "d";
- libraries += "libvcruntime" + debug + ".lib;";
- libraries += "libucrt" + debug + ".lib;";
- }
-
project << "\t\t<Link>\n"
"\t\t\t<OutputFile>$(OutDir)" << ((setup.devTools || setup.tests) ? name : setup.projectName) << ".exe</OutputFile>\n"
"\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n"
@@ -370,17 +364,17 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
"<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<PropertyGroup>\n"
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n"
- "\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(ExecutablePath)</ExecutablePath>\n"
- "\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
+ "\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(" << LIBS_DEFINE << ")\\bin\\" << (bits == 32 ? "x86" : "x64") << ";$(ExecutablePath)</ExecutablePath>\n"
+ "\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << "\\$(Configuration);$(LibraryPath)</LibraryPath>\n"
"\t\t<IncludePath>$(" << LIBS_DEFINE << ")\\include;$(" << LIBS_DEFINE << ")\\include\\SDL;$(IncludePath)</IncludePath>\n"
"\t\t<OutDir>$(Configuration)" << bits << "\\</OutDir>\n"
- "\t\t<IntDir>$(Configuration)" << bits << "/$(ProjectName)\\</IntDir>\n"
+ "\t\t<IntDir>$(Configuration)" << bits << "\\$(ProjectName)\\</IntDir>\n"
"\t</PropertyGroup>\n"
"\t<ItemDefinitionGroup>\n"
"\t\t<ClCompile>\n"
"\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
"\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
- "\t\t\t<AdditionalIncludeDirectories>$(" << LIBS_DEFINE << ")\\include;.;" << prefix << ";" << prefix << "\\engines;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
+ "\t\t\t<AdditionalIncludeDirectories>.;" << prefix << ";" << prefix << "\\engines;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
"\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<ExceptionHandling>" << ((setup.devTools || setup.tests) ? "Sync" : "") << "</ExceptionHandling>\n";
@@ -437,10 +431,14 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t\t\t<StringPooling>true</StringPooling>\n"
"\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
"\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
- "\t\t\t<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n"
+ "\t\t\t<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n"
"\t\t\t<EnablePREfast>" << (configuration == "Analysis" ? "true" : "false") << "</EnablePREfast>\n"
"\t\t</ClCompile>\n"
+ "\t\t<Lib>\n"
+ "\t\t\t<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>\n"
+ "\t\t</Lib>\n"
"\t\t<Link>\n"
+ "\t\t\t<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>\n"
"\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
"\t\t\t<SetChecksum>true</SetChecksum>\n";
} else {
@@ -448,11 +446,17 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t\t\t<PreprocessorDefinitions>WIN32;" << (configuration == "LLVM" ? "_CRT_SECURE_NO_WARNINGS;" : "") << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<MinimalRebuild>true</MinimalRebuild>\n"
"\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n"
- "\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n"
+ "\t\t\t<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n"
"\t\t\t<FunctionLevelLinking>true</FunctionLevelLinking>\n"
- "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n"
- "\t\t\t<DebugInformationFormat>" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "</DebugInformationFormat>\n" // For x64 format Edit and continue is not supported, thus we default to Program Database
- "\t\t\t<EnablePREfast>" << (configuration == "Analysis" ? "true" : "false") << "</EnablePREfast>\n";
+ "\t\t\t<TreatWarningAsError>false</TreatWarningAsError>\n";
+ if (_version >= 14) {
+ // Since MSVC 2015 Edit and Continue is support for x64 too.
+ properties << "\t\t\t<DebugInformationFormat>" << "EditAndContinue" << "</DebugInformationFormat>\n";
+ } else {
+ // Older MSVC versions did not support Edit and Continue for x64, thus we do not use it.
+ properties << "\t\t\t<DebugInformationFormat>" << (isWin32 ? "EditAndContinue" : "ProgramDatabase") << "</DebugInformationFormat>\n";
+ }
+ properties << "\t\t\t<EnablePREfast>" << (configuration == "Analysis" ? "true" : "false") << "</EnablePREfast>\n";
if (configuration == "LLVM") {
// FIXME The LLVM cl wrapper does not seem to work properly with the $(TargetDir) path so we hard-code the build folder until the issue is resolved
@@ -463,8 +467,7 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
properties << "\t\t</ClCompile>\n"
"\t\t<Link>\n"
"\t\t\t<GenerateDebugInformation>true</GenerateDebugInformation>\n"
- "\t\t\t<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n"
- "\t\t\t<IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n";
+ "\t\t\t<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n";
}
properties << "\t\t</Link>\n"
diff --git a/devtools/create_project/scripts/postbuild.cmd b/devtools/create_project/scripts/postbuild.cmd
index fcbd8c534a..31d2a94416 100644
--- a/devtools/create_project/scripts/postbuild.cmd
+++ b/devtools/create_project/scripts/postbuild.cmd
@@ -59,7 +59,7 @@ echo Invalid installer parameter. Should be "0" or "1" (was %~5)!
goto done
:error_script:
-echo An error occured while running the installer script!
+echo An error occurred while running the installer script!
goto done
:done
diff --git a/devtools/create_project/scripts/prebuild.cmd b/devtools/create_project/scripts/prebuild.cmd
index fbab426137..0efaab190c 100644
--- a/devtools/create_project/scripts/prebuild.cmd
+++ b/devtools/create_project/scripts/prebuild.cmd
@@ -27,7 +27,7 @@ echo Invalid target folder (%~2)!
goto done
:error_script:
-echo An error occured while running the revision script!
+echo An error occurred while running the revision script!
:done
exit /B0
diff --git a/devtools/create_wage/create_wage.sh b/devtools/create_wage/create_wage.sh
new file mode 100755
index 0000000000..5e8fe352a2
--- /dev/null
+++ b/devtools/create_wage/create_wage.sh
@@ -0,0 +1,119 @@
+#!/bin/bash
+#
+# This script downloads System 7.0.1 image from Apple and extracts fonts
+# from it. Mac only, unfortunately.
+#
+# On Windows you perhaps can perform the extraction manually with use of
+# HFV Explorer: https://web.archive.org/web/20011202005455/http://gamma.nic.fi/~lpesonen/HFVExplorer/
+#
+# More information could be found in the vMac documentation: http://www.gryphel.com/c/image/
+#
+# Alternatively you may use vMac instructions for extracting these disk images:
+# http://www.gryphel.com/c/minivmac/recipes/sys7inst/
+#
+# Based on instructions posted at
+# http://apple.stackexchange.com/questions/58243/can-i-get-the-original-mac-font-chicago-on-a-mountain-lion-mac
+
+echo_n() {
+ printf "$@"
+}
+
+if test `uname` != "Darwin"; then
+ echo This script is Mac OS X-only
+ exit
+fi
+
+echo_n "Downloading System 7.0.1 image..."
+if test ! -f System_7.0.1.smi.bin; then
+ curl -s http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Macintosh/System/Older_System/System_7.0.x/System_7.0.1.smi.bin -o System_7.0.1.smi.bin
+fi
+
+if test ! -f System_7.0.1.smi.bin; then
+ echo "Cannot download System_7.0.1.smi.bin"
+ exit
+fi
+
+echo done
+
+echo_n "Mounting System 7.0.1 image..."
+
+macbinary decode System_7.0.1.smi.bin
+hdiutil convert -quiet System\ 7.0.1.smi -format UDRO -o sys7.dmg
+hdiutil attach -quiet sys7.dmg
+
+if test ! -f /Volumes/7.0.1\ \(1440k.images\)/Fonts.image; then
+ echo "Failed to attach sys7.dmg"
+ exit
+fi
+
+echo done
+
+echo_n "Mounting Fonts disk image..."
+
+hdiutil convert -quiet /Volumes/7.0.1\ \(1440k.images\)/Fonts.image -format UDRO -o fonts.dmg
+hdiutil detach -quiet `hdiutil info|grep "/Volumes/7.0.1 (1440k.images)"|cut -f 1`
+hdiutil attach -quiet fonts.dmg
+
+if test ! -f /Volumes/Fonts/Chicago; then
+ echo "Failed to attach fonts.dmg"
+ exit
+fi
+
+echo done
+
+echo_n "Copying fonts..."
+
+for i in Athens Cairo Chicago Courier Geneva Helvetica London "Los Angeles" Monaco "New York" Palatino "San Francisco" Symbol Times Venice
+do
+ echo $i
+ macbinary encode "/Volumes/Fonts/$i" -o "$i.bin" -n
+done
+
+echo ...Done
+
+hdiutil detach -quiet `hdiutil info|grep "/Volumes/Fonts"|cut -f 1`
+
+if test ! -f fondu_src-060102.tgz; then
+ echo_n "Getting fondu_src-060102.tgz..."
+ curl -s http://fondu.sourceforge.net/fondu_src-060102.tgz -o fondu_src-060102.tgz
+ tar xf fondu_src-060102.tgz
+fi
+
+if test ! -d fondu-060102; then
+ echo "Failed to download fondu_src-060102.tgz"
+ exit
+fi
+
+echo done
+
+if test ! -x fondu-060102/fondu; then
+ echo_n "Compiling fondu..."
+ cd fondu-060102
+ ./configure >configure.log 2>&1 && make 2>&1 >make.log
+ cd ..
+fi
+
+if test ! -x fondu-060102/fondu; then
+ echo "Failed to build fondu. See configure.log and make.log"
+ exit
+else
+ rm -f configure.log make.log
+fi
+
+echo done
+
+echo_n "Converting fonts..."
+fondu-060102/fondu -force *.bin
+echo done
+
+zip -9 wage *.bdf
+mv wage.zip wage.dat
+
+echo_n "Cleaning up..."
+rm *.bdf
+rm *.ttf
+rm *.bin
+rm *.dmg
+echo done
+
+ls -l wage.dat
diff --git a/devtools/credits.pl b/devtools/credits.pl
index d7cd26fbdc..c67793cbfa 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -287,7 +287,7 @@ sub begin_section {
# headlines...
my $ascii_title = html_entities_to_ascii($title);
$title = html_entities_to_cpp($title);
- if ($ascii_title ne $title) {
+ if ($ascii_title ne $title) {
print '"A1""'.$ascii_title.'",' . "\n";
}
print '"C1""'.$title.'",' . "\n";
@@ -295,7 +295,7 @@ sub begin_section {
} else {
my $ascii_title = html_entities_to_ascii($title);
$title = html_entities_to_cpp($title);
- if ($ascii_title ne $title) {
+ if ($ascii_title ne $title) {
print '"A1""'.$ascii_title.'",' . "\n";
}
print '"C1""'.$title.'",' . "\n";
@@ -428,7 +428,7 @@ sub add_person {
if (length $desc > 0) {
my $ascii_desc = html_entities_to_ascii($desc);
$desc = html_entities_to_cpp($desc);
- if ($ascii_desc ne $desc) {
+ if ($ascii_desc ne $desc) {
print '"A2""'.$ascii_desc.'",' . "\n";
}
print '"C2""'.$desc.'",' . "\n";
@@ -572,7 +572,7 @@ begin_credits("Credits");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
add_person("Paul Gilbert", "dreammaster", "");
end_section();
-
+
begin_section("CGE2");
add_person("Peter Bozs&oacute;", "uruk", "");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
@@ -803,7 +803,7 @@ begin_credits("Credits");
add_person("Einar Johan T. S&oslash;m&aring;en", "somaen", "");
add_person("Tobia Tesan", "t0by", "");
end_section();
-
+
begin_section("Z-Vision");
add_person("Adrian Astley", "RichieSams", "");
add_person("Filippos Karapetis", "[md5]", "");
@@ -823,6 +823,10 @@ begin_credits("Credits");
add_person("Marcus Comstedt", "", "");
end_section();
+ begin_section("GCW0");
+ add_person("Eugene Sandulenko", "", "");
+ end_section();
+
begin_section("GPH Devices (GP2X, GP2XWiz &amp; Caanoo)");
add_person("John Willis", "DJWillis", "");
end_section();
diff --git a/dists/gcw0/default.gcw0.desktop b/dists/gcw0/default.gcw0.desktop
index 46bd2be092..890852184f 100644
--- a/dists/gcw0/default.gcw0.desktop
+++ b/dists/gcw0/default.gcw0.desktop
@@ -11,6 +11,6 @@ Exec=scummvm.sh
Icon=scummvm
Terminal=false
Type=Application
-Categories=games
+Categories=games;
StartupNotify=false
-X-OD-Manual=README
+X-OD-Manual=README.man.txt
diff --git a/dists/ios7/Info.plist b/dists/ios7/Info.plist
index 2ea3ad87be..ceef7e7d36 100644
--- a/dists/ios7/Info.plist
+++ b/dists/ios7/Info.plist
@@ -26,6 +26,11 @@
<string>1.9.0git</string>
<key>UIApplicationExitsOnSuspend</key>
<false/>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchImages</key>
diff --git a/dists/ios7/Info.plist.in b/dists/ios7/Info.plist.in
index 33094f4df9..447677ebd9 100644
--- a/dists/ios7/Info.plist.in
+++ b/dists/ios7/Info.plist.in
@@ -26,6 +26,11 @@
<string>@VERSION@</string>
<key>UIApplicationExitsOnSuspend</key>
<false/>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchImages</key>
diff --git a/dists/macosx/DS_Store b/dists/macosx/DS_Store
index 7ad5a19d61..164e7beb9a 100644
--- a/dists/macosx/DS_Store
+++ b/dists/macosx/DS_Store
Binary files differ
diff --git a/dists/openpandora/pnd_make.sh b/dists/openpandora/pnd_make.sh
index 0c03e8154d..a24beaf5d4 100755
--- a/dists/openpandora/pnd_make.sh
+++ b/dists/openpandora/pnd_make.sh
@@ -41,9 +41,16 @@ cecho () # Color-echo. Argument $1 = message, Argument $2 = color
{
local default_msg="No message passed." # Doesn't really need to be a local variable.
message=${1:-$default_msg} # Defaults to default message.
- color=${2:-$black} # Defaults to black, if not specified.
- echo -e "$color$message"
- tput sgr0 # Reset to normal.
+
+ # We only output colors when stdout is outputting to a terminal.
+ # This avoids color codes being output in log files created on buildbot.
+ if [ -t 1 -a -n "$TERM" ]; then
+ color=${2:-$black} # Defaults to black, if not specified.
+ echo -e "$color$message"
+ tput -T"$TERM" sgr0 # Reset to normal.
+ else
+ echo "$message"
+ fi
return
}
diff --git a/dists/samsungtv/README-SamsungTV b/dists/samsungtv/README-SamsungTV
index 26ded6c7e6..7c171747dc 100644
--- a/dists/samsungtv/README-SamsungTV
+++ b/dists/samsungtv/README-SamsungTV
@@ -3,7 +3,7 @@ Notes:
- Should works on 2009 B series TVs (Full HD): LExxBE65x, LExxBE75x, PSxxB65x, UExxB7xxx, UExxB8xxx, PSxxB85x, LAxxB65x, LAxxB75x, UNxxB7xxx, UAxxB8xxx
- To allow use mouse and keyboard you need load extension first: "SamyGO Mouse And Keyboard"
Download from SamyGO project and run from Content Library:
- http://sourceforge.net/projects/samygo/files/SamyGO%20Kernel%20Modules/SamyGO%20Mouse%20and%20Keyboard%20Modules%20v0.01.zip/download
+ http://download.samygo.tv/B%20Series/Content%20Library%20Applications/SamyGO%20Mouse%20and%20Keyboard%20Modules%20v0.01.zip
- Buttons on remote controler: EXIT, SOURCE, P+, P-, TV, POWER, CONTENT - cause immediately exit from ScummVM
- Config file is in /mtd_rwarea/.scummvmrc
- Saves are stored in '/mtd_wiselink/scummvm savegames' directory
diff --git a/dists/win32/ScummVM.iss b/dists/win32/ScummVM.iss
index c156ab6ca1..817cc5aeef 100644
--- a/dists/win32/ScummVM.iss
+++ b/dists/win32/ScummVM.iss
@@ -105,7 +105,7 @@ Source: doc/de/Liesmich.txt; DestDir: {app}; Flags: ignoreversion isreadme; Lang
Source: doc/se/LasMig.txt; DestDir: {app}; Flags: ignoreversion isreadme; Languages: se
Source: README-SDL.txt; DestDir: {app}; Flags: ignoreversion
Source: scummvm.exe; DestDir: {app}; Flags: ignoreversion
-Source: SDL.dll; DestDir: {app}
+Source: SDL.dll; DestDir: {app}; Flags: replacesameversion
;Mirgration script for saved games in Windows NT4 onwards
Source: migration.bat; DestDir: {app}; Flags: ignoreversion; MinVersion: 0, 1
Source: migration.txt; DestDir: {app}; Flags: ignoreversion; MinVersion: 0, 1
diff --git a/doc/cz/PrectiMe b/doc/cz/PrectiMe
index d360aa46f9..3c03db9802 100644
--- a/doc/cz/PrectiMe
+++ b/doc/cz/PrectiMe
@@ -1,8 +1,8 @@
-PŘEČTIMĚ ScummVM
+\rPŘEČTIMĚ ScummVM
------------------------------------------------------------------------
Pro více informací, seznamy kompatibility, podrobnosti o dotacích, nejnovější verze,
-novinky o vývoji a další, prosím navštivte domovskou stránku ScummVM na: http://www.scummvm.org/
+novinky o vývoji a další, prosím navštivte domovskou stránku ScummVM na: <http://www.scummvm.org/>
Obsah:
@@ -10,31 +10,40 @@ Obsah:
1.0) Úvod
* 1.1 O ScummVM
* 1.2 Rychlý návod
+ * 1.3 NejÄastÄ›jší otázky
2.0) Kontakt
* 2.1 Hlášení chyb
3.0) Podporované hry
* 3.1 Ochrana proti kopírování
- * 3.2 Poznámky ke hře Day of the Tentacle
- * 3.3 Poznámky ke hrám Commodore64
- * 3.4 Poznámky k Maniac Mansion NES
- * 3.5 Poznámky ke hrám Macintosh
- * 3.6 Poznámky ke hrám Multi-CD
- * 3.7 Poznámky k The Curse of Monkey Island
- * 3.8 Poznámky ke hrám Broken Sword
- * 3.9 Poznámky k Beneath a Steel Sky
+ * 3.2 Datové soubory
+ * 3.3 Poznámky ke hrám Multi-CD
+ * 3.4 Známé problémy
+ * 3.5 Poznámky k Beneath a Steel Sky
+ * 3.6 Poznámky ke hrám Broken Sword
+ * * 3.6.1 Broken Sword
+ * * 3.6.2 Broken Sword II
+ * * 3.6.3 Videa z her Broken Sword
+ * * 3.6.4 Videa her Broken Sword ve zpětném pohledu
+ * 3.7 Poznámky k Day of the Tentacle
+ * 3.8 Poznámky k Discworld II
+ * 3.9 Poznámky k DraÄí Historie
* 3.10 Poznámky k Flight of the Amazon Queen
* 3.11 Poznámky ke Gobliiins
* 3.12 Poznámky k Inherit the Earth: Quest for the Orb
- * 3.13 Poznámky k Simon the Sorcerer
- * 3.14 Poznámky k The Feeble Files
- * 3.15 Poznámky k The Legend of Kyrandia
- * 3.16 Poznámky k Předvídavému Vstupnímu Dialogu her Sierra AGI
- * 3.17 Poznámky k Mickey's Space Adventure
- * 3.18 Poznámky k Winnie the Pooh
- * 3.19 Poznámky k Troll's Tale
- * 3.20 Poznámky k DraÄí Historie
- * 3.21 Titulky a hlasy souběžně v hrách Sierra SCI
- * 3.22 Známé problémy
+ * 3.13 Poznámky k Maniac Mansion na Apple II/NES
+ * 3.14 Poznámky k Mickey's Space Adventure
+ * 3.15 Poznámky k Nippon Safes Inc. na Amiga
+ * 3.16 Poznámky k Simon the Sorcerer
+ * 3.17 Poznámky k The Curse of Monkey Island
+ * 3.18 Poznámky k The Feeble Files
+ * 3.19 Poznámky k The Legend of Kyrandia
+ * 3.20 Poznámky k Troll's Tale
+ * 3.21 Poznámky k Winnie the Pooh
+ * 3.22 Poznámky k Předvídavému Vstupnímu Dialogu her Sierra AGI
+ * 3.23 Titulky a hlasy souběžně v hrách Sierra SCI
+ * 3.24 Poznámky k hrám Zork
+ * 3.25 Poznámky ke hrám Commodore64
+ * 3.26 Poznámky ke hrám Macintosh
4.0) Podporované platformy
5.0) Spuštění ScummVM
* 5.1 Možnosti příkazového řádku
@@ -52,7 +61,21 @@ Obsah:
* 7.3 Emulace MT-32
* 7.4 Emulace MIDI
* 7.5 Přirozená podpora MIDI
+ * * 7.5.1 Použití voleb MIDI pro přizpůsobení výstupu přirozeného MIDI
* 7.6 Podpora nativního UNIX, ALSA a sekvenceru dmedia
+ * * 7.6.1 Sekvencer ALSA [POUZE UNIX]
+ * * 7.6.2 Sekvencer dmedia IRIX [POUZE UNIX]
+ * 7.7 Podpora MIDI serveru TiMidity++
+ * 7.8 Použití komprimovaných zvukových souborů (MP3, Ogg Vorbis, Flac)
+ * * 7.8.1 Použití souborů MP3 pro zvuky z CD
+ * * 7.8.2 Použití souborů Ogg Vorbis pro zvuky z CD
+ * * 7.8.3 Použití souborů Flac pro zvuky z CD
+ * * 7.8.4 Komprimování MONSTER.SOU pomocí MP3
+ * * 7.8.5 Komprimování MONSTER.SOU pomocí Ogg Vorbis
+ * * 7.8.6 Komprimování MONSTER.SOU pomocí Flac
+ * * 7.8.7 Komprimování hudby/zvuků/hlasů v hrách AGOS
+ * * 7.8.8 Komprimování hlasů/hudby v Broken Sword
+ * * 7.8.9 Komprimování hlasů/hudby v Broken Sword II
* 7.7 Podpora MIDI serveru TiMidity++
* 7.8 Použití komprimovaných zvukových souborů (MP3, Ogg Vorbis, Flac)
* 7.9 Výstupní vzorkovací kmitoÄet
@@ -60,6 +83,7 @@ Obsah:
* 8.1 Rozpoznávaná klíÄová slova nastavení
* 8.2 Vlastní herní volby, které mohou být přepínány pomoci grafického rozhraní
9.0) Sestavení
+10.0) Poděkování
1.0) Úvod:
@@ -104,16 +128,21 @@ V budoucnu byste mÄ›li být schopni pÅ™eskoÄit na krok 5, pokud nechcete pÅ™id
Rada: Pokud chcete pÅ™idat více her najednou, zkuste stisknout a držet klávesu shift pÅ™edtím, než kliknete na 'PÅ™idat hru' – tlaÄítko se zmÄ›ní na 'Hromadné PÅ™idání' a pokud ho stisknÄ›te, jste znovu požádáni o zvolení složky, ale tentokrát ScummVM prohledá vÅ¡echny podsložky pro podporované hry.
+1.3) NejÄastÄ›jší otázky
+---- ------------------
+Na <http://www.scummvm.org/faq/> jsme pro Vás pÅ™ipravili seznam nejÄastÄ›jších otázek a jejich odpovÄ›dí.
+
+
2.0) Kontakt:
---- --------
-Nejjednodušším způsobem, jak kontaktovat tým ScummVM je předložením hlášení o chybě (viz oddíl 2.1) nebo použitím našich fór na http://forums.scummvm.org .
+Nejjednodušším způsobem, jak kontaktovat tým ScummVM je předložením hlášení o chybě (viz oddíl 2.1) nebo použitím našich fór na <http://forums.scummvm.org>.
Můžete se také pÅ™ipojit a odesílat a e-maily na korespondenÄní seznam scummvm-devel, nebo si s námi popovídejte na IRC (#scummvm na irc.freenode.net) Nežádejte nás, prosím, o podporu nefungující hry – nejdříve si pÅ™eÄtÄ›te nejÄastÄ›jší otázky na naší stránce
2.1) Hlášení chyb:
---- -------------
Abyste mohli nahlásit chybu, nejdříve si, prosíme, vytvoÅ™te si úÄet na SourceForge a kliknÄ›te na odkaz "Bug Tracker" na naší stránce. UjistÄ›te se, prosím, že se chyba dá znovu zjistit a stále se objevuje v nejnovÄ›jší verzi git/denního sestavení. Také na naší stránce zkontrolujte seznam známých problémů (níže) a seznam kompatibility pro tuto hru, abyste se ujistili, že problém již není znám:
- http://www.scummvm.org/compatibility
+ <http://www.scummvm.org/compatibility>
Prosíme, nenahlaÅ¡ujte chyby ve hrách, které nejsou v seznamu v sekci 'Supported Games' nebo seznamu kompatibility uvedeny jako dokonÄitelné. My –víme-, že tyto hry mají chyby.
@@ -131,13 +160,18 @@ Nakonec prosíme, abyste každou chybu nahlaÅ¡ovali samostatnÄ›; neohlaÅ¡ujte nÄ
3.0) Podporované hry:
---- ----------------
-V tuto chvíli je o následujících hrách známo, že fungují a měly by být hratelné až dokonce:
+V tuto chvíli je o následujících hrách známo, že fungují a měly by být hratelné až dokonce.
+Podrobnější seznam kompatibility podporovaných her můžete nalézt na adrese:
+
+ <http://www.scummvm.org/compatibility/>)
+
-Hry SCUMM od LucasArts:
+Hry od LucasArts (SCUMM):
Maniac Mansion [maniac]
Zak McKracken and the Alien Mindbenders [zak]
Indiana Jones and the Last Crusade [indy3]
Loom [loom]
+ Passport to Adventure [pass]
The Secret of Monkey Island [monkey]
Monkey Island 2: LeChuck's Revenge [monkey2]
Indiana Jones and the Fate of Atlantis [atlantis]
@@ -147,32 +181,16 @@ Hry SCUMM od LucasArts:
The Dig [dig]
The Curse of Monkey Island [comi]
-Hry AGI a před AGI od Sierra:
- The Black Cauldron [bc]
- Gold Rush! [goldrush]
- King's Quest I [kq1]
- King's Quest II [kq2]
- King's Quest III [kq3]
- King's Quest IV [kq4]
- Leisure Suit Larry in the Land of the
- Lounge Lizards [lsl1]
- Mixed-Up Mother Goose [mixedup]
- Manhunter 1: New York [mh1]
- Manhunter 2: San Francisco [mh2]
- Police Quest I: In Pursuit of the Death
- Angel [pq1]
- Space Quest I: The Sarien Encounter [sq1]
- Space Quest II: Vohaul's Revenge [sq2]
- Fanmade Games [agi-fanmade]
- Mickey's Space Adventure [mickey]
- Troll's Tale [troll]
- Winnie the Pooh in the Hundred Acre Wood [winnie]
+Hry od Activision (MADE):
+ Leather Goddesses of Phobos 2 [lgop2]
+ The Manhole [manhole]
+ Return to Zork [rtz]
+ Rodney's Funscreen [rodney]
-Hry AGOS od Adventuresoft/Horrorsoft:
+Hry od Adventuresoft/Horrorsoft (AGOS):
Elvira - Mistress of the Dark [elvira1]
Elvira II - The Jaws of Cerberus [elvira2]
Personal Nightmare [pn]
- Waxworks [waxworks]
Simon the Sorcerer 1 [simon1]
Simon the Sorcerer 2 [simon2]
Simon the Sorcerer's Puzzle Pack
@@ -184,16 +202,9 @@ Hry AGOS od Adventuresoft/Horrorsoft:
Simon the Sorcerer's Puzzle Pack
- Swampy Adventures [swampy]
The Feeble Files [feeble]
-
-Hry Composer od Animation Magic:
- Darby the Dragon [darby]
- Gregory and the Hot Air Balloon [gregory]
- Magic Tales: Liam Finds a Story [liam]
- The Princess and the Crab [princess]
- Sleeping Cub's Test of Courage [sleepingcub]
+ Waxworks [waxworks]
-Hry GOB od Coktel Vision:
- Bambou le sauveur de la jungle [bambou]
+Hry od Coktel Vision (GOB):
Bargon Attack [bargon]
Fascination [fascination]
Geisha [geisha]
@@ -202,80 +213,40 @@ Hry GOB od Coktel Vision:
Goblins 3 [gob3]
Lost in Time [lostintime]
Once Upon A Time: Little Red Riding Hood [littlered]
+ Playtoons: Bambou le sauveur de la jungle [bambou]
The Bizarre Adventures of Woodruff
and the Schnibble [woodruff]
Urban Runner [urban]
Ween: The Prophecy [ween]
-
-Hry Living Books:
- Aesop's Fables: The Tortoise and the Hare [tortoise]
- Arthur's Birthday [arthurbday]
- Arthur's Teacher Trouble [arthur]
- Dr. Seuss's ABC [seussabc]
- Green Eggs and Ham [greeneggs]
- Harry and the Haunted House [harryhh]
- Just Grandma and Me [grandma]
- Little Monster at School [lilmonster]
- Ruff's Bone [ruff]
- Sheila Rae, the Brave [sheila]
- Stellaluna [stellaluna]
- The Berenstain Bears Get in a Fight [bearfight]
- The Berenstain Bears in the Dark [beardark]
- The New Kid on the Block [newkid]
-Hry MADE od Activision:
- Leather Goddesses of Phobos 2 [lgop2]
- Return to Zork [rtz]
- Rodney's Funscreen [rodney]
- The Manhole [manhole]
-
-Další hry:
- 3 Skulls of the Toltecs [toltecs]
- Blue Force [blueforce]
+Hry od Revolution Software (Různé):
Beneath a Steel Sky [sky]
Broken Sword: The Shadow of the Templars [sword1]
Broken Sword II: The Smoking Mirror [sword2]
- Bud Tucker in Double Trouble [tucker]
- Cruise for a Corpse [cruise]
- Discworld [dw]
- Discworld 2: Missing Presumed ...!? [dw2]
- Dragon History [draci]
- Drascula: The Vampire Strikes Back [drascula]
- DreamWeb [dreamweb]
- Eye of the Beholder [eob]
- Eye of the Beholder II: The Legend of
- Darkmoon [eob2]
- Flight of the Amazon Queen [queen]
- Future Wars [fw]
- Hopkins FBI [hopkins]
- Hugo's House of Horrors [hugo1]
- Hugo 2: Whodunit? [hugo2]
- Hugo 3: Jungle of Doom [hugo3]
- I Have No Mouth, and I Must Scream [ihnm]
- Inherit the Earth: Quest for the Orb [ite]
- Nippon Safes Inc. [nippon]
- Lands of Lore: The Throne of Chaos [lol]
Lure of the Temptress [lure]
- Mortville Manor [mortevielle]
- Nippon Safes Inc. [nippon]
- Ringworld: Revenge Of The Patriarch [ringworld]
- Return to Ringworld [ringworld2]
- Sfinx [sfinx]
- Soltys [soltys]
- TeenAgent [teenagent]
- The Journeyman Project: Pegasus Prime [pegasus]
- The Legend of Kyrandia [kyra1]
- The Legend of Kyrandia: The Hand of Fate [kyra2]
- The Legend of Kyrandia: Malcolm's Revenge [kyra3]
- The 7th Guest [t7g]
- The Neverhood [neverhood]
- Tony Tough and the Night of Roasted Moths [tony]
- Toonstruck [toon]
- Touche: The Adventures of the Fifth
- Musketeer [touche]
- Voyeur [voyeur]
-
-Hry SCI od Sierra Entertainment:
+
+Hry od Sierra (AGI a před AGI):
+ The Black Cauldron [bc]
+ Gold Rush! [goldrush]
+ King's Quest I [kq1]
+ King's Quest II [kq2]
+ King's Quest III [kq3]
+ King's Quest IV [kq4]
+ Leisure Suit Larry in the Land of the
+ Lounge Lizards [lsl1]
+ Mixed-Up Mother Goose [mixedup]
+ Manhunter 1: New York [mh1]
+ Manhunter 2: San Francisco [mh2]
+ Police Quest I: In Pursuit of the Death
+ Angel [pq1]
+ Space Quest I: The Sarien Encounter [sq1]
+ Space Quest II: Vohaul's Revenge [sq2]
+ Hry od fanoušků [agi-fanmade]
+ Mickey's Space Adventure [mickey]
+ Troll's Tale [troll]
+ Winnie the Pooh in the Hundred Acre Wood [winnie]
+
+Hry od Sierra Entertainment (SCI):
Castle of Dr. Brain [castlebrain]
Codename: ICEMAN [iceman]
Conquests of Camelot [camelot]
@@ -316,19 +287,64 @@ Hry SCI od Sierra Entertainment:
Space Quest V [sq5]
The Island of Dr. Brain [islandbrain]
-Hry Wintermute:
+Další hry:
+ 3 Skulls of the Toltecs [toltecs]
+ Amazon: Guardians of Eden [access]
+ Beavis and Butt-head in Virtual Stupidity [bbvs]
+ Blue Force [blueforce]
+ Broken Sword: The Return of the Templars [sword25]
+ Bud Tucker in Double Trouble [tucker]
Chivalry is Not Dead [chivalry]
-
-Hry ZVISION od Activision:
- Zork Nemesis: The Forbidden Lands [znemesis]
+ Cruise for a Corpse [cruise]
+ DreamWeb [dreamweb]
+ Discworld [dw]
+ Discworld 2: Missing Presumed ...!? [dw2]
+ Dragon History [draci]
+ Drascula: The Vampire Strikes Back [drascula]
+ Eye of the Beholder [eob]
+ Eye of the Beholder II: The Legend of
+ Darkmoon [eob2]
+ Flight of the Amazon Queen [queen]
+ Future Wars [fw]
+ Hopkins FBI [hopkins]
+ Hugo's House of Horrors [hugo1]
+ Hugo 2: Whodunit? [hugo2]
+ Hugo 3: Jungle of Doom [hugo3]
+ I Have No Mouth, and I Must Scream [ihnm]
+ Inherit the Earth: Quest for the Orb [ite]
+ Lands of Lore: The Throne of Chaos [lol]
+ Mortville Manor [mortevielle]
+ Nippon Safes Inc. [nippon]
+ Rex Nebular and the Cosmic Gender Bender [nebular]
+ Ringworld: Revenge Of The Patriarch [ringworld]
+ Return to Ringworld [ringworld2]
+ Sfinx [sfinx]
+ Soltys [soltys]
+ The Journeyman Project: Pegasus Prime [pegasus]
+ The Legend of Kyrandia [kyra1]
+ The Legend of Kyrandia: The Hand of Fate [kyra2]
+ The Legend of Kyrandia: Malcolm's Revenge [kyra3]
+ The Lost Files of Sherlock Holmes: The Case
+ of the Serrated Scalpel [scalpel]
+ The Lost Files of Sherlock Holmes: The Case
+ of the Rose Tattoo [rosetattoo]
+ The Neverhood [neverhood]
+ The 7th Guest [t7g]
+ TeenAgent [teenagent]
+ Toonstruck [toon]
+ Tony Tough and the Night of Roasted Moths [tony]
+ Touche: The Adventures of the Fifth
+ Musketeer [touche]
+ Voyeur [voyeur]
Zork: Grand Inquisitor [zgi]
+ Zork Nemesis: The Forbidden Lands [znemesis]
-Hry SCUMM od Humongous Entertainment:
+Hry od Humongous Entertainment (SCUMM):
Backyard Baseball [baseball]
Backyard Baseball 2001 [baseball2001]
Backyard Baseball 2003 [baseball2003]
Backyard Football [football]
- Backyard Football 2002 [football2002]
+ Backyard Football 2002 [football2002]
Bear Stormin' [brstorm]
Big Thinkers First Grade [thinker1]
Big Thinkers Kindergarten [thinkerk]
@@ -354,7 +370,7 @@ Hry SCUMM od Humongous Entertainment:
Let's Explore the Airport with Buzzy [airport]
Let's Explore the Farm with Buzzy [farm]
Let's Explore the Jungle with Buzzy [jungle]
- Pajama Sam: Games to Play on Any Day [pjgames]
+ Pajama Sam: Games to Play on Any Day [pjgames]
Pajama Sam 1: No Need to Hide When It's
Dark Outside [pajama]
Pajama Sam 2: Thunder and Lightning
@@ -363,12 +379,12 @@ Hry SCUMM od Humongous Entertainment:
From Your Head to Your Feet [pajama3]
Pajama Sam's Lost & Found [lost]
Pajama Sam's Sock Works [socks]
- Putt-Putt Joins the Parade [puttputt]
+ Putt-Putt Enters the Race [puttrace]
Putt-Putt Goes to the Moon [puttmoon]
+ Putt-Putt Joins the Circus [puttcircus]
+ Putt-Putt Joins the Parade [puttputt]
Putt-Putt Saves the Zoo [puttzoo]
Putt-Putt Travels Through Time [putttime]
- Putt-Putt Enters the Race [puttrace]
- Putt-Putt Joins the Circus [puttcircus]
Putt-Putt and Pep's Balloon-O-Rama [balloon]
Putt-Putt and Pep's Dog on a Stick [dog]
Putt-Putt & Fatty Bear's Activity Pack [activity]
@@ -387,6 +403,29 @@ Pokud chcete mít nejnovÄ›jší zprávy o kompatibilitách her, navÅ¡tivte naÅ¡Ã
Backyard Soccer 2004 [soccer2004]
Blue's Treasure Hunt [BluesTreasureHunt]
+Hry Composer od Animation Magic:
+ Darby the Dragon [darby]
+ Gregory and the Hot Air Balloon [gregory]
+ Magic Tales: Liam Finds a Story [liam]
+ The Princess and the Crab [princess]
+ Sleeping Cub's Test of Courage [sleepingcub]
+
+Hry Living Books:
+ Aesop's Fables: The Tortoise and the Hare [tortoise]
+ Arthur's Birthday [arthurbday]
+ Arthur's Teacher Trouble [arthur]
+ Dr. Seuss's ABC [seussabc]
+ Green Eggs and Ham [greeneggs]
+ Harry and the Haunted House [harryhh]
+ Just Grandma and Me [grandma]
+ Little Monster at School [lilmonster]
+ Ruff's Bone [ruff]
+ Sheila Rae, the Brave [sheila]
+ Stellaluna [stellaluna]
+ The Berenstain Bears Get in a Fight [bearfight]
+ The Berenstain Bears in the Dark [beardark]
+ The New Kid on the Block [newkid]
+
Následující hry jsou odvozeny od jádra SCUMM, ale ScummVM je nepodporuje (zatím):
Moonbase Commander
@@ -422,95 +461,122 @@ ScummVM přeskakuje ochranu v následujících hrách:
* Waxworks
* Zak McKracken and the Alien Mindbenders
-3.2) Poznámky ke hře Day of the Tentacle:
------------------------------------------
-Na jednom místÄ› ve hÅ™e narazíte na poÄítaÄ umožňující si zahrát původní
-Maniac Mansion jako bonus. ScummVM toto podporuje, ale je třeba
-upozornit na pár věcí:
+3.2) Datové soubory
+---- --------------
+Pro přehledný seznam požadovaných datových souborů u podporovaných her navštivte:
-ScummVM prohledá váš soubor s nastavením hledajíc hru nacházející se
-v podsložce 'Maniac' ve složce hry Day of the Tentacle. Pokud jste
-zkopírovali datové soubory z CD verze, tato struktura by již měla být
-vytvořena, navíc ale budete muset hru přidat také do ScummVM.
+<http://wiki.scummvm.org/index.php/Datafiles>
-Pro návrat do Day of the Tentacle, stisknÄ›te F5 a zvolte "Návrat do spouÅ¡tÄ›Äe".
-Teoreticky toto znamená, že je možné spustit jakoukoli hru jako bonus.
-Vskutku tomu tak je. Existuje "tajná" volba nastavení, "easter_egg", která
-mÄ›ní ID spouÅ¡tÄ›né hry. BuÄte ale opatrní, protože ne vÅ¡echny hry podporují
-návrat do spouÅ¡tÄ›Äe, a nedoporuÄuje se nastavovat spuÅ¡tÄ›ní samotné hry Day
-of the Tentacle jako bonus.
-
-3.3) Poznámky ke hrám Commodore64:
----- -----------------------------
-Jak Maniac Mansion tak Zak McKracken mohou být spuštěny, ale Maniac Mansion není ještě hratelný. Jednoduše pojmenujte disky D64 jako
-"maniac1.d64" a "maniac2.d64" nebo "zak1.d64" a "zak2.d64", pak by měl ScummVM automaticky hru zjistit, pokud ho odkážete na správnou složku.
+3.3) Poznámky ke hrám Multi-CD:
+---- --------------------------
+ObecnÄ› ScummVM moc dobÅ™e nefunguje s hrami na Multi-CD. To je proto, že ScummVM pÅ™edpokládá, že vÅ¡echno o hÅ™e může být nalezeno v jedné složce. I když ScummVM má schopnost požádat uživatele, aby vymÄ›nil CD, původní spouÅ¡tÄ›Ä souboru vÄ›tÅ¡inou nainstaluje malé množství souborů na pevný disk. Pokud tyto soubory nelze najít na vÅ¡ech CD, ScummVM bude mít potíže.
-Nebo můžete použít 'extract_mm_c64' z balíÄku nástrojů pro extrahování datových souborů. Pak ale ScummVM hru řádnÄ› automaticky nezjistí ScummVM, a musíte se ujistit, že platforma je nastavena na Commodore64. DoporuÄujeme použít mnohem jednodušší postup popsaný v pÅ™edchozím odstavci.
+Naštěstí může ScummVM hry bez problémů spouštět přímo z pevného disku, pokud vytvoříte složku se správnou kombinací souborů. Většinou, když se soubor objeví na více, než jednom CD můžete vybrat jeden z nich.
-3.4) Poznámky ke Maniac Mansion NES:
----- -------------------------
-Podporované verze jsou Britská angliÄtina (E), FrancouzÅ¡tina (F), NÄ›mÄina (G), ItalÅ¡tina (I), Å védÅ¡tina (SW) a Americká angliÄtina (U). ScummVM pro spuÅ¡tÄ›ní vyžaduje pouze Äást PRG a ne celý ROM.
+3.4) Známé Problémy:
+---- ---------------
+Toto vydání má následující známé problémy. Není tÅ™eba je ohlaÅ¡ovat, i když záplaty pro jejich opravu jsou vítány. Pokud objevíte chybu, která není zde v seznamu, ani není v seznamu kompatibility na internetové stránce, prohlédnÄ›te si, prosím, Äást o hlášení chyb.
-Abyste mohli hru spustit, musíte vyjmout prvních 16 bajtů z ROM, s kterým pracujete. Jakýkoli hex editor bude fungovat, pokud můžete kopírovat/vkládat. Poté. Co ROM otevÅ™ete pomocí hex editoru, zkopírujte vÅ¡echno z druhého řádku (17. bajt) na konec. Poté, co toto provedete, vložte ho do nového hex souboru. Pojmenujte ho "Maniac Mansion (XX).prg" kde XX znamená verzi, se kterou pracujete (E, F, G, I, SW, nebo U). KoneÄná velikost by mÄ›la být pÅ™esnÄ› 262144 bajtů.
+ Hry CD Audio:
+ - Při hraní her, které používají CD Audio (hry FM-TOWNS, Loom CD, atd) může u uživatelů Microsoft Windows 2000/XP docházet k náhodným pádům. To je díky dlouhotrvající chybě Windows, která má za následek poškozené soubory
+ pÅ™i Ätení z CD. Abyste se tomuto vyhnuli, zkopírujte, prosím, soubory na pevný disk
-Pokud hru pÅ™idáváte ruÄnÄ›, ujistÄ›te se, že platforma je nastavena na NES.
+ Verze FM-TOWNS:
+ - Verze Kandži vyžaduje ROM písma FM-TOWNS
-Nejběžnější chyby, které zabraňují spuštění hry:
+ Loom:
+ - Vypnutí titulků pomocí souboru nastavení je nevypne spolehlivě, protože skripty Loom je znovu automaticky zapnou
+ - Podpora MIDI ve verzi EGA vyžaduje aktualizaci Roland LucasArts
+ - Verze Kandži na PC-Engine vyžaduje rom systémové karty
- * Špatný soubor
- * ROM byl extrahován pomocí nástrojů z verze 0.7.0
- * Snažíte se do ScummVM vkládat CELà ROM a ne jenom PRG Äást.
+ The Secret of Monkey Island:
+ - Podpora MIDI ve verzi EGA vyžaduje aktualizaci Roland LucasArts
-Je také možno extrahovat oddÄ›lené soubory LFL z PRG Äásti. Pro toto použijte nástroj 'extract_mm_nes' z balíÄku nástrojů.
+ Beneath a Steel Sky:
+ - Verze pro Amiga nejsou podporovány
+ - Demoverze z diskety nejsou podporovány
+ - Není chyba: Ve verzi na CD chybí v jistých dialozích Å™eÄ, to je normální.
+ Elvira - Mistress of the Dark:
+ - Ve verzi pro Atari ST nefunguje hudba
-3.5) Poznámky ke hrám Macintosh:
----- ---------------------------
-VÅ¡echny adventury LucasArts založené na SCUMM, kromÄ› COMI, také existují ve verzích pro in Macintosh. ScummVM může vÄ›tÅ¡inu (vÅ¡echny?) použít, nicménÄ›, v nÄ›kterých případech je nutná dodateÄná práce. Nejdříve, pokud pro toto nepoužíváte Macintosh, přístup k datům na CD/disketÄ› může být obtížný. Důvodem je to, že Mac používá zvláštní formát disku nazvaný HFS, který ostatní systémy vÄ›tÅ¡inou nepodporují. NicménÄ› existuje, nÄ›kolik nástrojů, které jsou zadarmo a umožňují Äíst takovéto svazky HFS. Například "HFVExplorer" pro Windows a "hfsutils" pro Linux a ostatní Unixové operaÄní systémy.
+ Elvira II - The Jaws of Cerberus:
+ - Ve verzi pro Atari ST nefunguje hudba
+ - Ve verzi pro PC nefungují zvukové efekty
+ - Ve verzi pro Atari ST jsou problémy s paletou
-VÄ›tÅ¡ina novÄ›jších her na Macintosh je dodávána pouze s jedním datovým souborem (v nÄ›kterých případech byl tento soubor uÄinÄ›n neviditelným, takže možná budete potÅ™ebovat dodateÄné nástroje, abyste ho mohli zkopírovat). ScummVM je schopen takovýto soubor použít přímo; jednoduÅ¡e odkažte ScummVM na složku obsahující tento soubor a mÄ›lo by to fungovat (tak jako s každou podporovanou hrou).
+ Inherit the Earth: Quest for the Orb:
+ - Verze pro Amiga nejsou podporovány
-V balíÄku nástrojů také poskytujeme nástroj nazvaný 'extract_scumm_mac', který extrahuje data z tÄ›chto datových souborů, ale toto není ani potÅ™eba, ani doporuÄeno.
+ Lure of the Temptress:
+ - Žádná podpora Roland MT-32
+ - Podpora zvuku není dokonÄena a nezní jako v původní hÅ™e
-Pro další informace o kopírování herních souborů Macintosh na Váš pevný disk si prohlédněte:
+ Simon the Sorcerer 1:
+ - V anglických a německých verzích na CD nejsou titulky dostupné, protože jim většina titulků chybí.
- http://wiki.scummvm.org/index.php/HOWTO-Mac_Games
+ Simon the Sorcerer 2:
+ - Kombinace Å™eÄi a titulků Äasto způsobí, že Å™eÄ je pÅ™eruÅ¡ena brzo, toto je omezení původní hry.
+ - Ve verzích pro Amiga a Macintosh je podporován pouze výchozí jazyk datových souborů (angliÄtina).
+ Simon the Sorcerer's Puzzle Pack:
+ - Žádná podpora pro zobrazování, zadávání, ukládání, Äi naÄítání nejvyšších skóre.
+ - Žádná podpora pro zobrazování názvů položek, když na ně najedete myší ve Swampy Adventures.
-3.6) Poznámky ke hrám Multi-CD:
----- --------------------------
-ObecnÄ› ScummVM moc dobÅ™e nefunguje s hrami na Multi-CD. To je proto, že ScummVM pÅ™edpokládá, že vÅ¡echno o hÅ™e může být nalezeno v jedné složce. I když ScummVM má schopnost požádat uživatele, aby vymÄ›nil CD, původní spouÅ¡tÄ›Ä souboru vÄ›tÅ¡inou nainstaluje malé množství souborů na pevný disk. Pokud tyto soubory nelze najít na vÅ¡ech CD, ScummVM bude mít potíže.
+ The Feeble Files:
+ - Titulky jsou Äasto nedokonÄené. V původní hÅ™e byly vždy zakázány.
-Naštěstí může ScummVM hry bez problémů spouštět přímo z pevného disku, pokud vytvoříte složku se správnou kombinací souborů. Většinou, když se soubor objeví na více, než jednom CD můžete vybrat jeden z nich.
+ The Legend of Kyrandia:
+ - Ve verzích na disketě pro Mac není žádná hudba ani zvukové efekty.
+ - CD Macintosh používá zahrnutou hudbu a zvukové efekty z DOS.
+ Hry Humongous Entertainment:
+ - Pouze původní rozhraní pro uložení a naÄtení mohou být použity.
+ - Žádná podpora pro hru více hráÄů nebo tisknutí obrázků
-3.7) Poznámky k The Curse of Monkey Island:
----- --------------------------------------
-Pro tuto hru budete potřebovat soubory comi.la0, comi.la1 a comi.la2.
-Soubor comi.la0 můžete nalézt na všech CD hry, ale protože jsou stejné, můžete použít kterýkoli z nich.
-Dále potřebujete vytvořit podsložku "resource" obsahující všechny soubory z –obou- podsložek "resource" na dvou CD. Některé soubory se objevují na obou CD, ale znovu jsou stejné.
+3.5) Poznámky k Beneath a Steel Sky:
+---- -------------------------------
+Od ScummVM 0.8.0 potÅ™ebujete dodateÄný soubor 'SKY.CPT', abyste mohli Beneath a Steel Sky spustit.
+
+Tento soubor je dostupný na stránce 'Downloads' domovské stránky ScummVM.
+Můžete ho umístit buÄ do složky obsahující ostatní datové soubory (SKY.DNR, SKY.DSK), na VaÅ¡i dodateÄnou cestu, nebo do složky. Kde se nachází spouÅ¡tÄ›cí soubor ScummVM.
-3.8) Poznámky ke hrám Broken Sword:
+3.6) Poznámky ke hrám Broken Sword:
---- ------------------------------
Pokyny pro hry Broken Sword jsou pro verze od Sold-Out Software, kde každá hra je na dvou CD, protože tyto verze byly nejdostupnÄ›jší v dobÄ›, kdy je ScummVM zaÄal podporovat. Doufáme, že jsou dostateÄnÄ› obecné pro použití i v jiných vydáních her.
-3.8.1) Videa z her Broken Sword:
+3.6.1) Broken Sword:
+------ -------------
+Pro tuto hru budete potřebovat všechny soubory ze seskupení složek na obou CD. Pro verze Windows a Macintosh budete také potřebovat soubory speech.clu ze složek speech, ale protože soubory nejsou stejné, budete je muset přejmenovat na speech1.clu a speech2.clu z CD 1 a 2 v tomto pořadí. Verze na PlayStation vyžaduje speech.tab, speech.dat, speech.lis, a speech.inf.
+
+Dále verze pro Windows a Macintosh vyžadují podsložku music se vÅ¡emi soubory z podsložek music na obou CD. NÄ›které z tÄ›chto souborů se objevují na obou CD, ale v tÄ›chto případech jsou buÄ stejné, nebo, v jednom případÄ›, je téměř stejný, že to nemá žádný význam. Verze pro PlayStation vyžaduje tunes.dat a tunes.tab.
+
+
+3.6.2) Broken Sword II:
+------ ----------------
+Pro tuto hru budete potřebovat všechny soubory ze seskupení složek na obou CD. (Abych pravdu řekl, pár z nich nemusí být nezbytně nutné, ale ty, o kterých nemám jistotu, jsou velmi malé.)
+Je také třeba přejmenovat soubory speech.clu a music.clu na speech1.clu, speech2.clu, music1.clu a music2.clu, aby ScummVM mohl zjistit, které jsou z CD 1 a které z CD 2. Všechny ostatní soubory, které jsou umístěny v seskupení složek, jsou stejné. Použijte kterékoli soubory chcete.
+
+Kromě toho budete potřebovat soubory cd.inf a, případně, startup.inf ze složky sword2 na CD 1.
+
+
+3.6.3) Videa z her Broken Sword:
------ -------------------------
Videa pro hry Broken Sword mají v sobÄ› trochu historie (viz další oddíl, pokud jste zvÄ›daví), ale obecnÄ› jediné, co potÅ™ebujete udÄ›lat, je zkopírovat soubory .SMK ze složek "SMACKS" nebo "SMACKSHI" na CD do stejné složky jako ostatní datové soubory hry. (Broken Sword má také složku "SMACKSLO" se stejnými videi, ale ty jsou nižší kvality.) Můžete je umístit do podsložky s názvem "video", pokud Vám to pÅ™ijde hezÄí.
Ve verzích pro PlayStation, můžete původní videa vypsat z disku. Každý soubor, který má příponu "STR", byste mÄ›li vypsat jako *Äist* sektory z disku (vÅ¡ech 2352 bajtů na sektor). Můžete také míst toho použít pÅ™eformátovaná videa, která jsou zmínÄ›na níže, ale to nebude fungovat pro vÅ¡echny videa v Broken Sword II. Pro více informací si prohlédnÄ›te:
- http://wiki.scummvm.org/index.php/HOWTO-PlayStation_Videos
+ <http://wiki.scummvm.org/index.php/HOWTO-PlayStation_Videos>
Některá vydání hry, a také verze pro PlayStation, Smacker videa nemají. Revolution Software nám laskavě dovolilo poskytovat přeformátovaná videa ke stažení na naší stránce:
- http://www.scummvm.org/downloads.php
+ <http://www.scummvm.org/downloads.php>
Tato videa jsou poskytována ve formátu DXA se zvukem ve formátu FLAC. Jejich kvalita se rovná originálu díky použití bezztrátové komprese. Zobrazení těchto videí vyžaduje, aby verze ScummVM byla sestavena s podporou FLAC i zlib.
@@ -519,7 +585,7 @@ Pro systémy, které jsou příliš pomalé, aby zvládli dekódovat formát FLA
Pro Broken Sword také poskytujeme přídavek pro titulky. JednoduÅ¡e ho rozbalte a následujte pokyny v souboru readme.txt. BalíÄek v souÄasnosti nefunguje ve videích na PlayStation. (Broken Sword II již titulky má; není tÅ™eba další práce pro jejich pÅ™idání.)
-3.8.2) Videa her Broken Sword ve zpětném pohledu:
+3.6.4) Videa her Broken Sword ve zpětném pohledu:
------ ------------------------------------------
Původní vydání her Broken Sword používalo formát Smackerâ„¢ od RAD Game Tools. Protože spoleÄnost RAD nebyla ochotna nám otevřít starší zastaralé verze tohoto formátu a požádala, abychom neprovádÄ›li jeho zpÄ›tnou analýzu, museli jsme nalézt jiné Å™eÅ¡ení.
@@ -531,49 +597,59 @@ Ve ScummVM 0.6.0 jsme používali MPEG, což zajistilo rozumný kompromis mezi v
Nakonec na zaÄátku roku 2006 byl formát Smacker zpÄ›tnÄ› analyzován pro projekt FFmpeg. Díky jejich tvrdé práci ScummVM 1.0.0 nyní podporuje původní videa. Zároveň byla ukonÄena podpora MPEG. Z technického hlediska je toto dobÅ™e, protože pÅ™ehrávání videí MPEG bylo velmi složité a stejnÄ› nevypadaly tak dobÅ™e jako verze ve formátu DXA a Smacker.
-3.8.3) Broken Sword:
------- -------------
-Pro tuto hru budete potřebovat všechny soubory ze seskupení složek na obou CD. Pro verze Windows a Macintosh budete také potřebovat soubory speech.clu ze složek speech, ale protože soubory nejsou stejné, budete je muset přejmenovat na speech1.clu a speech2.clu z CD 1 a 2 v tomto pořadí. Verze na PlayStation vyžaduje speech.tab, speech.dat, speech.lis, a speech.inf.
+3.7) Poznámky k Day of the Tentacle:
+---- -------------------------------
-Dále verze pro Windows a Macintosh vyžadují podsložku music se vÅ¡emi soubory z podsložek music na obou CD. NÄ›které z tÄ›chto souborů se objevují na obou CD, ale v tÄ›chto případech jsou buÄ stejné, nebo, v jednom případÄ›, je téměř stejný, že to nemá žádný význam. Verze pro PlayStation vYžaduje tunes.dat a tunes.tab.
+Na jednom místÄ› ve hÅ™e narazíte na poÄítaÄ umožňující si zahrát původní Maniac Mansion jako bonus. ScummVM toto podporuje, ale je tÅ™eba upozornit na pár vÄ›cí:
+ScummVM prohledá váš soubor s nastavením hledajíc hru nacházející se v podsložce 'Maniac' ve složce hry Day of the Tentacle. Pokud jste zkopírovali datové soubory z CD verze, tato struktura by již měla být
+vytvořena, navíc ale budete muset hru přidat také do ScummVM.
-3.8.4) Broken Sword II:
------- ----------------
-Pro tuto hru budete potřebovat všechny soubory ze seskupení složek na obou CD. (Abych pravdu řekl, pár z nich nemusí být nezbytně nutné, ale ty, o kterých nemám jistotu, jsou velmi malé.)
-Je také třeba přejmenovat soubory speech.clu a music.clu na speech1.clu,
-speech2.clu, music1.clu a music2.clu, aby ScummVM mohl zjistit, které jsou z CD 1 a které z CD 2. Všechny ostatní soubory, které jsou umístěny v seskupení složek, jsou stejné. Použijte kterékoli soubory chcete.
+Pro návrat do Day of the Tentacle, stisknÄ›te F5 a zvolte "Návrat do spouÅ¡tÄ›Äe".
-Kromě toho budete potřebovat soubory cd.inf a, případně, startup.inf ze složky sword2 na CD 1.
+Teoreticky toto znamená, že je možné spustit jakoukoli hru jako bonus. Vskutku tomu tak je. Existuje "tajná" volba nastavení, "easter_egg", která mÄ›ní ID spouÅ¡tÄ›né hry. BuÄte ale opatrní, protože ne vÅ¡echny hry podporují
+návrat do spouÅ¡tÄ›Äe, a nedoporuÄuje se nastavovat spuÅ¡tÄ›ní samotné hry Day of the Tentacle jako bonus.
-3.9) Poznámky k Beneath a Steel Sky:
----- -------------------------------
-Od ScummVM 0.8.0 potÅ™ebujete dodateÄný soubor 'SKY.CPT', abyste mohli Beneath a Steel Sky spustit.
+3.8) Poznámky k Discworld II:
+---- ------------------------
-Tento soubor je dostupný na stránce 'Downloads' domovské stránky ScummVM.
-Můžete ho umístit buÄ do složky obsahující ostatní datové soubory (SKY.DNR, SKY.DSK), na VaÅ¡i dodateÄnou cestu, nebo do složky. Kde se nachází spouÅ¡tÄ›cí soubor ScummVM.
+Pro tuto hru potřebujete všechny soubory z podsložky DW2 na obou CD.
+Dále je třeba zkopírovat soubor SAMPLE.BNK.
+
+Je třeba přejmenovat soubory ENGLISH.SMP, ENGLISH.IDX a ENGLISH.TXT na CD1 na ENGLISH1.SMP, ENGLISH1.IDX a ENGLISH1.txt.
+To samé provést se soubory z CD2 a přejmenovat je na ENGLISH2.SMP, ENGLISH2.IDX a ENGLISH2.TXT.
+
+
+3.9) Poznámky k DraÄí Historie:
+---- --------------------------
+Existují 4 jazykové varianty této hry: Äeská, anglická, polská a nÄ›mecká. Každá je umístÄ›na v oddÄ›leném archivu. Jediná oficiální verze je Äeská, a anglická, polská a nÄ›mecká byly vždycky nedokonÄené práce a nikdy nebyly oficiálnÄ› vydány. I když texty byly zcela pÅ™eloženy, je známo, že nÄ›které z nich obsahují pÅ™eklepy.
+
+Pro tuto hru existuje nepovinný Äeský dabing. Z důvodu velikosti si ho můžete dodateÄnÄ› stáhnout a pak ho rozbalit do adresáře hry. Můžete také Äeský dabing poslouchat se vÅ¡emi jazykovými varianty hry, zatímco Ätete titulky.
+
+Všechny herní soubory a návody můžou být staženy z:
+
+<http://www.ucw.cz/draci-historie/index-en.html>
3.10) Poznámky k Flight of the Amazon Queen:
----- --------------------------------------
-Abyste mohli použít tu verzi, která není volně šiřitelná
-(z původního CD), musíte mít soubor 'queen.tbl'
-(dostupný ze stránky 'Downloads' naší domovské stránky) a umístit ho buÄ do složky obsahující soubor hry 'queen.1', na VaÅ¡i dodateÄnou cestu, nebo do složky. Kde se nachází spouÅ¡tÄ›cí soubor ScummVM.
+----- --------------------------------------
+Abyste mohli použít tu verzi, která není volnÄ› Å¡iÅ™itelná (z původního CD), musíte mít soubor 'queen.tbl' (dostupný ze stránky 'Downloads' naší domovské stránky) a umístit ho buÄ do složky obsahující soubor hry 'queen.1',
+na VaÅ¡i dodateÄnou cestu, nebo do složky. Kde se nachází spouÅ¡tÄ›cí soubor ScummVM.
Také můžete použít nástroj 'compress_queen' z balíÄku nástrojů pro 'znovu sestavení' VaÅ¡eho datového souboru FOTAQ pro zahrnutí tabulky pro tuto konkrétní verzi, Äímž odstraníte závislost na soubor 'queen.tbl' pÅ™i spuÅ¡tÄ›ní. Tento nástroj Vám také umožňuje komprimovat Å™eÄ a zvukové efekty do formátu MP3, OGG nebo FLAC.
3.11) Poznámky ke Gobliiins:
----- ----------------------
-CD verze série Gobliiins obsahuje jednu velkou zvukovou stopu, kterou potÅ™ebujete vyjmout (viz oddíl o použití komprimovaných zvukových souborů) a zkopírovat ji do herní složky, pokud chcete ve hÅ™e hudbu, aniž byste museli CD mít stále v jednotce. V této stopÄ› jsou také Å™eÄ a její hlasitost se tedy také mÄ›ní podle hlasitosti hudby.
+CD verze série Gobliiins obsahuje jednu velkou zvukovou stopu, kterou je tÅ™eba vyjmout (viz oddíl o použití komprimovaných zvukových souborů) a zkopírovat ji do herní složky, pokud chcete ve hÅ™e hudbu, aniž byste museli CD mít stále v jednotce. V této stopÄ› je také Å™eÄ a její hlasitost se tedy také mÄ›ní podle hlasitosti hudby.
3.12) Poznámky k Inherit the Earth: Quest for the Orb:
----- ------------------------------------------------
Abyste mohli spustit verzi pro Mac OS X od Wyrmkeep musíte data zkopírovat z CD na Váš pevný disk. Pokud používáte PC, pak se podívejte na:
- http://wiki.scummvm.org/index.php/HOWTO-Mac_Games
+ <http://wiki.scummvm.org/index.php/HOWTO-Mac_Games>
I když se v tomto Älánku píše hlavnÄ› o hrách SCUMM, je zde také zmínÄ›n nástroj "HFVExplorer", který potÅ™ebujete k extrakci souborů. Nezapomeňte, že data Å™eÄi "Inherit the Earth Voices" musíte umístit do stejného adresáře, kde jsou uložena data hry:
@@ -582,13 +658,64 @@ I když se v tomto Älánku píše hlavnÄ› o hrách SCUMM, je zde také zmínÄ›
Ve staré verzi pro Mac OS 9 potřebujete soubory zkopírovat ve formátu MacBinary, protože by měli obsahovat jak zdrojové, tak datové vidlice. Zkopírujte všechny soubory 'ITE *'.
-3.13) Poznámky k Simon the Sorcerer 1 a 2:
+3.13) Poznámky ke Maniac Mansion na Apple II/NES:
+----- -------------------------------------------
+Apple II:
+Je třeba přejmenovat obraz disku 1 na maniac1.dsk
+Je třeba přejmenovat obraz disku 2 na maniac2.dsk
+
+NES:
+Podporované verze jsou Britská angliÄtina (E), FrancouzÅ¡tina (F), NÄ›mÄina (G), ItalÅ¡tina (I), Å védÅ¡tina (SW) a Americká angliÄtina (U). ScummVM pro spuÅ¡tÄ›ní vyžaduje pouze Äást PRG a ne celý ROM.
+
+Abyste mohli hru spustit, musíte vyjmout prvních 16 bajtů z ROM, s kterým pracujete. Jakýkoli hex editor bude fungovat, pokud můžete kopírovat/vkládat. Poté. Co ROM otevÅ™ete pomocí hex editoru, zkopírujte vÅ¡echno z druhého řádku (17. bajt) na konec. Poté, co toto provedete, vložte ho do nového hex souboru. Pojmenujte ho "Maniac Mansion (XX).prg" kde XX znamená verzi, se kterou pracujete (E, F, G, I, SW, nebo U). KoneÄná velikost by mÄ›la být pÅ™esnÄ› 262144 bajtů.
+
+Pokud hru pÅ™idáváte ruÄnÄ›, ujistÄ›te se, že platforma je nastavena na NES.
+
+Nejběžnější chyby, které zabraňují spuštění hry:
+
+ * Špatný soubor
+ * ROM byl extrahován pomocí nástrojů z verze 0.7.0
+ * Snažíte se do ScummVM vkládat CELà ROM a ne jenom PRG Äást.
+
+Je také možno extrahovat oddÄ›lené soubory LFL z PRG Äásti. Pro toto použijte nástroj 'extract_mm_nes' z balíÄku nástrojů.
+
+
+3.14) Poznámky k Mickey's Space Adventure:
+----- ------------------------------------
+Abyste mohli Mickey's Space Adventure hrát ve ScummVM, potÅ™ebujete spolu s datovými soubory hry také původní spouÅ¡tÄ›Ä (mickey.exe).
+
+Pro tuto hru ve ScummVM, existuje rozšířená podpora myÅ¡i, i když v původní hÅ™e takováto podpora nebyla. Položky menu mohou být vybrány pomocí myÅ¡i a je také možné se myší pÅ™esunout do jiných míst. Když se kurzor myÅ¡i nachází na okraji obrazovky, zÄervená, pokud je možné jít v tomto smÄ›ru. HrÃ¡Ä pak může jednoduÅ¡e kliknout na okraje herní obrazovky pro zmÄ›nu místa, podobnÄ› jako mnoho adventur, což je jednodušší a přímoÄaÅ™ejší než pohyb pomocí menu.
+
+
+3.15) Nippon Safes Inc. Amiga notes:
+----- ------------------------------
+Pro tuto hru potřebujete disk0, soubory global.table a pointer a it (en, fr, ge pro mezinárodní verzi).
+
+Dále je třeba přejmenovat obraz disku 2 na disk1, obraz disku 3 na disk2, obraz disku 4 na disk3 a obraz disku 5 na disk4.
+
+
+3.16) Poznámky k Simon the Sorcerer 1 a 2:
----- ------------------------------------
Pokud máte dvojitou verzi Simon the Sorcerer 1 nebo 2 na CD, verzi pro Windows naleznete v hlavní složce na CD a verzi pro DOS ve složce DOS na CD.
-3.14) Poznámky k The Feeble Files:
+3.17) Poznámky k The Curse of Monkey Island:
+----- --------------------------------------
+Pro tuto hru budete potřebovat soubory comi.la0, comi.la1 a comi.la2.
+Soubor comi.la0 můžete nalézt na všech CD hry, ale protože jsou stejné, můžete použít kterýkoli z nich.
+
+Dále potřebujete vytvořit podsložku "resource" obsahující všechny soubory z –obou- podsložek "resource" na dvou CD. Některé soubory se objevují na obou CD, ale znovu jsou stejné.
+
+
+3.18) Poznámky k The Feeble Files:
----- ----------------------------
+Amiga/Macintosh:
+Musíte nainstalovat malý balíÄek videí, které chybí v obou tÄ›chto verzích této hry. Jmenuje se "The Feeble Files - Omni TV and epilogue cutscenes for the Amiga and Macintosh versions"
+a lze ho získat zde:
+
+ <http://www.scummvm.org/games/#feeble>
+
+Windows:
Pokud máte verzi pro Windows, je třeba si uvědomit pár věcí.
Mnoho souborů, které hra vyžaduje, je uloženo v souboru InstallShield s názvem data1.cab, který ScummVM nemůže rozbalit. Budete muset použít původní instalátor, nebo i5comp pro rozbalení obsahu tohoto souboru. Nástroj pro dekomprimaci i5comp může být nalezen při hledání na internetu.
@@ -599,7 +726,7 @@ Přejmenovat voices.wav na CD2 na voices2.wav
Přejmenovat voices.wav na CD3 na voices3.wav
Přejmenovat voices.wav na CD4 na voices4.wav
-3.15) Poznámky k The Legend of Kyrandia:
+3.19) Poznámky k The Legend of Kyrandia:
----- ----------------------------------
Abyste mohli spustit The Legend of Kyrandia ve ScummVM potřebujete soubor 'kyra.dat'.
Soubor by mÄ›l být vždycky souÄástí oficiálních balíÄků ScummVM. V případÄ›, že ScummVM
@@ -607,7 +734,20 @@ nahlásí, že soubor chybí, můžete ho najít na stránce ScummVM v sekci 'Do
Nezapomeňte, že souÄasná verze ScummVM pro Windows by mÄ›la soubor obsahovat ve spouÅ¡tÄ›Äi a tudíž ho
musíte mít pouze, když ScummVM soubor nemůže nalézt.
-3.16) Poznámky k Předvídavému Vstupnímu Dialogu her Sierra AGI:
+
+3.20) Poznámky k Troll's Tale:
+----- ------------------------
+Původní hra vycházela na zaváděcím disku PC, proto je nutné vypsat obsah tohoto disku jako obraz disku a přejmenovat ho na "troll.img", abyste tuho hru mohli hrát ve ScummVM.
+
+
+3.21) Winnie the Pooh notes:
+----- ----------------------
+Je možné importovat uložené hry z původní hry do ScummVM.
+
+Pro tuto hru ve ScummVM, existuje rozšířená podpora myÅ¡i, i když v původní hÅ™e takováto podpora nebyla. Položky menu mohou být vybrány pomocí myÅ¡i a je také možné se myší pÅ™esunout do jiných míst. Když se kurzor myÅ¡i nachází na okraji obrazovky, zÄervená, pokud je možné jít v tomto smÄ›ru. HrÃ¡Ä pak může jednoduÅ¡e kliknout na okraje herní obrazovky pro zmÄ›nu místa, podobnÄ› jako mnoho adventur, což je jednodušší a přímoÄaÅ™ejší než pohyb pomocí menu.
+
+
+3.22) Poznámky k Předvídavému Vstupnímu Dialogu her Sierra AGI:
----- ---------------------------------------------------------
Předvídavý Vstupní Dialog je pomůcka ScummVM pro spouštění her používající jádro AGI (který je znám, že vyžaduje vstup z příkazové řádky) na zařízeních s omezenou podporou klávesnice. V těchto situacích, kdy zadávání pomocí emulované klávesnice je dosti únavné, můžou být příkazy rychle a snadno zadány pomocí Předvídavého Vstupního Dialogu.
@@ -615,48 +755,19 @@ Abyste zapnuli předvídavý vstup v hrách AGI, potřebujete zkopírovat soubor
Pokud je slovník zjiÅ¡tÄ›n, je PÅ™edvídavý Vstupní Dialog zobrazen buÄ pÅ™i kliknutí na oblast příkazového řádku (kdykoliv je požadován vstup klávesnice, i v rámeÄcích dialogových oken), nebo v nÄ›kterých verzích pro jiné systémy stisknutím urÄené klávesové zkratky.
-PÅ™edvídavý Vstupní Dialog pracuje ve tÅ™ech režimech, které jsou pÅ™epínány tlaÄítkem (*)Pre/123/Abc. Hlavní vstupní metodou je pÅ™edvídavý režim
-(Pre), který připomíná "rychlé zadávání" v mobilních telefonech.
+PÅ™edvídavý Vstupní Dialog pracuje ve tÅ™ech režimech, které jsou pÅ™epínány tlaÄítkem (*)Pre/123/Abc. Hlavní vstupní metodou je pÅ™edvídavý režim
+(Pre), který připomíná "rychlé zadávání" v mobilních telefonech.
Abeceda je rozdÄ›lena do 9 sad, které pÅ™irozenÄ› odpovídají 9 klávesám Äíselné klávesnice (0 je mezera). Pro psaní slova zmáÄknÄ›te jednou Äíslo sady, která obsahuje písmeno slova, které chcete napsat, pak pokraÄujete k dalšímu. Například, pokud chcete napsat příkaz 'look', mÄ›li byste zmáÄknout 5665. Jak postupnÄ› píšete Äíselný kód zamýšleného slova, je slovník prohledáván pro známá slova, která se shodují s Vaším vstupem až do tohoto bodu. Jak maÄkáte více kláves, slovník se pÅ™iblíží ke správnému slovu. To je důvod, proÄ vypsané slovo se může náhle zmÄ›nit mezi stisky kláves. NÄ›kdy se ale vyskytnou případy, kdy více než jedno slovo má stejné Äíselné zastoupení. Například slova 'quit' a 'suit' odpovídají stejným Äíslům, a to 7848. V tÄ›chto případech se rozsvítí tlaÄítko další
(#). Jeho stisknutím můžete procházet seznam slov, která sdílejí stejný kód a nakonec pÅ™ijmout to správné stisknutím (0)mezera nebo tlaÄítka Ok.
Druhou vstupní metodou (123) je Äíselný vstup: Každou klávesu, kterou stisknÄ›te, je doslova zadána jako Äíslo.
-
+
TÅ™etí vstupní metodou (Abc) je vstupní režim Alfa/opakovaného stisknutí tlaÄítka. Tento režim je urÄen pro zadávání textu bez pomoci od slovníku pÅ™edvídavého režimu (Pre). Text je zadáván po jednotlivých písmenech. Pro každé písmeno nejdříve stisknÄ›te Äíslo sady, které obsahuje písmeno, které chcete, pak použijte tlaÄítko další (#) pro procházení písmeny a opakujte s dalším Äíslem. Například, pro zadání slova 'look' musíte stisknout následující: 5##6##6##5#
Dialogové okno je plnÄ› použitelné pomocí myÅ¡i, ale v nÄ›kterých verzích ScummVM pro jiné platformy, je použití dialogu pohodlnÄ›jší pomocí Äíselné klávesnice. NÄ›která tlaÄítka dialogu mohou být také používána pomocí Å¡ipkových kláves a enter.
-3.17) Poznámky k Mickey's Space Adventure:
------ ------------------------------------
-Abyste mohli Mickey's Space Adventure hrát ve ScummVM, potÅ™ebujete spolu s datovými soubory hry také původní spouÅ¡tÄ›Ä (mickey.exe).
-
-Pro tuto hru ve ScummVM, existuje rozšířená podpora myÅ¡i, i když v původní hÅ™e takováto podpora nebyla. Položky menu mohou být vybrány pomocí myÅ¡i a je také možné se myší pÅ™esunout do jiných míst. Když se kurzor myÅ¡i nachází na okraji obrazovky, zÄervená, pokud je možné jít v tomto smÄ›ru. HrÃ¡Ä pak může jednoduÅ¡e kliknout na okraje herní obrazovky pro zmÄ›nu místa, podobnÄ› jako mnoho adventur, což je jednodušší a přímoÄaÅ™ejší než pohyb pomocí menu.
-
-
-3.18) Winnie the Pooh notes:
------ ----------------------
-Je možné importovat uložené hry z původní hry do ScummVM.
-
-Pro tuto hru ve ScummVM, existuje rozšířená podpora myÅ¡i, i když v původní hÅ™e takováto podpora nebyla. Položky menu mohou být vybrány pomocí myÅ¡i a je také možné se myší pÅ™esunout do jiných míst. Když se kurzor myÅ¡i nachází na okraji obrazovky, zÄervená, pokud je možné jít v tomto smÄ›ru. HrÃ¡Ä pak může jednoduÅ¡e kliknout na okraje herní obrazovky pro zmÄ›nu místa, podobnÄ› jako mnoho adventur, což je jednodušší a přímoÄaÅ™ejší než pohyb pomocí menu.
-
-
-3.19) Poznámky k Troll's Tale:
------ ------------------------
-Původní hra vycházela na zaváděcím disku PC, proto je nutné vypsat obsah tohoto disku jako obraz disku a přejmenovat ho na "troll.img", abyste tuho hru mohli hrát ve ScummVM.
-
-
-3.20) Poznámky k DraÄí Historie:
------ --------------------------
-Existují 4 jazykové varianty této hry: Äeská, anglická, polská a
-nÄ›mecká. Každá je umístÄ›na v oddÄ›leném archivu. Jediná oficiální verze je Äeská, a anglická, polská a nÄ›mecká byly vždycky nedokonÄené práce a nikdy nebyly oficiálnÄ› vydány. I když texty byly zcela pÅ™eloženy, je známo, že nÄ›které z nich obsahují pÅ™eklepy.
-
-Pro tuto hru existuje nepovinný Äeský dabing. Z důvodu velikosti si ho můžete dodateÄnÄ› stáhnout a pak ho rozbalit do adresáře hry. Můžete také Äeský dabing poslouchat se vÅ¡emi jazykovými varianty hry, zatímco Ätete titulky.
-
-Všechny herní soubory a návody můžou být staženy z
-http://www.ucw.cz/draci-historie/index-en.html
-
-3.21) Titulky a hlasy souběžně v hrách Sierra SCI:
+3.23) Titulky a hlasy souběžně v hrách Sierra SCI:
----- --------------------------------------------
UrÄité CD verze her Sierra SCI mají textová i hlasová data.
Některé z nich mají volbu pro přepínání mezi nimi, ale existují případy
@@ -674,7 +785,7 @@ Hry na CD, kde zvuk i titulky lze zobrazit souÄasnÄ›:
Space Quest 4 CD
EcoQuest 1 CD:
- Hlas i text lze zapnout pomocí volby "Mode" v okně nastavení,
+ Hlas i text lze zapnout pomocí volby "Mode" v okně nastavení,
nebo přes nastavení zvuku ScummVM.
Freddy Pharkas CD:
@@ -684,84 +795,136 @@ Freddy Pharkas CD:
King's Quest 6 CD
Hlas i text lze zapnout pomocí volby "Mode" v okně nastavení (kde je ve
- ScummVM pÅ™idána dodateÄná volba "Dual"), nebo pomocí nastavení
+ ScummVM pÅ™idána dodateÄná volba "Dual"), nebo pomocí nastavení
zvuku ve ScummVM.
Laura Bow 2 CD
Hlas i text lze zapnout pomocí volby "Mode" v okně nastavení (kde je ve
- ScummVM pÅ™idána dodateÄná volba "Dual"), nebo pomocí nastavení
+ ScummVM pÅ™idána dodateÄná volba "Dual"), nebo pomocí nastavení
zvuku ve ScummVM.
Leisure Suit Larry 6 CD
Ve hÅ™e lze povolit buÄ hlas, nebo hlas a text. Neexistuje možnost pro
- povolení textu. Pouze nastavení zvuku ve ScummVM lze použít pro
+ povolení textu. Pouze nastavení zvuku ve ScummVM lze použít pro
zobrazení jen titulků.
Space Quest 4 CD:
Hlas a text lze povolit pomocí tlaÄítka "Display Mode" v
nastavení hry, nebo pomocí nastavení zvuku ve ScummVM.
-
-3.22) Známé Problémy:
------ ---------------
-Toto vydání má následující známé problémy. Není tÅ™eba je ohlaÅ¡ovat, i když záplaty pro jejich opravu jsou vítány. Pokud objevíte chybu, která není zde v seznamu, ani není v seznamu kompatibility na internetové stránce, prohlédnÄ›te si, prosím, Äást o hlášení chyb.
-
- Hry CD Audio:
- - Při hraní her, které používají CD Audio (hry FM-TOWNS, Loom CD, atd) může u uživatelů Microsoft Windows 2000/XP docházet k náhodným pádům. To je díky dlouhotrvající chybě Windows, která má za následek poškozené soubory
- pÅ™i Ätení z CD. Abyste se tomuto vyhnuli, zkopírujte, prosím, soubory na pevný disk
-
- Verze FM-TOWNS:
- - Verze Kandži vyžaduje ROM písma FM-TOWNS
-
- Loom:
- - Vypnutí titulků pomocí souboru nastavení je nevypne spolehlivě, protože skripty Loom je znovu automaticky zapnou
- - Podpora MIDI ve verzi EGA vyžaduje aktualizaci Roland LucasArts
- - Verze Kandži na PC-Engine vyžaduje rom systémové karty
-
- The Secret of Monkey Island:
- - Podpora MIDI ve verzi EGA vyžaduje aktualizaci Roland LucasArts
- Beneath a Steel Sky:
- - Verze pro Amiga nejsou podporovány
- - Demoverze z diskety nejsou podporovány
- - Není chyba: Ve verzi na CD chybí v jistých dialozích Å™eÄ, to je normální.
-
- Elvira - Mistress of the Dark
- - Ve verzi pro Atari ST nefunguje hudba
-
- Elvira II - The Jaws of Cerberus
- - Ve verzi pro Atari ST nefunguje hudba
- - Ve verzi pro PC nefungují zvukové efekty
- - Ve verzi pro Atari ST jsou problémy s paletou
+3.24) Poznámky ke hrám Zork:
+----- ----------------------
+Pro spuÅ¡tÄ›ní podporovaných her Zork (Zork Nemesis: The Forbidden Lands a Zork: Grand Inquisitor) musíte zkopírovat nÄ›která (dodateÄná) data do odpovídajících umístÄ›ní.
+
+Zork Nemesis: The Forbidden Lands
+
+VÅ¡echny verze
+
+StáhnÄ›te si balíÄek písem Liberation(tm)
+<https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
+a rozbalte vÅ¡echny soubory ttf do vaší dodateÄné složky ScummVM.
+Nebo si stáhnÄ›te balíÄek GNU FreeFont TTF
+<https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip> a umístÄ›te vÅ¡echny soubory ttf z adresáře sfd do dodateÄné složky ScummVM, i když je tÅ™eba říci, že v souÄasné dobÄ›
+mají některá tato písma potíže při vykreslování.
+Stáhněte si opravu pro titulky
+<http://www.thezorklibrary.com/installguides/znpatch.zip> a rozbalte adresář addon přímo do kořenového adresáře hry
+
+Verze z GoG
+
+Použijte instalátor GoG, žádných dalších kroků není třeba
+
+Verze z CD
+
+Zkopírujte následující z adresáře nemesis na CD1 do kořenového adresáře hry:
+Adresář znemmx
+Adresář znemscr
+nemesis.str
+Z CD1 zkopírujte adresář zassets do kořenového adresáře hry
+Z CD2 zkopírujte adresář zassets do koÅ™enového adresáře hry a nahraÄte vÅ¡echny soubory
+Z CD3 zkopírujte adresář zassets do koÅ™enového adresáře hry a nahraÄte vÅ¡echny soubory
+
+Verze z DVD
+
+Zkopírujte následující z adresáře nemesis do kořenového adresáře hry:
+Adresář znemmx
+Adresář znemscr
+nemesis.str
+Poznámka: Je třeba také přesunout cursor.zfs z adresáře zassets/global do adresáře znemscr
+Zkopírujte adresář disc2 do kořenového adresáře hry
+Zkopírujte adresář disc3 do kořenového adresáře hry
+Zkopírujte adresář zassets do kořenového adresáře hry
+
+
+Zork: Grand Inquisitor
+
+VÅ¡echny verze
+
+StáhnÄ›te si balíÄek písem Liberation(tm)
+<https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
+a rozbalte vÅ¡echny soubory ttf do vaší dodateÄné složky ScummVM.
+Nebo si stáhnÄ›te balíÄek GNU FreeFont TTF
+<https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip> a umístÄ›te vÅ¡echny soubory ttf z adresáře sfd do dodateÄné složky ScummVM, i když je tÅ™eba říci, že v souÄasné dobÄ›
+mají některá tato písma potíže při vykreslování.
+
+Verze z GoG
+
+Použijte instalátor GoG, žádných dalších kroků není třeba
+
+Verze z CD
+
+Zkopírujte následující z adresáře zgi na CD1 do kořenového adresáře hry:
+Adresář zgi_mx
+cursor.zfs
+death.zfs
+inquis.str
+inquis.zix
+r.svr
+scripts.zfs
+subtitle.zfs
+Z CD1 zkopírujte adresář zassets1 do kořenového adresáře hry
+Z CD2 zkopírujte adresář zassets2 do kořenového adresáře hry
+DoporuÄujeme V8m nainstalovat záplatu 1.2
+<http://www.thezorklibrary.com/installguides/Zpatch.exe>,
+ale je možné že pro to budete muset hru nainstalovat normálním způsobem, protože záplata má vlastní instalátor.
+
+Verze z DVD
+
+Zkopírujte následující z adresáře zgi_e do kořenového adresáře hry:
+Adresář addon (oprava hry 1.2)
+Adresář zgi_mx
+cursor.zfs
+death.zfs
+inquis.str
+inquis.zix
+r.svr
+scripts.zfs
+subtitle.zfs
+Zkopírujte adresář eng_mpeg (video soubory MPEG2 ve vysokém rozlišení) do kořenového adresáře hry
+Zkopírujte adresář zassetsc do kořenového adresáře hry
+Zkopírujte adresář zassetse do kořenového adresáře hry
+
+
+3.25) Poznámky ke hrám Commodore64:
+----- -----------------------------
+Jak Maniac Mansion tak Zak McKracken mohou být spuštěny, ale Maniac Mansion není ještě hratelný. Jednoduše pojmenujte disky D64 jako
+"maniac1.d64" a "maniac2.d64" nebo "zak1.d64" a "zak2.d64", pak by měl ScummVM automaticky hru zjistit, pokud ho odkážete na správnou složku.
- Inherit the Earth: Quest for the Orb
- - Verze pro Amiga nejsou podporovány
+Nebo můžete použít 'extract_mm_c64' z balíÄku nástrojů pro extrahování datových souborů. Pak ale ScummVM hru řádnÄ› automaticky nezjistí ScummVM, a musíte se ujistit, že platforma je nastavena na Commodore64. DoporuÄujeme použít mnohem jednodušší postup popsaný v pÅ™edchozím odstavci.
- Lure of the Temptress
- - Žádná podpora Roland MT-32
- - Podpora zvuku není dokonÄena a nezní jako v původní hÅ™e
- Simon the Sorcerer 1:
- - V anglických a německých verzích na CD nejsou titulky dostupné, protože jim většina titulků chybí.
+3.26) Poznámky ke hrám Macintosh:
+----- ---------------------------
+VÅ¡echny adventury LucasArts založené na SCUMM, kromÄ› COMI, také existují ve verzích pro in Macintosh. ScummVM může vÄ›tÅ¡inu (vÅ¡echny?) použít, nicménÄ›, v nÄ›kterých případech je nutná dodateÄná práce. Nejdříve, pokud pro toto nepoužíváte Macintosh, přístup k datům na CD/disketÄ› může být obtížný. Důvodem je to, že Mac používá zvláštní formát disku nazvaný HFS, který ostatní systémy vÄ›tÅ¡inou nepodporují. NicménÄ› existuje, nÄ›kolik nástrojů, které jsou zadarmo a umožňují Äíst takovéto svazky HFS. Například "HFVExplorer" pro Windows a "hfsutils" pro Linux a ostatní Unixové operaÄní systémy.
- Simon the Sorcerer 2:
- - Kombinace Å™eÄi a titulků Äasto způsobí, že Å™eÄ je pÅ™eruÅ¡ena brzo, toto je omezení původní hry.
- - Ve verzích pro Amiga a Macintosh je podporován pouze výchozí jazyk datových souborů (angliÄtina).
+VÄ›tÅ¡ina novÄ›jších her na Macintosh je dodávána pouze s jedním datovým souborem (v nÄ›kterých případech byl tento soubor uÄinÄ›n neviditelným, takže možná budete potÅ™ebovat dodateÄné nástroje, abyste ho mohli zkopírovat). ScummVM je schopen takovýto soubor použít přímo; jednoduÅ¡e odkažte ScummVM na složku obsahující tento soubor a mÄ›lo by to fungovat (tak jako s každou podporovanou hrou).
- Simon the Sorcerer's Puzzle Pack:
- - Žádná podpora pro zobrazování, zadávání, ukládání, Äi naÄítání nejvyšších skóre.
- - Žádná podpora pro zobrazování názvů položek, když na ně najedete myší ve Swampy Adventures.
+V balíÄku nástrojů také poskytujeme nástroj nazvaný 'extract_scumm_mac', který extrahuje data z tÄ›chto datových souborů, ale toto není ani potÅ™eba, ani doporuÄeno.
- The Feeble Files:
- - Titulky jsou Äasto nedokonÄené. V původní hÅ™e byly vždy zakázány.
+Pro další informace o kopírování herních souborů Macintosh na Váš pevný disk si prohlédněte:
- The Legend of Kyrandia:
- - Ve verzích na disketě pro Mac není žádná hudba ani zvukové efekty.
- - CD Macintosh používá zahrnutou hudbu a zvukové efekty z DOS.
+ <http://wiki.scummvm.org/index.php/HOWTO-Mac_Games>
- Hry Humongous Entertainment:
- - Pouze původní rozhraní pro uložení a naÄtení mohou být použity.
- - Žádná podpora pro hru více hráÄů nebo tisknutí obrázků
4.0) Podporované Platformy:
---- ----------------------
@@ -772,7 +935,8 @@ Podporované platformy zahrnují (mimo jiné):
UNIX (Linux, Solaris, IRIX, *BSD, ...)
Windows
- Windows CE a Windows Mobile (vÄetnÄ› Smartphonů a PocketPCs)
+ Windows CE
+ Windows Mobile (vÄetnÄ› Smartphonů a PocketPCs)
Mac OS X
AmigaOS
Android
@@ -793,7 +957,7 @@ Podporované platformy zahrnují (mimo jiné):
Verze pro Dreamcast nepodporuje The Curse of Monkey Island, ani The Dig. Verze pro Nintendo DS nepodporuje Full Throttle, The Dig, nebo The Curse of Monkey Island.
Pro další omezení v závislosti na platformě se, prosím, podívejte na naší Wiki:
- http://wiki.scummvm.org/index.php/Platforms
+ <http://wiki.scummvm.org/index.php/Platforms>
Ve verzi pro Macintosh je stisknutí pravého tlaÄítka myÅ¡i emulováno pomocí Cmd-kliknutí (to je, že stisknete tlaÄítko myÅ¡i pÅ™i držení klávesy
Command/Apple/Vrtule).
@@ -833,7 +997,7 @@ ScummVM může také hru spustit přímo pomocí argumentů příkazové řádky
-g, --gfx-mode=REŽIM Vybere režim obrazu (viz také Äást 5.3)
--gui-theme=VZHLED Vybere vzhled rozhraní (výchozí, moderní, klasický)
--themepath=CESTA Cesta kde jsou vzhledy rozhraní uloženy
- --list-themes Zobrazí seznam všech použitelných vzhledů
+ --list-themes Zobrazí seznam všech použitelných vzhledů
-e, --music-driver=REŽIM Vybere ovladaÄ hudby (viz také Äást 7.0)
--list-audio-devices Zobrazí seznam všech dostupných zvukových zařízení
-q, --language=JAZYK Vybere jazyk hry (viz také Äást 5.2)
@@ -858,7 +1022,10 @@ ScummVM může také hru spustit přímo pomocí argumentů příkazové řádky
--output-rate=FREKVENCE Výstupní vzorkovací kmitoÄet v Hz (napÅ™. 22050)
--opl-driver=OVLADAČ Vybere emulátor AdLib (OPL) (db, mame)
--aspect-ratio Povolí korekci poměru stran
- --render-mode=REŽIM Povolí dodateÄné režimy vykreslení (cga, ega, hercGreen, hercAmber, amiga)
+ --render-mode=REŽIM Povolí dodateÄné režimy vykreslení (hercGreen, hercAmber,
+ cga, ega, vga, amiga, fmtowns, pc9821, pc9801, 2gs,
+ atari, macintosh)
+
--alt-intro Použije alternativní intro pro CD verze Beneath a Steel Sky a Flight of the Amazon Queen
--copy-protection Povolí ochranu proti kopírování v hrách, když ji ScummVM standardně zakazuje.
--talkspeed=ÄŒÃSLO Nastaví zdržení mluvení v hrách SCUMM, nebo rychlost mluvení v jiných hrách (výchozí: 60)
@@ -1018,12 +1185,12 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
Ctrl-F5 - Zobrazí Globální Menu
Cmd-q - UkonÄit (Mac OS X)
Ctrl-q - UkonÄit (další unixy vÄetnÄ› Linux)
- Ctrl-z NEBO Alt-x - UkonÄit (další platformy)
+ Ctrl-z - UkonÄit (další platformy)
Ctrl-u - Zeslabí všechny zvuky
Ctrl-m - Přepínat zachycení myši
Ctrl-Alt 1-8 - Přepínat mezi grafickými filtry
Ctrl-Alt + a - - Zvětšit/Zmenšit faktor zvětšení
- Ctrl-Alt a - Přepínat korekci poměru stran. Většina her používá rozlišení 320x200 pixelů, což může na většině novějších monitorů vypadat splácle. Korekce poměru stran obraz roztáhne, aby místo toho použil
+ Ctrl-Alt a - Přepínat korekci poměru stran. Většina her používá rozlišení 320x200 pixelů, což může na většině novějších monitorů vypadat splácle. Korekce poměru stran obraz roztáhne, aby místo toho použil
320x240, nebo jeho násobky
Alt-Enter - Přepíná celou obrazovku/do okna
Alt-s - Vytvořit snímek obrazovky (pouze jádro SDL)
@@ -1032,6 +1199,7 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
prostÅ™edního tlaÄítka nebo koleÄka myÅ¡i.
SCUMM:
+ Alt-x - UkonÄit
Ctrl 0-9 a Alt 0-9 - Nahrát a uložit stav hry
Ctrl-d - Spustit ladění
Ctrl-f - Zapnout rychlý režim
@@ -1058,12 +1226,12 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
TeÄka (.) - PÅ™eskoÄí souÄasný řádek textu
Broken Sword:
- F5 nebo Escape - Zobrazí rámeÄek pro uložení/naÄtení
+ F5 nebo Escape - Zobrazí rámeÄek pro uložení/naÄtení
Broken Sword II:
Ctrl-d - Spustit ladění
Ctrl-f - Zapnout rychlý režim
- p - Pozastavení
+ p - Pozastavení
DraÄí Historie:
F5 - Zobrazí Globální Menu
@@ -1084,7 +1252,7 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
Escape - PÅ™eskoÄí video
Mezerník - PÅ™eskoÄí souÄasný řádek textu
- Future Wars
+ Future Wars:
F1 - Prozkoumat
F2 - Vzít
F3 - Inventář
@@ -1095,7 +1263,7 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
F10 - Menu "Použít"
Escape - Zobrazit menu příkazů
- Nippon Safes
+ Nippon Safes:
Ctrl-d - Spustit ladění
l - NaÄíst hru
s - Uložit hru
@@ -1115,21 +1283,21 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
t - PÅ™epínat mezi Å™eÄí a kombinací Å™eÄi a titulků [Simon the Sorcerer 1 CD (jiné než angliÄtina a nÄ›mÄina) a Simon the Sorcerer 2 CD (vÅ¡echny jazyky)]
v - PÅ™epínat mezi titulky a kombinací Å™eÄi a titulků [Pouze Simon the Sorcerer 2 CD]
- Simon the Sorcerer's Puzzle Pack
+ Simon the Sorcerer's Puzzle Pack:
Ctrl-d - Spustit ladění
Ctrl-f - Zapnout rychlý režim
F12 - Zapnout/vypnout režim rychle rychlosti ve Swampy Adventures
- a + - Hlasitost hudby, snížit/zvýšit
m - Hudba vypnout/zapnout
s - Zvukové efekty zapnout/vypnout
- Pause - Pozastavení
+ Pause - Pozastavení
- The Feeble Files
+ The Feeble Files:
Ctrl-d - Spustit ladění
Ctrl-f - Zapnout rychlý režim
F7 - Vyměnit postavy
F9 - Zapnout/vypnout jména hitboxů
- s - Zvukové efekty zapnout/vypnout
+ s - Zvukové efekty zapnout/vypnout
Pause - Pozastavení
t - PÅ™epínat mezi Å™eÄí a kombinací Å™eÄi a titulků
v - PÅ™epínat mezi titulky a kombinací Å™eÄi a titulků
@@ -1143,16 +1311,16 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
F5 - Zobrazí Globální Menu
Touche: The Adventures of the Fifth Musketeer:
- Ctrl-f - Zapnout rychlý režim
+ Ctrl-f - Zapnout rychlý režim
F5 - Zobrazit možnosti
F9 - Zapnout režim rychlé chůze
- F10 - Vypnout režim rychlé chůze
+ F10 - Vypnout režim rychlé chůze
Escape - UkonÄit
Mezerník - PÅ™eskoÄí souÄasný řádek textu
t - PÅ™epnout mezi 'Pouze ŘeÄ',
'ŘeÄ a Text' a 'Pouze Text'
-
- Zork: Grand Inquisitor
+
+ Zork: Grand Inquisitor:
Ctrl-s - Uložit
Ctrl-r - NaÄíst
Ctrl-q - UkonÄit
@@ -1165,7 +1333,7 @@ ScummVM podporuje různé zkratky ve hře. Liší se mezi různými hrami SCUMM
F9 - Vyjmout minci (musíte mít měšec)
Space - PÅ™eskoÄit videa
- Zork Nemesis: The Forbidden Lands
+ Zork Nemesis: The Forbidden Lands:
Ctrl-s - Uložit
Ctrl-r - NaÄíst
Ctrl-q - UkonÄit
@@ -1182,18 +1350,24 @@ Poznámka pro uživatele WinCE: Kvůli omezenému vstupu z klávesnice ve vÄ›tÅ
Uložené hry jsou na nÄ›kterých platformách standardnÄ› umístÄ›ny do souÄasné složky a v jiných do pÅ™ednastavené složky. To můžete urÄit v souboru s nastavením pomocí parametru savepath. Podívejte se na vzorový soubor s nastavením dále v tomto souboru.
Platformy, které v souÄasnosti mají jiné výchozí složky jsou:
- Mac OS X:
+ Mac OS X:
$HOME/Documents/ScummVM Savegames/
-
+
Jiné unixy:
- $HOME/.scummvm/
-
+ Řídíme se specifikacemi základního adresáře XDG. To znamená, že nastavení lze nalézt v:
+ $XDG_DATA_HOME/scummvm/saves/
+
+ Pokud XDG_DATA_HOME není nastaven nebo je prázdný, bude, podle pravidel specifikace, použito '~/.local/share' jako hodnota pro XDG_DATA_HOME.
+
+ Pokud byla ve vašem systému nainstalována dřívější verze ScummVM, bude ponecháno původní výchozí umístění '~/.scummvm'.
+ Program toto zjistí nalezením složky '~/.scummvm'´ v cestě.
+
Windows Vista/7:
\Users\užjméno\AppData\Roaming\ScummVM\Saved games\
-
+
Windows 2000/XP:
\Documents and Settings\užjméno\Application Data\ScummVM\Saved games\
-
+
Windows NT4:
<windir>\Profiles\užjméno\Application Data\ScummVM\Saved games\
@@ -1203,7 +1377,7 @@ povolením zobrazení skrytých složek v Průzkumníku Windows.
Poznámka pro uživatele Windows NT4/2000/XP/Vista/7: Výchozí umístění uložených her
bylo ve ScummVM 1.5.0 změněno. Dávkový soubor přesunu může být použit pro zkopírování
-uložených her ze starého výchozího umístění do nového.
+uložených her ze starého výchozího umístění do nového.
6.1) 6.1 Automatické ukládání:
---- -------------------------
@@ -1465,7 +1639,7 @@ do VaÅ¡eho souboru s nastavením v Äásti [scummvm], nebo nastavením SCUMMVM_P
7.7) Použití MIDI serveru TiMidity++:
---- --------------------------------
-Pokud na Vašem systému chybí jakýkoliv sekvencer MIDI, ale přesto chcete lepší kvalitu MIDI, než kterou může nabídnout standardní emulace AdLib, můžete zkusit MIDI server TiMidity++. Prohlédněte si http://timidity.sourceforge.net/ pro stažení a pokyny k instalaci.
+Pokud na Vašem systému chybí jakýkoliv sekvencer MIDI, ale přesto chcete lepší kvalitu MIDI, než kterou může nabídnout standardní emulace AdLib, můžete zkusit MIDI server TiMidity++. Prohlédněte si <http://timidity.sourceforge.net/> pro stažení a pokyny k instalaci.
Nejdříve musíte spustit daemona:
@@ -1475,7 +1649,7 @@ Nyní můžete spustit ScummVM a zkusit vybrat TiMidity jako výstup pro hudbu.
"Äíslo zařízení" použitím promÄ›nné "SCUMMVM_MIDIPORT".
-7.8) Použití komprimovaných zvukových souborů
+7.8) Použití komprimovaných zvukových souborů
---- ----------------------------------------
7.8.0) Použití souborů MP3 pro CD audio:
@@ -1625,7 +1799,12 @@ StandardnÄ› je soubor s nastavením uložen a naÄítán:
Pokud ve Windows nainstalována dřívější verze ScummVM bude ponecháno dřívější umístění '<složkawin>\scummvm.ini'.
Unix:
- ~/.scummvmrc
+ Řídíme se specifikacemi základního adresáře XDG. To znamená, že naše nastavení lze nalézt v:
+ $XDG_CONFIG_HOME/scummvm/scummvm.ini
+
+ Pokud XDG_CONFIG_HOME není nastaven nebo je prázdný, bude, podle pravidel specifikace, použito '~/.config' jako hodnota pro XDG_CONFIG_HOME.
+
+ Pokud byla ve vašem systému nainstalována dřívější verze ScummVM, bude ponecháno původní výchozí umístění '~/.scummvmrc'.
Mac OS X:
~/Library/Preferences/ScummVM Preferences
@@ -1672,7 +1851,7 @@ Vzorový soubor s nastavením vypadá takto:
music_driver=windows
8.1) Rozpoznávaná klíÄová slova nastavení
----- ------------------------------------
+---- ------------------------------------
Jsou rozpoznávána následující klíÄová slova:
path řetězec Cesta, kde jsou umístěny datové soubory hry
@@ -1689,7 +1868,8 @@ Jsou rozpoznávána následující klíÄová slova:
talkspeed Äíslo ZpoždÄ›ní textu v hrách SCUMM, nebo rychlost textu v jiných hrách.
fullscreen boolean Režim celé obrazovky
aspect_ratio boolean Povolit korekci poměru stran
- gfx_mode řetězec Grafický režim (normální, 2x, 3x, 2xsai, super2xsai, supereagle, advmame2x, advmame3x,hq2x, hq3x, tv2x, dotmatrix)
+ gfx_mode řetězec Grafický režim (normální, 2x, 3x, 2xsai, super2xsai, supereagle, advmame2x, advmame3x, hq2x, hq3x, tv2x, dotmatrix, opengl_linear, opengl_nearest)
+
confirm_exit boolean Zeptat se uživatele na potvrzení pÅ™ed ukonÄením (pouze jádro SDL).
console boolean Povolit okno konzole (výchozí: zapnuto) (pouze Windows).
cdrom Äíslo Číslo jednotky CD-ROM, kterou použít pro zvuk. Pokud je záporné, k pokusu o přístup k CD-ROM nedojde.
@@ -1727,7 +1907,7 @@ Hry Sierra používající jádro SCI přidávají následující nestandardní
use_cdaudio boolean Použít zvuky na CD místo ve hře, pokud je dostupné
windows_cursors boolean Použít kurzory Windows (menší a Äernobílé) místo kurzorů z DOS (King's Quest 6)
silver_cursors boolean Použít alternativní sadu stříbrných kurzorů místo standardních zlatých (Space Quest 4)
-
+
Broken Sword II pÅ™idává následující nestandardní klíÄová slova:
gfx_details Äíslo Nastavení grafických detailů (0-3)
@@ -1740,13 +1920,13 @@ Flight of the Amazon Queen pÅ™idává následující nestandardní klíÄová sl
music_mute boolean Pokud true, hudba je ztlumena
sfx_mute boolean Pokud true, zvukové efekty jsou ztlumeny
-
+
Hopkins FBI pÅ™idává následující nestandardní klíÄové slovo:
enable_gore boolean Pokud true, povolí některé nepovinné krvavé scény ve hře
Jones in the Fast Lane pÅ™idává následující nestandardní klíÄové slovo:
- music_mute boolean Pokud true, je použito CD audio místo zvuků ve hře
+ music_mute boolean Pokud true, je použito CD audio místo zvuků ve hře
King's Quest VI Windows pÅ™idává následující nestandardní klíÄové slovo:
@@ -1758,14 +1938,14 @@ Lands of Lore: The Throne of Chaos pÅ™idává následující nestandardní klíÄ
floating_cursors boolean Pokud true, je kurzor zmÄ›nÄ›n na smÄ›rovou Å¡ipku pÅ™i najetí na okraj obrazovky. HrÃ¡Ä pak může kliknout pro pohyb v tomto smÄ›ru.
Space Quest IV CD pÅ™idává následující nestandardní klíÄové slovo:
-
+
silver_cursors boolean Pokud true, je místo původních zlatých kurzorů použita alternativní sada stříbrných
-
+
Simon the Sorcerer 1 a 2 pÅ™idává následující nestandardní klíÄová slova:
music_mute boolean Pokud true, hudba je ztlumena
sfx_mute boolean Pokud true, zvukové efekty jsou ztlumeny
-
+
Soltys pÅ™idává následující nestandardní klíÄové slovo:
enable_color_blind bool Pokud true, jsou původní barvy nahrazeny odstíny šedi
@@ -1777,7 +1957,7 @@ The Legend of Kyrandia: The Hand of Fate přidává následující nestandardní
walkspeed Äíslo Rychlost chůze (3 nebo 5, což znamená
rychle nebo pomalu)
-
+
The Legend of Kyrandia: Malcolm's Revenge pÅ™idává následující nestandardní klíÄová slova:
walkspeed Äíslo Rychlost chůze (3 nebo 5, což znamená
@@ -1785,10 +1965,10 @@ The Legend of Kyrandia: Malcolm's Revenge pÅ™idává následující nestandardnÃ
studio_audience boolean Pokud true, je slyšet potlesk a smích kdykoliv Malcolm provede něco vtipného
skip_support boolean Pokud true, hrÃ¡Ä může pÅ™eskakovat text a scény hry
helium_mode boolean Pokud true, lidé znějí tak, jakoby se nadýchali hélia
-
+
The Neverhood pÅ™idává následující nestandardní klíÄová slova:
- originalsaveload boolean Pokud true, jsou použity původní obrazovky pro
+ originalsaveload boolean Pokud true, jsou použity původní obrazovky pro
naÄítání/ukládání místo obrazovek ScummVM
skiphallofrecordsscenes boolean
Pokud true, umožní hráÄi pÅ™eskoÄit
@@ -1823,10 +2003,8 @@ Zork: Grand Inquisitor pÅ™idává následující nestandardní klíÄové slovo:
mpegmovies boolean Pokud true, jsou použita videa MPEG ve vysokém rozlišení z
DVD verze hry, místo videí AVI v nízkém rozlišení
-8.2) Vlastní herní volby, které mohou být přepínány pomoci grafického
----- ----------------------------------------------------------------
-rozhraní
---------
+8.2) Vlastní herní volby, které mohou být přepínány pomoci grafického rozhraní
+---- -------------------------------------------------------------------------
Mnoho vlastních herních voleb v pÅ™edchozí Äásti může být pÅ™epnuto pÅ™es grafické rozhraní. Pokud je takováto volba pro urÄitou hru dostupná, objeví se karta "Jádro" pÅ™i pÅ™idávání nebo úpravÄ› nastavení této hry.
Pokud vlastní možnosti nejsou zobrazeny, musí být konkrétní hry spuÅ¡tÄ›ny jednou nebo znovu pÅ™idány do seznamu her spouÅ¡tÄ›Äe ScummVM. Toto aktualizuje nastavení každé položky, Äímž umožní zobrazení vlastních voleb.
@@ -1834,73 +2012,124 @@ Pokud vlastní možnosti nejsou zobrazeny, musí být konkrétní hry spuštěny
---- ----------
Pro aktuální přehled o tom, jak ScummVM sestavit pro různé platformy, prohlédněte si, prosím, naší Wiki, zvláště tuto stránku:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM>
Pokud sestavujete ve Windows, Linux nebo Mac OS X, potřebujete SDL-1.2.2
Nebo novÄ›jší (starší verze mohou fungovat, ale nejsou podporovány) a podporovaný kompilátor. VÄ›tÅ¡ina kompilátorů, vÄetnÄ› GCC, mingw a novÄ›jších verzí Microsoft Visual C++ jsou podporovány. Pokud chcete použít stopy CD komprimované do MP3 nebo soubory .SOU, musíte nainstalovat knihovnu MAD; podobnÄ› potÅ™ebujete vhodné knihovny pro komprimovaný zvuk pomocí Ogg Vorbis a FLAC. Pro komprimované uložené stavy je potÅ™eba mít zlib.
-NÄ›které Äásti ScummVM, zvláštÄ› zvÄ›tÅ¡ovaÄe, mají vysoce optimalizované verze napsané v assembleru. Pokud si pÅ™ejete tuto možnost použít, potÅ™ebuje mít nainstalován assembler nasm (viz http://nasm.sf.net). Nezapomeňte, že v souÄasnosti máme pouze verze optimalizované pro x86 MMX, a nebudou sestaveny pro jiné procesory.
-
-Na Win9x/NT/XP můžete urÄit USE_WINDBG a pÅ™ipojit WinDbg pro procházení ladících zpráv (viz https://technet.microsoft.com/en-us/sysinternals/debugview.aspx).
-
- GCC a MinGW32:
- * Zadejte "./configure"
- * Zadejte "make" (nebo "gmake", Äi "gnumake", v závislosti na tom, jak je GNU make ve VaÅ¡em systému nazván) a ScummVM snad bude pro Vás sestaven.
- * Pro další informace si prohlédněte:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/GCC
- Äi
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW
-
- Microsoft Visual C++ 9 a novější:
- * PÅ™eÄtÄ›te si, jak vytvoÅ™it soubory projektu v odpovídající",
- složce "dists\msvc".
- * Otevřete výsledný soubor projektu.
- * Zadejte cestu k potÅ™ebným knihovnám a hlsiÄkovým souborům v
- Tools|Options|Projects and Solutions|VC++ Directories".
- * TeÄ by program mÄ›l být úspěšnÄ› sestaven.
- * Pro další informace si prohlédněte:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/Visual_Studio
-
- Windows Mobile:
- * PÅ™eÄtÄ›te si prosím:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/Windows_CE
-
- Mac OS X:
- * Ujistěte se, že máte nainstalovány nástroje pro vývojáře.
- * BalíÄek SDL pro vývojáře na OS X, který je dostupný na stránce SDL _není_ vhodný. Spíše potÅ™ebujete sestavení v unixovém stylu. Jeden takový způsob, jak ho nainstalovat je pomocí Fink
- (http://fink.sf.net). Také můžete SDL sestavit ruÄnÄ› ze zdrojového kódu pomocí systému sestavení pro unix (configure a make).
- * Ve složce ScummVM zadejte "./configure".
- * Nyní můžete zadat 'make' pro vytvoÅ™ení spouÅ¡tÄ›Äe příkazového řádku.
- * Abyste získali verzi, kterou můžete spustit z Finder, zadejte 'make bundle' což vytvoří ScummVM.app (toto se pokusí zjistit kde máte nainstalovány statické knihovny, což by mělo fungovat ve většině případů, pokud ne, musíte jejich cestu zadat pomocí --with-staticlib-prefix= při konfiguraci - například "./configure --with-staticlib-prefix=/Uživatelé/bla" pokud jsou knihovny umístěny v /Uživatelé/bla/lib.
- * Pro další informace si prohlédněte:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/MacOS_X_Crosscompiling
-
- AmigaOS 4 (Křížová kompilace pomocí Cygwin):
- * Ujistěte se, že máte nainstalován SDL, můžete také potřebovat
- libogg, libvorbis, libvorbisfile, zlib, libmad.
- * Zadejte ./configure --host=ppc-amigaos
- * Pokud dostanete chybu o sdl-config, použijte parametr --with-sdl-prefix pro nastavení cesty.
- * Zkontrolujte soubor 'config.mk' a pokud je vše v pořádku:
- * Spusťte 'make'.
- * Křížová kompilace pomocí Linux může být také tak lehká.
-
- iPhone:
- * PÅ™eÄtÄ›te si prosím:
- http://wiki.scummvm.org/index.php/Compiling_ScummVM/iPhone
-
- Maemo:
- * Nainstalujte Maemo SDK s rootstrap 4.1.2
- * Nainstalujte libmad, Tremor, FLAC ze zdroje
- * Spusťte 'ln -s backends/platform/maemo/debian'
- * Aktualizujte debian/changelog
- * Spusťte 'sb2 dpkg-buildpackage -b'
+NÄ›které Äásti ScummVM, zvláštÄ› zvÄ›tÅ¡ovaÄe, mají vysoce optimalizované verze napsané v assembleru. Pokud si pÅ™ejete tuto možnost použít, potÅ™ebuje mít nainstalován assembler nasm (viz http://www.nasm.us/). Nezapomeňte, že v souÄasnosti máme pouze verze optimalizované pro x86 MMX, a nebudou sestaveny pro jiné procesory.
+
+Na Win9x/NT/XP můžete urÄit USE_WINDBG a pÅ™ipojit WinDbg pro procházení ladících zpráv (viz <https://technet.microsoft.com/en-us/sysinternals/debugview.aspx)>.
+
+ Windows:
+ * Dev-C++
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/DevCPP>
+ * MinGW
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW>
+ * Visual Studio (MSVC)
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Visual_Studio>
+ * Windows CE/Mobile
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Windows_CE>
+
+ Linux:
+ * GCC
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/GCC>
+
+ Mac OS X:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Mac_OS_X>
+
+ AmigaOS4:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/AmigaOS>
+
+ Apple iPhone:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/iPhone>
+
+ Atari/FreeMiNT:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Atari/FreeMiNT>
+
+ Bada/Tizen:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Bada/Tizen>
+
+ BeOS/ZETA/Haiku:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/BeOS/ZETA/Haiku>
+
+ Google Android:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Android>
+
+ HP webOS:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/WebOS>
+
+ Mac OS:
+ * Mac OS X
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Mac_OS_X>
+ * Mac OS X 10.2.8
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_10.2.8>
+ * Mac OS X Křížová kompilace
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_Crosscompiling>
+
+ Maemo:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Maemo>
+
+ Nintendo DS:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Nintendo_DS>
+
+ Nintendo Wii a Gamecube:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Wii>
+
+ RaspberryPi:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/RPI>
+
+ Sega Dreamcast:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Dreamcast>
+
+ Sony Playstation:
+ * Sony PlayStation 2
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_2>
+ * Sony PlayStation 3
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/PlayStation_3#Building_from_source>
+ * Sony PlayStation Portable
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_Portable>
+
+ Symbian:
+ PÅ™eÄtÄ›te si prosím:
+ <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Symbian>
+
+
+10.0) Poděkování
+----- ----------
+Prosím pÅ™eÄtÄ›te si náš rozsáhlý seznam lidí, kterým chceme podÄ›kovat na
+
+<http://www.scummvm.org/credits/>
+
+
+
------------------------------------------------------------------------
Hodně Štěstí a Šťastné Adventurování!
Tým ScummVM.
-http://www.scummvm.org/
+<http://www.scummvm.org/>
------------------------------------------------------------------------
-
-
-
-
diff --git a/doc/de/Liesmich b/doc/de/Liesmich
index cdc11ffd09..f37fc7d396 100644
--- a/doc/de/Liesmich
+++ b/doc/de/Liesmich
@@ -20,38 +20,38 @@ Inhaltsverzeichnis:
* 3.3 Hinweise zu Spielen auf mehreren CDs
* 3.4 Bekannte Probleme
* 3.5 Hinweise zu Beneath a Steel Sky
- * 3.6 Hinweise zu Baphomets Fluch
+ * 3.6 Hinweise zu Baphomets Fluch I und II
* * 3.6.1 Baphomets Fluch
* * 3.6.2 Baphomets Fluch II
- * * 3.6.3 Zwischenszenen in Baphomets Fluch
- * * 3.6.4 Zwischenszenen in Baphomets Fluch (Rückblick)
+ * * 3.6.3 Zwischensequenzen in Baphomets Fluch
+ * * 3.6.4 Zwischensequenzen in Baphomets Fluch (Rückblick)
* 3.7 Hinweise zu Day of the Tentacle
* 3.8 Hinweise zu Discworld II
* 3.9 Hinweise zu DraÄi Historie
* 3.10 Hinweise zu Flight of the Amazon Queen
* 3.11 Hinweise zu Gobliiins
- * 3.12 Hinweise zu Inherit the Earth: Quest for the Orb
+ * 3.12 Hinweise zu Inherit the Earth: Quest for the Orb (Macintosh)
* 3.13 Hinweise zu Maniac Mansion (Apple II/NES)
* 3.14 Hinweise zu Mickey's Space Adventure
- * 3.15 Hinweise zu Nippon Safes Inc.
- * 3.16 Hinweise zu Simon the Sorcerer
+ * 3.15 Hinweise zu Nippon Safes Inc. (Amiga)
+ * 3.16 Hinweise zu Simon the Sorcerer 1 und 2
* 3.17 Hinweise zu The Curse of Monkey Island
* 3.18 Hinweise zu Floyd – Es gibt noch Helden
* 3.19 Hinweise zu The Legend of Kyrandia
* 3.20 Hinweise zu Troll's Tale
* 3.21 Hinweise zu Winnie the Pooh
* 3.22 Hinweise zum vorhersagenden Eingabedialog in AGI-Spielen von Sierra
- * 3.23 Gleichzeitige Sprachausgabe und Untertitel SCI-Spielen von Sierra
+ * 3.23 Gleichzeitige Sprachausgabe und Untertitel in SCI-Spielen von Sierra
* 3.24 Hinweise zu den Spielen der Zork-Reihe
* 3.25 Hinweise zu Spielen für den Commodore 64
* 3.26 Hinweise zu Spielen für den Macintosh
4.0) Unterstützte Plattformen
5.0) ScummVM verwenden
* 5.1 Kommandozeilenoptionen
- * 5.2 Sprachoptionen
+ * 5.2 Globales Menü
* 5.3 Grafikfilter
- * 5.4 Globales Menü
- * 5.5 Tastenkürzel
+ * 5.4 Tastenkürzel
+ * 5.5 Sprachoptionen
6.0) Spielstände
* 6.1 Automatisches Speichern von Spielständen
* 6.2 Spielstände umwandeln
@@ -69,14 +69,14 @@ Inhaltsverzeichnis:
* 7.7 TiMidity++-MIDI-Server-Unterstützung
* 7.8 Komprimierte Audio-Dateien verwenden (MP3, Ogg Vorbis, FLAC)
* * 7.8.1 MP3-Dateien für CD-Audio verwenden
- * * 7.8.2 Ogg Vorbis-Dateien für CD-Audio verwenden
- * * 7.8.3 Flac-Dateien für CD-Audio verwenden
+ * * 7.8.2 Ogg-Vorbis-Dateien für CD-Audio verwenden
+ * * 7.8.3 FLAC-Dateien für CD-Audio verwenden
* * 7.8.4 MONSTER.SOU mit MP3 komprimieren
* * 7.8.5 MONSTER.SOU mit Ogg Vorbis komprimieren
- * * 7.8.6 MONSTER.SOU mit Flac komprimieren
- * * 7.8.7 Musik/Effekte/Sprache in AGOS-Spielen komprimieren
- * * 7.8.8 Sprache/Musik in Baphomets Fluch komprimieren
- * * 7.8.9 Sprache/Musik in Baphomets Fluch II komprimieren
+ * * 7.8.6 MONSTER.SOU mit FLAC komprimieren
+ * * 7.8.7 Musik/Effekte/Sprachausgabe in AGOS-Spielen komprimieren
+ * * 7.8.8 Sprachausgabe/Musik in Baphomets Fluch komprimieren
+ * * 7.8.9 Sprachausgabe/Musik in Baphomets Fluch II komprimieren
* 7.9 Ausgabefrequenzen
8.0) Konfigurationsdatei
* 8.1 Verwendbare Konfigurationsschlüsselwörter
@@ -273,6 +273,7 @@ Spiele von Activision (MADE):
Spiele von Adventuresoft/Horrorsoft (AGOS):
Elvira - Mistress of the Dark [elvira1]
Elvira II - The Jaws of Cerberus [elvira2]
+ Floyd - Es gibt noch Helden [feeble]
Personal Nightmare [pn]
Simon the Sorcerer 1 [simon1]
Simon the Sorcerer 2 [simon2]
@@ -284,7 +285,6 @@ Spiele von Adventuresoft/Horrorsoft (AGOS):
- NoPatience [puzzle]
Simon the Sorcerer's Game Pack
- Swampy Adventures [swampy]
- Floyd - Es gibt noch Helden [feeble]
Waxworks [waxworks]
Spiele von Coktel Vision (GOB):
@@ -297,10 +297,9 @@ Spiele von Coktel Vision (GOB):
Lost in Time [lostintime]
Once Upon A Time: Little Red Riding Hood [littlered]
Playtoons: Bambou le sauveur de la jungle [bambou]
- The Bizarre Adventures of Woodruff
- and the Schnibble [woodruff]
Urban Runner [urban]
Ween: The Prophecy [ween]
+ Woodruff and the Schnibble of Azimuth [woodruff]
Spiele von Revolution Software:
Beneath a Steel Sky [sky]
@@ -329,7 +328,7 @@ Spiele von Sierra (AGI und preAGI):
Troll's Tale [troll]
Winnie the Pooh in the Hundred Acre Wood [winnie]
-SCI-Spiele von Sierra Entertainment:
+Spiele von Sierra (SCI):
Codename: ICEMAN [iceman]
Conquests of Camelot [camelot]
Conquests of the Longbow [longbow]
@@ -373,17 +372,22 @@ SCI-Spiele von Sierra Entertainment:
Andere Spiele:
3 Skulls of the Toltecs [toltecs]
Amazon: Guardians of Eden [access]
+ Baphomets Fluch 2.5:
+ Die Rückkehr der Tempelritter [sword25]
Beavis and Butt-head in Virtual Stupidity [bbvs]
Blue Force [blueforce]
- Baphomets Fluch: Die Rückkehr der Templer [sword25]
Bud Tucker in Double Trouble [tucker]
Chivalry is Not Dead [chivalry]
Cruise for a Corpse [cruise]
- DreamWeb [dreamweb]
+ Die ungelösten Fälle von Sherlock Holmes:
+ Das gezackte Skalpell [scalpel]
+ Die ungelösten Fälle von Sherlock Holmes:
+ Die tätowierte Rose [rosetattoo]
Discworld [dw]
Discworld 2: Vermutlich vermisst [dw2]
DraÄi Historie [draci]
Drascula: The Vampire Strikes Back [drascula]
+ DreamWeb [dreamweb]
Erben der Erde: Die große Suche [ite]
Eye of the Beholder [eob]
Eye of the Beholder II: The Legend of
@@ -403,25 +407,20 @@ Andere Spiele:
Return to Ringworld [ringworld2]
Sfinx [sfinx]
Soltys [soltys]
+ TeenAgent [teenagent]
+ The 7th Guest [t7g]
The Journeyman Project: Pegasus Prime [pegasus]
The Legend of Kyrandia [kyra1]
The Legend of Kyrandia: The Hand of Fate [kyra2]
The Legend of Kyrandia: Malcolm's Revenge [kyra3]
- The Lost Files of Sherlock Holmes: The Case
- of the Serrated Scalpel [scalpel]
- The Lost Files of Sherlock Holmes: The Case
- of the Rose Tattoo [rosetattoo]
The Neverhood [neverhood]
- The 7th Guest [t7g]
- TeenAgent [teenagent]
- Toonstruck [toon]
Tony Tough and the Night of Roasted Moths [tony]
Toonstruck [toon]
Touché: Die Abenteuer des fünften
Musketiers [touche]
Voyeur [voyeur]
- Zork: Grand Inquisitor [zgi]
- Zork Nemesis: The Forbidden Lands [znemesis]
+ Zork: Der Großinquisitor [zgi]
+ Zork Nemesis: Das verbotene Land [znemesis]
Spiele von Humongous Entertainment (SCUMM):
Backyard Baseball [baseball]
@@ -517,10 +516,10 @@ ScummVM unterstützt:
Seien Sie sich bitte bewusst, dass die Engines („Motoren“ der Spiele) Fehler
enthalten können und manche Funktionen möglicherweise fehlen, was es unmöglich
-machten kann, das Spiel zu Ende zu spielen. Speichern Sie oft und bitte schicken Sie
-englischsprachige Fehlerberichte ein (Anweisungen zum Senden von Fehlerberichten finden
-Sie oben), wenn Sie einen solchen Fehler in einem „unterstützten“ Spiel
-vorfinden.
+machen kann, das Spiel zu Ende zu spielen. Speichern Sie oft und bitte schicken
+Sie englischsprachige Fehlerberichte ein (Anweisungen zum Senden von
+Fehlerberichten finden Sie oben), wenn Sie einen solchen Fehler in einem
+„unterstützten“ Spiel vorfinden.
3.1) Kopierschutz:
@@ -562,16 +561,16 @@ ScummVM wird den Kopierschutz in folgenden Spielen überspringen:
* Zak McKracken and the Alien Mindbenders
-3.2) Spieldateien
----- ------------
-Für eine ausführliche Liste der benötigten Spieldateien für unterstützte
-Spiele, besuchen Sie:
+3.2) Spieldateien:
+---- -------------
+Für eine ausführliche Liste der benötigten Spieldateien für unterstützte Spiele,
+besuchen Sie:
- <http://wiki.scummvm.org/index.php/Datafiles>
+ http://wiki.scummvm.org/index.php/Datafiles
3.3) Hinweise zu Spielen auf mehreren CDs:
----- -----------------------------------
+---- -------------------------------------
Allgemein kann ScummVM nicht sehr gut mit Spielen auf mehreren CDs umgehen. Das
liegt daran, dass ScummVM annimmt, alles von einem Spiel in einem Verzeichnis
vorzufinden. Selbst wenn ScummVM einige Fälle berücksichtigt und den Anwender
@@ -588,20 +587,20 @@ hineinkopieren.
3.4) Bekannte Probleme:
------ ------------------
-Diese Version hat die unten folgenden bekannten Probleme. Es ist
-nicht notwendig, diese zu melden, jedoch sind Patches, um diese zu beheben,
+---- ------------------
+Diese Version hat die unten folgenden bekannten Probleme. Es ist nicht
+notwendig, diese zu melden, jedoch sind Patches, um diese zu beheben,
willkommen. Wenn Sie einen Fehler entdecken, der weder hier noch auf der
Kompatibilitätsseite der Website aufgeführt ist, sehen Sie bitte im Abschnitt
„Fehler melden“ nach, wenn Sie diesen melden möchten.
Spiele mit Ton von CD:
- Bei Spielen, die auf Audio von CD zurückgreifen (FM-TOWNS-Spiele,
- CD-Version von Loom usw.), ist es möglich, dass Anwender von Microsoft Windows
- 2000/XP zufällige Abstürze erleben. Das liegt an einem lange bestehenden
- Windows-Fehler, der dazu führt, dass fehlerhafte Spieldaten von der CD
- ausgelesen werden. Bitte kopieren Sie die Spieldaten in ein Verzeichnis
- Ihrer Festplatte, um dies zu vermeiden.
+ CD-Version von Loom usw.), ist es möglich, dass Anwender von Microsoft
+ Windows 2000/XP zufällige Abstürze erleben. Das liegt an einem lange
+ bestehenden Windows-Fehler, der dazu führt, dass fehlerhafte Spieldaten
+ von der CD ausgelesen werden. Bitte kopieren Sie die Spieldaten in ein
+ Verzeichnis Ihrer Festplatte, um dies zu vermeiden.
FM-TOWNS-Versionen:
- Die Kanji-Versionen erfordern die Schriftart-ROM-Datei von FM-TOWNS.
@@ -636,7 +635,7 @@ Kompatibilitätsseite der Website aufgeführt ist, sehen Sie bitte im Abschnitt
Lure of the Temptress:
- Keine Unterstützung für Roland MT32
- - Sound-Unterstützung ist unvollständig und klingt nicht wie das Original
+ - Sound-Unterstützung ist unvollständig und klingt nicht wie ursprünglich.
Simon the Sorcerer 1:
- Untertitel sind in den deutschen und englischen CD-Versionen nicht
@@ -794,8 +793,8 @@ Sache, da das Entschlüsseln von MPEG-Filmen mit vielen Schwierigkeiten verbunde
war und diese ohnehin nicht so gut aussahen wie Smacker- und DXA-Versionen.
-3.7) Hinweise zu Day of the Tentacle
----- -------------------------------
+3.7) Hinweise zu Day of the Tentacle:
+---- --------------------------------
An einem bestimmten Punkt im Spiel kommen Sie an einem Computer vorbei, der
Ihnen erlaubt, das originale Maniac Mansion zu spielen. ScummVM unterstützt
@@ -816,9 +815,10 @@ festlegen können. Jedoch erlauben nicht alle Spiele die Rückkehr zum HauptmenÃ
Es ist nicht empfehlenswert, Day of the Tentacle selbst als Easter-Egg-Spiel
festzulegen.
-3.8) Hinweise zu Discworld II
----- ------------------------
-Für diese Spiel benötien Sie alle Dateien im Verzeichnis DW2 auf beiden CDs.
+
+3.8) Hinweise zu Discworld II:
+---- -------------------------
+Für diese Spiel benötigen Sie alle Dateien im Verzeichnis DW2 auf beiden CDs.
Zusätzlich benötigen Sie die Datei SAMPLE.BNK.
Sie müssen ENGISH.SMP, ENGLISH.IDX und ENGLISH.TXT von CD1 zu ENGLISH1.SMP,
@@ -945,8 +945,8 @@ unkomplizierter ist, als sich mit dem Menü umherzubewegen.
Für dieses Spiel benötigen Sie die Dateien
disk0, global.table, pointer und it (en, fr, ge für die internationale Version).
-Zusätzlich müssen Sie das Diskettenabbild 2 in disk1, Abbild 3 in disk2, Abbild 4
-in disk3 sowie Abbild 5 in disk4 umbenennen.
+Zusätzlich müssen Sie das Diskettenabbild 2 in disk1, Abbild 3 in disk2,
+Abbild 4 in disk3 sowie Abbild 5 in disk4 umbenennen.
3.16) Hinweise zu Simon the Sorcerer 1 und 2:
@@ -973,10 +973,11 @@ diesem Fall identisch.
Amiga/Macintosh:
Sie benötigen ein kleines Paket mit Zwischensequenzen, welche sowohl in der
Amiga- als auch in der Macintosh-Version fehlen. Es heißt
-"The Feeble Files- Omni TV and epilogue cutscenes for the Amiga and Macintosh versions"
+„The Feeble Files - Omni TV and epilogue cutscenes for the Amiga and Macintosh
+versions“
und kann hier heruntergeladen werden:
- <http://www.scummvm.org/games/#feeble>
+ http://www.scummvm.org/games/#feeble
Windows:
Wenn Sie die Windows-Version von Floyd – Es gibt noch Helden haben, sind einige
@@ -1141,77 +1142,84 @@ Space Quest 4 CD:
deaktiviert und aktiviert werden.
-3.24) Hinweise zu den Spielen der Zork-Reihe
------ --------------------------------------
-Um die unterstützen Zork-Spiele (Zork Nemesis: The Forbidden Lands
-und Zork: Grand Inquisitor) zu spielen, müssen Sie einige zusätzliche
+3.24) Hinweise zu den Spielen der Zork-Reihe:
+----- ---------------------------------------
+Um die unterstützen Zork-Spiele (Zork Nemesis: Das verbotene Land und
+Zork: Der Großinquisitor) spielen zu können, müssen Sie einige zusätzliche
Dateien zu ihren entsprechenden Zielen kopieren.
-Zork Nemesis: The Forbidden Lands
+Zork Nemesis: Das verbotene Land
Alle Versionen
-Laden Sie das Liberation(tm)-Schriftartenpaket
-<https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
-herunter und entpacken Sie alle ttf-Dateien in Ihr ScummVM "extras"-Verzeichnis.
-Alternativ können Sie auch das GNU FreeFont TTF-Paket unter
-<https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip> herunterladen und alle ttf-Dateien
-aus dem sfd-Verzeichnis in Ihr ScummVM "extras"-Verzeichnis kopieren. Diese Schriftarten
-können Probleme mit der Textdarstellung verursachen.
-Laden Sie den Untertitel-Patch
-<http://www.thezorklibrary.com/installguides/znpatch.zip> herunter und entpacken
-Sie das Verzeichnis "addon" in das Hauptverzeichnis des Spiels.
+
+Laden Sie das Liberation(tm)-Schriftartenpaket unter
+https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-
+2.00.1.tar.gz
+herunter und entpacken Sie alle ttf-Dateien in ScummVMs Extras-Pfad. Alternativ
+können Sie auch das GNU FreeFont TTF-Paket unter
+https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip
+herunterladen und alle ttf-Dateien aus dem sfd-Verzeichnis in ScummVMs Extras-
+Pfad kopieren. Diese Schriftarten können Probleme bei der Textdarstellung
+verursachen. Laden Sie den Untertitel-Patch unter
+http://www.thezorklibrary.com/installguides/znpatch.zip
+herunter und entpacken Sie das Verzeichnis "addon" in das Hauptverzeichnis des
+Spiels.
GoG-Version
-Verwenden Sie das GoG-Installationsprogramm. Keine weiteren Dateien müssen kopiert werden.
+Verwenden Sie das GoG-Installationsprogramm. Keine weiteren Dateien müssen
+kopiert werden.
CD-Version
-Kopieren Sie folgende Verzeichnisse und Dateien aus dem Verzeichnis "nemesis" auf CD1
-in das Hauptverzeichnis des Spiels:
-Das Verzeichnis "znemmx"
-Das Verzeichnis "znemscr"
+Kopieren Sie folgende Verzeichnisse und Dateien aus dem Verzeichnis "nemesis"
+auf CD1 in das Hauptverzeichnis des Spiels:
+das Verzeichnis "znemmx"
+das Verzeichnis "znemscr"
nemesis.str
-Von CD1, kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des Spiels.
-Von CD2, kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des Spiels und
-überschreiben Sie alle identischen Dateien.
-Von CD3, kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des Spiels und
-überschreiben Sie alle identischen Dateien.
+Von CD1 kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des
+Spiels.
+Von CD2 kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des
+Spiels und überschreiben Sie alle identischen Dateien.
+Von CD3 kopieren Sie das Verzeichnis "zassets" in das Hauptverzeichnis des
+Spiels und überschreiben Sie alle identischen Dateien.
DVD-Version
-Kopieren Sie folgende Verzeichnisse und Dateien aus dem Verzeichnis "nemesis" auf CD1
-in das Hauptverzeichnis des Spiels:
+Kopieren Sie folgende Verzeichnisse und Dateien aus dem Verzeichnis "nemesis"
+auf CD1 in das Hauptverzeichnis des Spiels:
Das Verzeichnis "znemmx"
Das Verzeichnis "znemscr"
nemesis.str
-Hinweis: Sie müssen auch die Datei cursor.zfs vom Verzeichnis "zassets/global" in
-das Verzeichnis "znemscr" verschieben.
-Kopieren Sie die Verzeichnisse "disc2", "disc3" und "zassets" in das Hauptverzeichnis
-des Spiels.
+Hinweis: Sie müssen auch die Datei cursor.zfs vom Verzeichnis "zassets/global"
+in das Verzeichnis "znemscr" verschieben.
+Kopieren Sie die Verzeichnisse "disc2", "disc3" und "zassets" in das
+Hauptverzeichnis des Spiels.
-Zork: Grand Inquisitor
+Zork: Der Großinquisitor
Alle Versionen
-Alle Versionen
-Laden Sie das Liberation(tm)-Schriftartenpaket
-<https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
-herunter und entpacken Sie alle ttf-Dateien in Ihr ScummVM "extras"-Verzeichnis.
+Laden Sie das Liberation(tm)-Schriftartenpaket unter
+https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-
+2.00.1.tar.gz
+herunter und entpacken Sie alle ttf-Dateien in ScummVMs Extras-Pfad.
Alternativ können Sie auch das GNU FreeFont TTF-Paket unter
-<https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip> herunterladen und alle ttf-Dateien
-aus dem sfd-Verzeichnis in Ihr ScummVM "extras"-Verzeichnis kopieren. Diese Schriftarten
-können Probleme mit der Textdarstellung verursachen.
+https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip
+herunterladen und alle ttf-Dateien aus dem sfd-Verzeichnis in ScummVMs Extras-
+Pfad kopieren. Diese Schriftarten können Probleme bei der Textdarstellung
+verursachen.
GoG-Version
-Verwenden Sie das GoG-Installationsprogramm. Es müssen keine weiteren Dateien kopiert werden.
+Verwenden Sie das GoG-Installationsprogramm. Es müssen keine weiteren Dateien
+kopiert werden.
CD-Version:
-Kopieren Sie die folgenden Verzeichnisse und Dateien aus dem Verzeichnis "zgi" von CD1
-in das Hauptverzeichnis des Spiels:
+Kopieren Sie die folgenden Verzeichnisse und Dateien aus dem Verzeichnis "zgi"
+von CD1 in das Hauptverzeichnis des Spiels:
das Verzeichnis "zgi_mx"
cursor.zfs
death.zfs
@@ -1220,19 +1228,21 @@ inquis.zix
r.svr
scripts.zfs
subtitle.zfs
-Von CD1, kopieren Sie das Verzeichnis "zassets1" in das Hauptverzeichnis des Spiels
-Von CD2, kopieren Sie das Verzeichnis "zassets2" in das Hauptverzeichnis des Spiels
-Es wird empfohlen, den Patch 1.2 anzuwenden.
-<http://www.thezorklibrary.com/installguides/Zpatch.exe>
+Von CD1 kopieren Sie das Verzeichnis "zassets1" in das Hauptverzeichnis des
+Spiels.
+Von CD2 kopieren Sie das Verzeichnis "zassets2" in das Hauptverzeichnis des
+Spiels.
+Es wird empfohlen, den hier erhältlichen Patch 1.2 anzuwenden:
+http://www.thezorklibrary.com/installguides/Zpatch.exe
Möglicherweise müssen Sie das Spiel zuvor normal installieren, da der Patch ein
eigenes Installationsprogramm besitzt.
DVD-Version
-Kopieren Sie die folgenden Verzeichnisse und Dateien aus dem Verzeichnis "zgi_e"
+Kopieren Sie die folgenden Verzeichnisse und Dateien aus dem Verzeichnis "zgi_e"
in das Hauptverzeichnis des Spiels:
-Das Verzeichnis "addon" (Spiel-Patch 1.2)
-Das Verzeichnis zgi_mx
+das Verzeichnis "addon" (Spiel-Patch 1.2)
+das Verzeichnis zgi_mx
cursor.zfs
death.zfs
inquis.str
@@ -1240,13 +1250,13 @@ inquis.zix
r.svr
scripts.zfs
subtitle.zfs
-Kopieren Sie das Verzeichnis "eng_mpeg" (hochauflösende MPEG2-Videodateien") in das
-Hauptverzeichnis des Spiels. Kopieren Sie die Verzeichnisse "zassetsc" und "zassetse"
-ebenfalls in das Hauptverzeichnis des Spiels.
+Kopieren Sie das Verzeichnis "eng_mpeg" (hochauflösende MPEG2-Videodateien) in
+das Hauptverzeichnis des Spiels. Kopieren Sie die Verzeichnisse "zassetsc" und
+"zassetse" ebenfalls in das Hauptverzeichnis des Spiels.
3.25) Hinweise zu Spielen für den Commodore 64:
----- ------------------------------------------
+----- -----------------------------------------
Sowohl Maniac Mansion als auch Zak McKracken laufen, aber Maniac Mansion ist
noch nicht spielbar. Benennen Sie einfach die D64-Datenträger um in
„maniac1.d64“ und „maniac2.d64“ und entsprechend „zak1.d64“ und „zak2.d64“, dann
@@ -1260,8 +1270,8 @@ Plattform eingestellt ist. Wir empfehlen, auf die viel einfachere Methode
zurückzugreifen, die im vorherigen Absatz beschrieben ist.
-3.5) Hinweise zu Spielen für den Macintosh:
----- --------------------------------------
+3.26) Hinweise zu Spielen für den Macintosh:
+----- --------------------------------------
Alle auf SCUMM basierenden Adventures von Lucasarts, mit Ausnahme von COMI,
existieren auch als Versionen für den Macintosh. ScummVM kann die meisten
(alle?) von diesen verwenden, jedoch ist in manchen Fällen zusätzliche Arbeit
@@ -1431,8 +1441,9 @@ gestartet werden -- siehe nächster Abschnitt.
--output-rate=FREQUENZ Wählt Ausgabefrequenz in Hz (z. B. 22050).
--opl-driver=TREIBER Wählt AdLib-(OPL-)Emulator (db, mame).
--aspect-ratio Aktiviert Seitenverhältniskorrektur.
- --render-mode=MODUS Aktiviert zusätzlichen Render-Modus (cga, ega,
- hercGreen, hercAmber, amiga).
+ --render-mode=MODUS Aktiviert zusätzlichen Render-Modus (hercGreen,
+ hercAmber, cga, ega, vga, amiga, fmtowns, pc9821,
+ pc9801, 2gs, atari, macintosh).
--alt-intro Verwendet alternativen Vorspann in CD-Versionen von
Beneath a Steel Sky und Flight of the Amazon Queen.
@@ -1582,6 +1593,7 @@ zwischen SCUMM-Spielen und anderen Spielen.
Strg+F5 - Zeigt globales Menü.
Cmd+q - Beenden (Mac OS X)
Strg+q - Beenden (andere UNIX-Systeme einschließlich Linux)
+ Alt+F4 - Beenden (Windows)
Strg+z ODER Alt+x - Beenden (andere Plattformen)
Strg+u - Allen Ton abschalten - EIN/AUS
Strg+m - Mausbegrenzung in Fenster EIN/AUS
@@ -1735,27 +1747,28 @@ zwischen SCUMM-Spielen und anderen Spielen.
Escape - Beenden
Leertaste - Ãœberspringt aktuelle Textzeile.
t - Wechselt zwischen „Nur Sprachausgabe“,
- „Sprachausgabe und Text“ und „Nur Text“
-
- Zork: Grand Inquisitor:
- Ctrl-s - Save
- Ctrl-r - Restore
- Ctrl-q - Quit
- Ctrl-p - Preferences
- F1 - Help
- F5 - Inventory
- F6 - Spellbook
- F7 - Score
- F8 - Put away current object/forget spell
- F9 - Extract coin (must have the coin bag)
- Space - Skips movies
-
- Zork Nemesis: The Forbidden Lands:
- Ctrl-s - Save
- Ctrl-r - Restore
- Ctrl-q - Quit
- Ctrl-p - Preferences
- Space - Skips movies
+ „Sprachausgabe und Text“ und „Nur Text“.
+
+ Zork: Der Großinquisitor:
+ Strg+s - Speichern
+ Strg+r - Laden
+ Strg+q - Beenden
+ Strg+p - Einstellungen
+ F1 - Hilfe
+ F5 - Inventar
+ F6 - Zauberbuch
+ F7 - Punkte
+ F8 - Aktuelles Objekt wegtun / Zauberspruch vergessen
+ F9 - Münze hervorholen (muss Münzentasche haben)
+ Space - Ãœberspringt Zwischensequenzen.
+
+ Zork Nemesis: Das verbotene Land:
+ Strg+s - Speichern
+ Strg+r - Laden
+ Strg+q - Beenden
+ Strg+p - Einstellungen
+ Leertaste - Ãœberspringt Zwischensequenzen.
+
Beachten Sie, dass von der Verwendung von Strg+f oder Strg+g abgeraten wird:
Spiele können abstürzen, wenn sie schneller als mit ihrer normalen
@@ -1838,8 +1851,8 @@ Die folgenden Plattformen haben ein anderes Standard-Verzeichnis:
$HOME/Documents/ScummVM Savegames/
Andere UNIX-Systeme:
- Wir befolgen die "XDG Base Directory"-Spezifikation. Dies bedeutet, dass
- die Spielstände in:
+ Wir befolgen die Spezifikation XDG Base Directory. Dies bedeutet, dass
+ die Spielstände in
$XDG_DATA_HOME/scummvm/saves/
gespeichert werden.
@@ -1847,8 +1860,8 @@ Die folgenden Plattformen haben ein anderes Standard-Verzeichnis:
Wert für XDG_DATA_HOME in Übereinstimmung mit der Spezifikation verwendet.
Wenn eine frühere Version von ScummVM auf Ihrem System installiert war, wird
- das ursprüngliche Standard-Verzeichnis "~/.scummvm" beibehalten. Dies wird daran
- erkannt, dass der Pfad "~/.scummvm" vorhanden ist.
+ das ursprüngliche Standard-Verzeichnis „~/.scummvm“ beibehalten. Dies wird
+ daran erkannt, dass der Pfad „~/.scummvm“ vorhanden ist.
Windows Vista/7/8/10:
\Users\Benutzername\AppData\Roaming\ScummVM\Saved games\
@@ -1862,14 +1875,15 @@ Die folgenden Plattformen haben ein anderes Standard-Verzeichnis:
Application Data\ScummVM\Saved games\
Spielstände werden unter Windows NT4/2000/XP/Vista/7/8/10 in einem versteckten
-Verzeichnis gespeichert, auf welches über den Pfad "%APPDATA%\ScummVM\Saved Games\"
-zugegriffen werden kann. Es wir auch sichtbar, wenn die Anzeige von versteckten
-Dateien im Windows Explorer aktiviert wird.
+Verzeichnis gespeichert, auf welches über den Pfad
+„%APPDATA%\ScummVM\Saved Games\“ zugegriffen werden kann. Es wird auch sichtbar,
+wenn die Anzeige versteckter Dateien im Windows Explorer aktiviert wird.
+
+Hinweis für Anwender von Windows NT4/2000/XP/Vista/7/8/10: Das Standard-
+Verzeichnis für Spielstände wurde bei ScummVM 1.5.0 geändert. Die
+Stapelverarbeitungsdatei migration.bat kann verwendet werden, um die Spielstände
+vom alten Standard-Verzeichnis in das neue zu kopieren.
-Hinweis für Anwender von Windows NT4/2000/XP/Vista/7/8/10: Das Standard-Verzeichnis
-für Spielstände wurde bei ScummVM 1.5.0 geändert. Die Stapelverarbeitungsdatei
-migration.bat kann verwendet werden, um die Spielstände vom alten
-Standard-Verzeichnis in das neue zu kopieren.
6.1) Automatische Speicherung der Spielstände:
---- -----------------------------------------
@@ -2466,7 +2480,7 @@ Ausgabefrequenz ein Vielfaches der Originalfrequenz ist.
---- --------------------
Standardmäßig wird die Konfigurationsdatei hier gespeichert und geladen:
- Windows Vista/7/8/10:
+ Windows Vista/7:
\Users\Benutzername\AppData\Roaming\ScummVM\scummvm.ini
Windows 2000/XP:
@@ -2484,8 +2498,8 @@ Standardmäßig wird die Konfigurationsdatei hier gespeichert und geladen:
der frühere Standard-Ort „<Windows-Verzeichnis>\scummvm.ini“ beibehalten.
Unix:
- Wir befolgen die "XDG Base Directory"-Spezifikation. Dies bedeutet, dass
- unsere Konfiguration in:
+ Wir befolgen die Spezifikation XDG Base Directory. Dies bedeutet, dass
+ unsere Konfiguration in
$XDG_DATA_HOME/scummvm/scummvm.ini
gefunden werden kann.
@@ -2493,9 +2507,8 @@ Standardmäßig wird die Konfigurationsdatei hier gespeichert und geladen:
Wert für XDG_DATA_HOME in Übereinstimmung mit der Spezifikation verwendet.
Wenn eine frühere Version von ScummVM auf Ihrem System installiert war, wird
- das ursprüngliche Standard-Verzeichnis "~/.scummvm" beibehalten. Dies wird daran
- erkannt, dass der Pfad "~/.scummvm" vorhanden ist.
-
+ das ursprüngliche Standard-Verzeichnis „~/.scummvm“ beibehalten. Dies wird
+ daran erkannt, dass der Pfad „~/.scummvm“ vorhanden ist.
Mac OS X:
~/Library/Preferences/ScummVM Preferences
@@ -2771,7 +2784,7 @@ Schlüsselwort:
Geschwindigkeit wiedergegeben, um Probleme bei
der Musik-Synchronität zu vermeiden.
-Zork Nemesis: The Forbidden Lands verfügt zusätzlich über folgende nicht
+Zork Nemesis: Das verbotene Land verfügt zusätzlich über folgende nicht
standardmäßige Schlüsselwörter:
originalsaveload Bool Falls „true“, werden die originalen Menüs zum
@@ -2782,11 +2795,11 @@ standardmäßige Schlüsselwörter:
noanimwhileturning Bool Falls „true“, werden Animationen während des
Drehens im Panorama-Modus deaktiviert.
mpegmovies Bool Falls „true“, werden hochauflösende MPEG-Videos
- der DVD-Version im Spiel verwendet, anstelle der
+ der DVD-Version im Spiel verwendet anstelle der
niedrig auflösenden AVI-Videos.
-Zork: Grand Inquisitor verfügt zusätzlich über folgende nicht
-standardmäßige Schlüsselwörter:
+Zork: Der Großinquisitor verfügt zusätzlich über folgende nicht standardmäßige
+Schlüsselwörter:
originalsaveload Bool Falls „true“, werden die originalen Menüs zum
Speichern und Laden statt der erweiterten
@@ -2796,12 +2809,12 @@ standardmäßige Schlüsselwörter:
noanimwhileturning Bool Falls „true“, werden Animationen während des
Drehens im Panorama-Modus deaktiviert.
mpegmovies Bool Falls „true“, werden hochauflösende MPEG-Videos
- der DVD-Version im Spiel verwendet, anstelle der
+ der DVD-Version im Spiel verwendet anstelle der
niedrig auflösenden AVI-Videos.
-8.2) Spielspezifische Optionen der grafischen Benutzeroberfläche
----- ---------------------------------------------------------------
+8.2) Spielspezifische Optionen bei der grafischen Benutzeroberfläche:
+---- ----------------------------------------------------------------
Viele spielspezifische Optionen, die im vorigen Abschnitt aufgeführt wurden,
können über die grafische Benutzeroberfläche angesprochen werden. Falls eine
spielspezifische Option für ein bestimmtes Spiel verfügbar ist, erscheint ein
@@ -2813,7 +2826,7 @@ aktualisiert, was die spielspezifischen Optionen zum Vorschein bringt.
9.0) Kompilieren:
----- -------------
+---- ------------
Für eine aktuelle Übersicht dazu, wie man ScummVM für unterschiedliche
Plattformen kompiliert, schauen Sie bitte in unserem Wiki nach, insbesondere auf
dieser Seite:
@@ -2821,12 +2834,12 @@ dieser Seite:
Wenn Sie für Windows, Linux oder Mac OS X kompilieren, benötigen Sie SDL-1.2.2
oder höher (ältere Versionen funktionieren möglicherweise, haben aber keinen
-Support) und einen unterstützten Compiler. Mehrere Compiler,
-einschließlich GCC, mingw und neue Versionen von Microsoft Visual C++ werden
-unterstützt. Wenn Sie mit MP3 komprimierte CD-Titel oder .SOU-Dateien verwenden
-möchten, müssen Sie die MAD-Bibliothek installieren; ebenso benötigen Sie die
-geeigneten Bibliotheken für Sound-Dateien, die mit Ogg Vorbis und FLAC
-komprimiert wurden. Für komprimierte Speicherstände ist zlib erforderlich.
+Support) und einen unterstützten Compiler. Mehrere Compiler, einschließlich GCC,
+mingw und neue Versionen von Microsoft Visual C++ werden unterstützt. Wenn Sie
+mit MP3 komprimierte CD-Titel oder .SOU-Dateien verwenden möchten, müssen Sie
+die MAD-Bibliothek installieren; ebenso benötigen Sie die geeigneten
+Bibliotheken für Sound-Dateien, die mit Ogg Vorbis und FLAC komprimiert wurden.
+Für komprimierte Speicherstände ist zlib erforderlich.
Von einigen Teilen in ScummVM, insbesondere Grafikwandlern, gibt es stark
optimierte Versionen, die in Assembler geschrieben sind. Wenn Sie diese
@@ -2843,102 +2856,103 @@ Debug-Nachrichten zu durchsuchen
Windows:
* Dev-C++
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/DevCPP>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/DevCPP
* MinGW
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW
* Visual Studio (MSVC)
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Visual_Studio>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Visual_Studio
* Windows CE/Mobile
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Windows_CE>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Windows_CE
Linux:
* GCC
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/GCC>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/GCC
AmigaOS4:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/AmigaOS>
+ http://wiki.scummvm.org/index.php/AmigaOS
Apple iPhone:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/iPhone>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/iPhone
Atari/FreeMiNT:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Atari/FreeMiNT>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Atari/FreeMiNT
Bada/Tizen:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Bada/Tizen>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Bada/Tizen
BeOS/ZETA/Haiku:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/BeOS/ZETA/Haiku>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/BeOS/ZETA/Haiku
Google Android:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Android>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Android
HP webOS:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/WebOS>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/WebOS
Mac OS:
* Mac OS X
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Mac_OS_X>
+ http://wiki.scummvm.org/index.php/Mac_OS_X
* Mac OS X 10.2.8
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_10.2.8>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_10.2.8
* Mac OS X Crosscompiling
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_Crosscompiling>
+http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_Crosscompiling
Maemo:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Maemo>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Maemo
Nintendo DS:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Nintendo_DS>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Nintendo_DS
Nintendo Wii and Gamecube:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Wii>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Wii
RaspberryPi:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/RPI>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/RPI
Sega Dreamcast:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Dreamcast>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Dreamcast
Sony Playstation:
* Sony PlayStation 2
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_2>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_2
* Sony PlayStation 3
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/PlayStation_3#Building_from_source>
+ http://wiki.scummvm.org/index.php/PlayStation_3#Building_from_source
* Sony PlayStation Portable
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_Portable>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/PlayStation_Portable
Symbian:
Weiterführende Informationen finden Sie unter:
- <http://wiki.scummvm.org/index.php/Compiling_ScummVM/Symbian>
+ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Symbian
10.0) Mitwirkende
----- -------
-Eine ausführliche Liste derjenigen, die ScummVM ermöglicht haben, finden Sie unter:
+Eine ausführliche Liste derjenigen, die ScummVM ermöglicht haben, finden Sie
+unter:
- <http://www.scummvm.org/credits/>
+ http://www.scummvm.org/credits/
------------------------------------------------------------------------
diff --git a/doc/de/Neues b/doc/de/Neues
index 1b109a91f0..ef462c189c 100644
--- a/doc/de/Neues
+++ b/doc/de/Neues
@@ -2,36 +2,50 @@ Umfangreichere Informationen über die Änderungen des aktuellen experimentellen
Programmcodes finden Sie auf Englisch unter:
https://github.com/scummvm/scummvm/commits/
-1.8.0 (??.??.????)
+1.9.0 (DD.MM.YYYY)
+ AGI:
+ - Unterstützung für Hercules-Darstellung (Grün + Bernstein) hinzugefügt
+ - Unterstützung für hochauflösende Hercules-Schriftart hinzugefügt
+ (auch außerhalb der Hercules-Darstellung nutzbar)
+ - Optionale Funktion "Pause, wenn Befehle eingegeben werden" hinzugefügt.
+ Diese Funktion war im originalen Interpreter nur im Hercules-Darstellungsmodus
+ verfügbar.
+
+
+1.8.0 (04.03.2016)
Neue Spiele:
- Unterstützung für Rex Nebular and the Cosmic Gender Bender hinzugefügt.
- Unterstützung für Sfinx hinzugefügt.
- - Unterstützung für Zork Nemesis: The Forbidden Lands hinzugefügt.
- - Unterstützung für Zork: Grand Inquisitor hinzugefügt.
- - Unterstützung für The Lost Files of Sherlock Holmes: The Case of the Serrated Scalpel
- hinzugefügt.
- - Unterstützung für The Lost Files of Sherlock Holmes: The Case of the Rose Tattoo hinzugefügt.
+ - Unterstützung für Zork Nemesis: Das verbotene Land hinzugefügt.
+ - Unterstützung für Zork: Der Großinquisitor hinzugefügt.
+ - Unterstützung für Die ungelösten Fälle von Sherlock Holmes: Das gezackte
+ Skalpell hinzugefügt.
+ - Unterstützung für Die ungelösten Fälle von Sherlock Holmes: Das Geheimnis
+ der tätowierten Rose hinzugefügt.
- Unterstützung für Beavis and Butthead in Virtual Stupidity hinzugefügt.
- Unterstützung für Amazon: Guardians of Eden hinzugefügt.
- - Unterstützung für Broken Sword 2.5: The Return of the Templars hinzugefügt.
+ - Unterstützung für Baphomets Fluch 2.5: Die Rückkehr der Tempelritter
+ hinzugefügt.
- Unterstützung für Labyrinth of Time hinzugefügt.
- Neue Portierungen:
- - Portierung auf den Raspberry Pi erfolgt.
+Neue Portierungen:
+ - Portierung für den Raspberry Pi hinzugefügt.
+ - Portierung für den GCW Zero (GCW0) hinzugefügt.
Allgemein:
- Code für Munt-MT-32-Emulation auf Version 1.5.0 aktualisiert.
SDL:
- - Alt-x beendet ScummVM nicht mehr auf Plattformen, die dieses Problem
- zuvor gezeigt haben. Ein bedeutendes Beispiel dafür ist unsere Version für Windows.
- Auf POSIX-Systemen befolgen wir nun die "XDG Base Directory Specification" für die
- Speicherung von Benutzerdaten. Dies resultiert in neuen Speicherorten für unsere
- Konfigurationsdatei, unsere Log-Datei sowie für den standardmäßig voreingestellten
- Speicherort für Spielstände. Wir unterstützen weiterhin die vorherigen Speicherorte.
- Solange diese vorhanden sind, werden wir diese weiter verwenden. Bitte beachten Sie die
- Liesmich-Datei für weitere Informationen. Speicherorte auf Mac OS X sind von dieser
- Änderung nicht betroffen.
+ - Alt+x beendet ScummVM nicht mehr. Verwenden Sie stattdessen
+ Cmd+q/Strg+q/Strg+z und beachten Sie die Hinweise in der Liesmich-Datei.
+ - Auf POSIX-Systemen befolgen wir nun die Spezifikation XDG Base Directory
+ für die Speicherung von Benutzerdaten. Dies führt zu neuen
+ Speicherorten für unsere Konfigurationsdatei, unsere Log-Datei sowie für
+ den standardmäßig voreingestellten Speicherort für Spielstände. Wir
+ unterstützen weiterhin die vorherigen Speicherorte. Solange diese vorhanden
+ sind, werden wir diese weiter verwenden. Bitte beachten Sie die
+ Liesmich-Datei für weitere Informationen. Speicherorte auf Mac OS X sind
+ von dieser Änderung nicht betroffen.
3 Skulls of the Toltecs:
- Unterstützung für AdLib-Musik verbessert.
@@ -39,17 +53,20 @@ Programmcodes finden Sie auf Englisch unter:
AGI:
- Es ist nun möglich, die Maus-Unterstützung zu deaktivieren (außer bei
Amiga-Versionen und Fan-Spielen, die eine Maus benötigen).
- - Fehlerhafte Lautstärke-Dämpfung im PCjr-Sound-Code behoben (Fehler #6858).
+ - Fehlerhafte Lautstärke in PCjr-Spielen korrigiert.
- Umfangreiche Änderung im Grafik-Subsystem.
- - Unterstützung für Übergänge, Schriftarten und Mauszeigern für Apple IIgs, Amiga + Atari.
- (die Atari ST 8x8 Systemschriftart ist nicht in ScummVM enthalten)
- - Eine PC-Version kann jetzt wie eine Apple IIgs-Version dargestellt werden.
- (inklusive Farbpalette, Cursor, Übergänge und Schriftart). Sie müssen lediglich
- den gewünschten Darstellungsmodus auswählen.
- - Unterstützung für vereinfachtes automatisches Speichern/Wiederherstellen hinzugefügt.
- (verwendet von Mixed Up Mother Goose)
- - Feste Verzögerung von 2 Sekunden bei Raumwechseln entfernt und durch Heuristik ersetzt
- - Controller (skriptgesteuerte Tastenbelegungen) werden jetzt mit abgespeichert (Fehler #5858).
+ - Unterstützung für Übergänge, Schriftarten und Mauszeigern für Apple IIgs,
+ Amiga und Atari (die Systemschriftart Atari ST 8x8 ist nicht in ScummVM
+ enthalten)
+ - Eine PC-Version kann jetzt wie eine Apple IIgs-Version dargestellt werden
+ (inklusive Farbpalette, Cursor, Übergänge und Schriftart). Sie müssen
+ lediglich den gewünschten Darstellungsmodus auswählen.
+ - Apple IIgs-Spiele laufen nicht mehr zu schnell.
+ - Unterstützung für automatisches Speichern / Laden hinzugefügt
+ (verwendet von Mixed Up Mother Goose).
+ - Feste Verzögerung von 2 Sekunden bei Raumwechseln entfernt und durch
+ Heuristik ersetzt.
+ - Fehlerhafte Tastenbelegungen nach abspeichern/laden behoben
AGOS:
- Arpeggio-Effekt in der Musik der Amiga-Version von Elvira 1 repariert.
@@ -57,19 +74,19 @@ Programmcodes finden Sie auf Englisch unter:
- Verb-Feld in der Amiga-Version von Simon the Sorcerer 1 repariert.
- Accolade AdLib- und MT32-Treiber für folgende Spiele hinzugefügt:
Elvira 1, Elvira 2, Waxworks und Simon the Sorcerer 1 (Demoversion)
- - AdLib-Ausgabe in Simon the Sorcerer 1 hinzugefügt. Dies verbessert die AdLib-
- Ausgabe erheblich und erhöht die Originaltreue.
+ - AdLib-Ausgabe in Simon the Sorcerer 1 hinzugefügt. Dies verbessert die
+ AdLib-Ausgabe erheblich und erhöht die Originaltreue.
Baphomets Fluch 1:
- - Erkennung der Byte-Reihenfolge der Sprachausgabe auf Big-Endian-Systemen
- für die Macintosh-Version (Fehler #6720) repariert.
- - Absturz beim Neuladen eines Spiels aus dem Hauptmenü heraus, während sich
- das Spiel in der Szene am Bull's Head Hill befindet, behoben
- (Fehler #6728). Dieser Fehler trat womöglich auch in anderen Szenen auf.
+ - Sprachausgabe in Macintosh-Versionen korrigiert, wenn ScumMVM
+ auf Big-Endian-Systemen ausgeführt wird.
+ - Fehler beim Laden eines Spielstandes aus dem Hauptmenü in der
+ Bull's Head Hill-Szene korrigiert. Dieser Fehler trat womöglich auch
+ in anderen Szenen auf.
CinE:
- Unterstützung für Musik in der CD-Version von Future Wars hinzugefügt.
-
+
MADE:
- Unterstützung für AdLib-Musik in Return to Zork verbessert.
@@ -79,18 +96,23 @@ Programmcodes finden Sie auf Englisch unter:
SCI:
- Behandlung der Musik-Priorität extrem verbessert.
- Viele Fehler in den originalen Skripten behoben, die auch bei
- Verwendung des originalen Interpreters auftreten:
- KQ6 (Sprache und Untertitel), LSL5, QfG1 (EGA), QfG (VGA), QfG2, QfG3,
- SQ1, SQ4 (CD)
+ Verwendung des originalen Interpreters auftreten.
+ Folgende Spiele sind davon betroffen:
+ KQ6 (Sprache und Untertitel), LSL5, PQ1, QfG1 (EGA), QfG (VGA),
+ QfG2, QfG3, SQ1, SQ4 (CD)
- Rückkehr aus dem ScummVM-Menü im Spiel sollte nun immer funktionieren.
- Verbesserte Unterstützung für japanische PC-9801-Spiele
+ - Verwende standardmäßig die hochauflösende Version von KQ6
+ (kann in den Spieloptionen umgeschaltet werden)
SCUMM:
- Umfangreiche Verbesserung der Textdarstellung in koreanischen Versionen
- - Originaler Code der Gang-Animation in Maniac Mansion v0-v1 hinzugefügt
+ - Originaler Code der Geh-Animation in Maniac Mansion v0-v1 hinzugefügt.
- Es ist nun möglich, Maniac Mansion innerhalb von Day of the
Tentacle zu spielen. Bitte Liesmich-Datei für weitere Details lesen.
- - Alt-x kann jetzt auf allen Plattformen dazu verwendet werden, SCUMM-Spiele zu beenden.
+ - Alt+x kann jetzt auf allen Plattformen dazu verwendet werden, SCUMM-Spiele
+ zu beenden.
+ - Lippensynchronisation in neueren Spielen von Humongous Entertainment verbessert.
Tinsel:
- Unterstützung für AdLib-Musik in Discworld 1 verbessert.
diff --git a/engines/access/access.cpp b/engines/access/access.cpp
index bc9bcb4b08..c12761af4a 100644
--- a/engines/access/access.cpp
+++ b/engines/access/access.cpp
@@ -436,20 +436,9 @@ void AccessEngine::copyBF1BF2() {
}
void AccessEngine::copyBF2Vid() {
- const byte *srcP = (const byte *)_buffer2.getPixels();
- byte *destP = (byte *)_screen->getBasePtr(_screen->_windowXAdd,
- _screen->_windowYAdd + _screen->_screenYOff);
-
- for (int yp = 0; yp < _screen->_vWindowLinesTall; ++yp) {
- Common::copy(srcP, srcP + _screen->_vWindowBytesWide, destP);
- srcP += _buffer2.pitch;
- destP += _screen->pitch;
- }
-
- // Add dirty rect for affected area
- Common::Rect r(_screen->_vWindowBytesWide, _screen->_vWindowLinesTall);
- r.moveTo(_screen->_windowXAdd, _screen->_windowYAdd + _screen->_screenYOff);
- _screen->addDirtyRect(r);
+ _screen->blitFrom(_buffer2,
+ Common::Rect(0, 0, _screen->_vWindowBytesWide, _screen->_vWindowLinesTall),
+ Common::Point(_screen->_windowXAdd, _screen->_windowYAdd));
}
void AccessEngine::playVideo(int videoNum, const Common::Point &pt) {
diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp
index f693e6a3a0..2518ff6ad8 100644
--- a/engines/access/asurface.cpp
+++ b/engines/access/asurface.cpp
@@ -110,7 +110,7 @@ void ImageEntryList::addToList(ImageEntry &ie) {
int ASurface::_clipWidth;
int ASurface::_clipHeight;
-ASurface::ASurface(): Graphics::Surface() {
+ASurface::ASurface(): Graphics::ManagedSurface() {
_leftSkip = _rightSkip = 0;
_topSkip = _bottomSkip = 0;
_lastBoundsX = _lastBoundsY = 0;
@@ -122,65 +122,14 @@ ASurface::ASurface(): Graphics::Surface() {
}
ASurface::~ASurface() {
- free();
_savedBlock.free();
}
-void ASurface::create(uint16 width, uint16 height) {
- Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-}
-
void ASurface::clearBuffer() {
byte *pSrc = (byte *)getPixels();
Common::fill(pSrc, pSrc + w * h, 0);
}
-bool ASurface::clip(Common::Rect &r) {
- int skip;
- _leftSkip = _rightSkip = 0;
- _topSkip = _bottomSkip = 0;
-
- if (r.left > _clipWidth || r.left < 0) {
- if (r.left >= 0)
- return true;
-
- skip = -r.left;
- r.setWidth(r.width() - skip);
- _leftSkip = skip;
- r.moveTo(0, r.top);
- }
-
- int right = r.right - 1;
- if (right < 0)
- return true;
- else if (right > _clipWidth) {
- skip = right - _clipWidth;
- r.setWidth(r.width() - skip);
- _rightSkip = skip;
- }
-
- if (r.top > _clipHeight || r.top < 0) {
- if (r.top >= 0)
- return true;
-
- skip = -r.top;
- r.setHeight(r.height() - skip);
- _topSkip = skip;
- r.moveTo(r.left, 0);
- }
-
- int bottom = r.bottom - 1;
- if (bottom < 0)
- return true;
- else if (bottom > _clipHeight) {
- skip = bottom - _clipHeight;
- _bottomSkip = skip;
- r.setHeight(r.height() - skip);
- }
-
- return false;
-}
-
void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt) {
SpriteFrame *frame = sprite->getFrame(frameNum);
Common::Rect r(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h);
@@ -195,81 +144,7 @@ void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Poi
}
}
-void ASurface::transBlitFrom(ASurface *src, const Common::Point &destPos) {
- if (getPixels() == nullptr)
- create(w, h);
-
- for (int yp = 0; yp < src->h; ++yp) {
- const byte *srcP = (const byte *)src->getBasePtr(0, yp);
- byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
-
- for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
- if (*srcP != TRANSPARENCY)
- *destP = *srcP;
- }
- }
-}
-
-void ASurface::transBlitFrom(ASurface *src, const Common::Rect &bounds) {
- const int SCALE_LIMIT = 0x100;
- int scaleX = SCALE_LIMIT * bounds.width() / src->w;
- int scaleY = SCALE_LIMIT * bounds.height() / src->h;
- int scaleXCtr = 0, scaleYCtr = 0;
-
- for (int yCtr = 0, destY = bounds.top; yCtr < src->h; ++yCtr) {
- // Handle skipping lines if Y scaling
- scaleYCtr += scaleY;
- if (scaleYCtr < SCALE_LIMIT)
- continue;
- scaleYCtr -= SCALE_LIMIT;
-
- // Handle off-screen lines
- if (destY >= this->h)
- break;
-
- if (destY >= 0) {
- // Handle drawing the line
- const byte *pSrc = (const byte *)src->getBasePtr(0, yCtr);
- byte *pDest = (byte *)getBasePtr(bounds.left, destY);
- scaleXCtr = 0;
- int x = bounds.left;
-
- for (int xCtr = 0; xCtr < src->w; ++xCtr, ++pSrc) {
- // Handle horizontal scaling
- scaleXCtr += scaleX;
- if (scaleXCtr < SCALE_LIMIT)
- continue;
- scaleXCtr -= SCALE_LIMIT;
-
- // Only handle on-screen pixels
- if (x >= this->w)
- break;
- if (x >= 0 && *pSrc != 0)
- *pDest = *pSrc;
-
- ++pDest;
- ++x;
- }
- }
-
- ++destY;
- }
-}
-
-void ASurface::transBlitFrom(ASurface &src) {
- blitFrom(src);
-}
-
-void ASurface::blitFrom(const Graphics::Surface &src) {
- assert(w >= src.w && h >= src.h);
- for (int y = 0; y < src.h; ++y) {
- const byte *srcP = (const byte *)src.getBasePtr(0, y);
- byte *destP = (byte *)getBasePtr(0, y);
- Common::copy(srcP, srcP + src.w, destP);
- }
-}
-
-void ASurface::copyBuffer(Graphics::Surface *src) {
+void ASurface::copyBuffer(Graphics::ManagedSurface *src) {
blitFrom(*src);
}
@@ -282,14 +157,11 @@ void ASurface::plotB(SpriteFrame *frame, const Common::Point &pt) {
}
void ASurface::sPlotF(SpriteFrame *frame, const Common::Rect &bounds) {
- transBlitFrom(frame, bounds);
+ transBlitFrom(*frame, Common::Rect(0, 0, frame->w, frame->h), bounds, TRANSPARENCY, false);
}
void ASurface::sPlotB(SpriteFrame *frame, const Common::Rect &bounds) {
- ASurface flippedFrame;
- frame->flipHorizontal(flippedFrame);
-
- transBlitFrom(&flippedFrame, bounds);
+ transBlitFrom(*frame, Common::Rect(0, 0, frame->w, frame->h), bounds, TRANSPARENCY, true);
}
void ASurface::copyBlock(ASurface *src, const Common::Rect &bounds) {
@@ -324,22 +196,22 @@ void ASurface::restoreBlock() {
}
void ASurface::drawRect() {
- Graphics::Surface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor);
+ Graphics::ManagedSurface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor);
}
void ASurface::drawLine(int x1, int y1, int x2, int y2, int col) {
- Graphics::Surface::drawLine(x1, y1, x2, y2, col);
+ Graphics::ManagedSurface::drawLine(x1, y1, x2, y2, col);
}
void ASurface::drawLine() {
- Graphics::Surface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
+ Graphics::ManagedSurface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
}
void ASurface::drawBox() {
- Graphics::Surface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
- Graphics::Surface::drawLine(_orgX1, _orgY2, _orgX2, _orgY2, _lColor);
- Graphics::Surface::drawLine(_orgX2, _orgY1, _orgX2, _orgY1, _lColor);
- Graphics::Surface::drawLine(_orgX2, _orgY2, _orgX2, _orgY2, _lColor);
+ Graphics::ManagedSurface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
+ Graphics::ManagedSurface::drawLine(_orgX1, _orgY2, _orgX2, _orgY2, _lColor);
+ Graphics::ManagedSurface::drawLine(_orgX2, _orgY1, _orgX2, _orgY1, _lColor);
+ Graphics::ManagedSurface::drawLine(_orgX2, _orgY2, _orgX2, _orgY2, _lColor);
}
void ASurface::flipHorizontal(ASurface &dest) {
@@ -373,4 +245,50 @@ void ASurface::moveBufferDown() {
Common::copy_backward(p, p + (pitch * (h - TILE_HEIGHT)), p + (pitch * h));
}
+bool ASurface::clip(Common::Rect &r) {
+ int skip;
+ _leftSkip = _rightSkip = 0;
+ _topSkip = _bottomSkip = 0;
+
+ if (r.left > _clipWidth || r.left < 0) {
+ if (r.left >= 0)
+ return true;
+
+ skip = -r.left;
+ r.setWidth(r.width() - skip);
+ _leftSkip = skip;
+ r.moveTo(0, r.top);
+ }
+
+ int right = r.right - 1;
+ if (right < 0)
+ return true;
+ else if (right > _clipWidth) {
+ skip = right - _clipWidth;
+ r.setWidth(r.width() - skip);
+ _rightSkip = skip;
+ }
+
+ if (r.top > _clipHeight || r.top < 0) {
+ if (r.top >= 0)
+ return true;
+
+ skip = -r.top;
+ r.setHeight(r.height() - skip);
+ _topSkip = skip;
+ r.moveTo(r.left, 0);
+ }
+
+ int bottom = r.bottom - 1;
+ if (bottom < 0)
+ return true;
+ else if (bottom > _clipHeight) {
+ skip = bottom - _clipHeight;
+ _bottomSkip = skip;
+ r.setHeight(r.height() - skip);
+ }
+
+ return false;
+}
+
} // End of namespace Access
diff --git a/engines/access/asurface.h b/engines/access/asurface.h
index dd05c8067b..ec18ec09c3 100644
--- a/engines/access/asurface.h
+++ b/engines/access/asurface.h
@@ -27,7 +27,7 @@
#include "common/array.h"
#include "common/memstream.h"
#include "common/rect.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
#include "access/data.h"
namespace Access {
@@ -35,7 +35,7 @@ namespace Access {
class SpriteResource;
class SpriteFrame;
-class ASurface : public Graphics::Surface {
+class ASurface : virtual public Graphics::ManagedSurface {
private:
Graphics::Surface _savedBlock;
@@ -61,14 +61,8 @@ public:
virtual ~ASurface();
- void create(uint16 width, uint16 height);
-
- bool empty() const { return w == 0 || h == 0 || pixels == nullptr; }
-
void clearBuffer();
- bool clip(Common::Rect &r);
-
void plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt);
/**
@@ -102,18 +96,8 @@ public:
virtual void drawLine();
virtual void drawBox();
-
- virtual void transBlitFrom(ASurface *src, const Common::Point &destPos);
-
- virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds);
- virtual void transBlitFrom(ASurface &src);
-
- virtual void blitFrom(const Graphics::Surface &src);
-
- virtual void copyBuffer(Graphics::Surface *src);
-
- virtual void addDirtyRect(const Common::Rect &r) {}
+ virtual void copyBuffer(Graphics::ManagedSurface *src);
void copyTo(ASurface *dest);
@@ -126,6 +110,8 @@ public:
void moveBufferUp();
void moveBufferDown();
+
+ bool clip(Common::Rect &r);
};
class SpriteFrame : public ASurface {
diff --git a/engines/access/detection.cpp b/engines/access/detection.cpp
index 7494c9c047..2cd7e50f0f 100644
--- a/engines/access/detection.cpp
+++ b/engines/access/detection.cpp
@@ -146,7 +146,6 @@ SaveStateList AccessMetaEngine::listSaves(const char *target) const {
Access::AccessSavegameHeader header;
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
@@ -167,6 +166,8 @@ SaveStateList AccessMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/access/detection_tables.h b/engines/access/detection_tables.h
index 9556cd9f67..7d9509ca43 100644
--- a/engines/access/detection_tables.h
+++ b/engines/access/detection_tables.h
@@ -49,7 +49,7 @@ static const AccessGameDescription gameDescriptions[] = {
AD_ENTRY1s("c00.ap", "aeb429ff015596144c0df06886c84825", 303753),
Common::ES_ESP,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
+ ADGF_UNSTABLE,
GUIO1(GUIO_NONE)
},
GType_Amazon,
diff --git a/engines/access/events.cpp b/engines/access/events.cpp
index d62b05c33f..21ff0d0928 100644
--- a/engines/access/events.cpp
+++ b/engines/access/events.cpp
@@ -115,7 +115,7 @@ void EventsManager::setCursor(CursorType cursorId) {
}
}
-void EventsManager::setCursorData(Graphics::Surface *src, const Common::Rect &r) {
+void EventsManager::setCursorData(Graphics::ManagedSurface *src, const Common::Rect &r) {
_invCursor.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8());
_invCursor.copyRectToSurface(*src, 0, 0, r);
}
@@ -281,8 +281,7 @@ void EventsManager::nextFrame() {
// Give time to the debugger
_vm->_debugger->onFrame();
- // TODO: Refactor for dirty rects
- _vm->_screen->updateScreen();
+ _vm->_screen->update();
}
void EventsManager::nextTimer() {
diff --git a/engines/access/events.h b/engines/access/events.h
index b8c5f0ee5e..5acbb71c9d 100644
--- a/engines/access/events.h
+++ b/engines/access/events.h
@@ -100,7 +100,7 @@ public:
/**
* Set the image for the inventory cursor
*/
- void setCursorData(Graphics::Surface *src, const Common::Rect &r);
+ void setCursorData(Graphics::ManagedSurface *src, const Common::Rect &r);
/**
* Return the current cursor Id
diff --git a/engines/access/files.cpp b/engines/access/files.cpp
index b9c0f7080d..48276ee477 100644
--- a/engines/access/files.cpp
+++ b/engines/access/files.cpp
@@ -130,13 +130,13 @@ void FileManager::openFile(Resource *res, const Common::String &filename) {
error("Could not open file - %s", filename.c_str());
}
-void FileManager::loadScreen(Graphics::Surface *dest, int fileNum, int subfile) {
+void FileManager::loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile) {
Resource *res = loadFile(fileNum, subfile);
handleScreen(dest, res);
delete res;
}
-void FileManager::handleScreen(Graphics::Surface *dest, Resource *res) {
+void FileManager::handleScreen(Graphics::ManagedSurface *dest, Resource *res) {
_vm->_screen->loadRawPalette(res->_stream);
if (_setPaletteFlag)
_vm->_screen->setPalette();
@@ -147,20 +147,17 @@ void FileManager::handleScreen(Graphics::Surface *dest, Resource *res) {
res->_size -= res->_stream->pos();
handleFile(res);
- if (dest != _vm->_screen)
- dest->w = _vm->_screen->w;
+ Graphics::Surface destSurface = dest->getSubArea(Common::Rect(0, 0,
+ _vm->_screen->w, _vm->_screen->h));
- if (dest->w == dest->pitch) {
- res->_stream->read((byte *)dest->getPixels(), dest->w * dest->h);
+ if (destSurface.w == destSurface.pitch) {
+ res->_stream->read((byte *)destSurface.getPixels(), destSurface.w * destSurface.h);
} else {
- for (int y = 0; y < dest->h; ++y) {
- byte *pDest = (byte *)dest->getBasePtr(0, y);
- res->_stream->read(pDest, dest->w);
+ for (int y = 0; y < destSurface.h; ++y) {
+ byte *pDest = (byte *)destSurface.getBasePtr(0, y);
+ res->_stream->read(pDest, destSurface.w);
}
}
-
- if (dest == _vm->_screen)
- _vm->_screen->addDirtyRect(Common::Rect(0, 0, dest->w, dest->h));
}
void FileManager::loadScreen(int fileNum, int subfile) {
diff --git a/engines/access/files.h b/engines/access/files.h
index d081934e91..61fccc2431 100644
--- a/engines/access/files.h
+++ b/engines/access/files.h
@@ -26,7 +26,7 @@
#include "common/scummsys.h"
#include "common/array.h"
#include "common/file.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
#include "access/decompress.h"
namespace Access {
@@ -81,7 +81,7 @@ private:
/**
* Handles loading a screen surface and palette with decoded resource
*/
- void handleScreen(Graphics::Surface *dest, Resource *res);
+ void handleScreen(Graphics::ManagedSurface *dest, Resource *res);
/**
* Open up a sub-file container file
@@ -133,7 +133,7 @@ public:
/**
* Load a screen resource onto a designated surface
*/
- void loadScreen(Graphics::Surface *dest, int fileNum, int subfile);
+ void loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile);
};
} // End of namespace Access
diff --git a/engines/access/font.cpp b/engines/access/font.cpp
index 8af183f193..6ae65e43f0 100644
--- a/engines/access/font.cpp
+++ b/engines/access/font.cpp
@@ -151,13 +151,12 @@ void Font::drawString(ASurface *s, const Common::String &msg, const Common::Poin
int Font::drawChar(ASurface *s, char c, Common::Point &pt) {
Graphics::Surface &ch = _chars[c - ' '];
-
- s->addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h));
+ Graphics::Surface dest = s->getSubArea(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h));
// Loop through the lines of the character
for (int y = 0; y < ch.h; ++y) {
byte *pSrc = (byte *)ch.getBasePtr(0, y);
- byte *pDest = (byte *)s->getBasePtr(pt.x, pt.y + y);
+ byte *pDest = (byte *)dest.getBasePtr(0, y);
// Loop through the horizontal pixels of the line
for (int x = 0; x < ch.w; ++x, ++pSrc, ++pDest) {
diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp
index aa15abd59a..9700640b71 100644
--- a/engines/access/screen.cpp
+++ b/engines/access/screen.cpp
@@ -69,8 +69,6 @@ void Screen::clearScreen() {
clearBuffer();
if (_vesaMode)
_vm->_clearSummaryFlag = true;
-
- addDirtyRect(Common::Rect(0, 0, this->w, this->h));
}
void Screen::setDisplayScan() {
@@ -89,28 +87,14 @@ void Screen::setPanel(int num) {
_msVirtualOffset = _virtualOffsetsTable[num];
}
-void Screen::updateScreen() {
+void Screen::update() {
if (_vm->_startup >= 0) {
if (--_vm->_startup == -1)
_fadeIn = true;
return;
}
-
- // Merge the dirty rects
- mergeDirtyRects();
-
- // Loop through copying dirty areas to the physical screen
- Common::List<Common::Rect>::iterator i;
- for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
- const Common::Rect &r = *i;
- const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
- g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
- r.width(), r.height());
- }
-
- // Signal the physical screen to update
- g_system->updateScreen();
- _dirtyRects.clear();
+ markAllDirty();//****DEBUG****
+ Graphics::Screen::update();
}
void Screen::setInitialPalettte() {
@@ -153,7 +137,7 @@ void Screen::loadRawPalette(Common::SeekableReadStream *stream) {
void Screen::updatePalette() {
g_system->getPaletteManager()->setPalette(&_tempPalette[0], 0, PALETTE_COUNT);
- updateScreen();
+ update();
}
void Screen::savePalette() {
@@ -293,22 +277,7 @@ void Screen::drawBox() {
ASurface::drawBox();
}
-void Screen::transBlitFrom(ASurface *src, const Common::Point &destPos) {
- addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src->w, destPos.y + src->h));
- ASurface::transBlitFrom(src, destPos);
-}
-
-void Screen::transBlitFrom(ASurface *src, const Common::Rect &bounds) {
- addDirtyRect(bounds);
- ASurface::transBlitFrom(src, bounds);
-}
-
-void Screen::blitFrom(const Graphics::Surface &src) {
- addDirtyRect(Common::Rect(0, 0, src.w, src.h));
- ASurface::blitFrom(src);
-}
-
-void Screen::copyBuffer(Graphics::Surface *src) {
+void Screen::copyBuffer(Graphics::ManagedSurface *src) {
addDirtyRect(Common::Rect(0, 0, src->w, src->h));
ASurface::copyBuffer(src);
}
@@ -349,51 +318,7 @@ void Screen::cyclePaletteBackwards() {
}
void Screen::flashPalette(int count) {
- warning("TODO: Implement flashPalette");
-}
-
-void Screen::addDirtyRect(const Common::Rect &r) {
- _dirtyRects.push_back(r);
- assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
-}
-
-void Screen::mergeDirtyRects() {
- Common::List<Common::Rect>::iterator rOuter, rInner;
-
- // Ensure dirty rect list has at least two entries
- rOuter = _dirtyRects.begin();
- for (int i = 0; i < 2; ++i, ++rOuter) {
- if (rOuter == _dirtyRects.end())
- return;
- }
-
- // Process the dirty rect list to find any rects to merge
- for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
- rInner = rOuter;
- while (++rInner != _dirtyRects.end()) {
-
- if ((*rOuter).intersects(*rInner)) {
- // these two rectangles overlap or
- // are next to each other - merge them
-
- unionRectangle(*rOuter, *rOuter, *rInner);
-
- // remove the inner rect from the list
- _dirtyRects.erase(rInner);
-
- // move back to beginning of list
- rInner = rOuter;
- }
- }
- }
+ // No implementation needed in ScummVM
}
-bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
- destRect = src1;
- destRect.extend(src2);
-
- return !destRect.isEmpty();
-}
-
-
} // End of namespace Access
diff --git a/engines/access/screen.h b/engines/access/screen.h
index 6fa0fe3812..a022741f91 100644
--- a/engines/access/screen.h
+++ b/engines/access/screen.h
@@ -26,15 +26,13 @@
#include "common/scummsys.h"
#include "common/rect.h"
#include "common/stream.h"
+#include "graphics/screen.h"
#include "access/asurface.h"
namespace Access {
class AccessEngine;
-#define PALETTE_COUNT 256
-#define PALETTE_SIZE (256 * 3)
-
struct ScreenSave {
int _clipWidth;
int _clipHeight;
@@ -47,7 +45,7 @@ struct ScreenSave {
int _screenYOff;
};
-class Screen : public ASurface {
+class Screen : public virtual ASurface, public virtual Graphics::Screen {
private:
AccessEngine *_vm;
byte _tempPalette[PALETTE_SIZE];
@@ -66,10 +64,6 @@ private:
Common::List<Common::Rect> _dirtyRects;
void updatePalette();
-
- void mergeDirtyRects();
-
- bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
public:
int _vesaMode;
int _startColor, _numColors;
@@ -87,6 +81,11 @@ public:
bool _screenChangeFlag;
bool _fadeIn;
public:
+ /**
+ * Updates the screen
+ */
+ virtual void update();
+
virtual void copyBlock(ASurface *src, const Common::Rect &bounds);
virtual void restoreBlock();
@@ -95,15 +94,7 @@ public:
virtual void drawBox();
- virtual void transBlitFrom(ASurface *src, const Common::Point &destPos);
-
- virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds);
-
- virtual void blitFrom(const Graphics::Surface &src);
-
- virtual void copyBuffer(Graphics::Surface *src);
-
- virtual void addDirtyRect(const Common::Rect &r);
+ virtual void copyBuffer(Graphics::ManagedSurface *src);
public:
Screen(AccessEngine *vm);
@@ -114,11 +105,6 @@ public:
void setPanel(int num);
/**
- * Update the underlying screen
- */
- void updateScreen();
-
- /**
* Fade out screen
*/
void forceFadeOut();
diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp
index 7c354e78e5..38313640f1 100644
--- a/engines/access/scripts.cpp
+++ b/engines/access/scripts.cpp
@@ -1005,10 +1005,7 @@ void Scripts::cmdFreeSound() {
} while (!_vm->shouldQuit() && sound.isSFXPlaying());
// Free the sounds
- while (sound._soundTable.size() > 0) {
- delete sound._soundTable[0]._res;
- sound._soundTable.remove_at(0);
- }
+ sound.freeSounds();
}
}
diff --git a/engines/access/video.cpp b/engines/access/video.cpp
index 5fc5f6762c..e3ff457c3b 100644
--- a/engines/access/video.cpp
+++ b/engines/access/video.cpp
@@ -157,7 +157,7 @@ void VideoPlayer::playVideo() {
// If the video is playing on the screen surface, add a dirty rect
if (_vidSurface == _vm->_screen)
- _vm->_screen->addDirtyRect(_videoBounds);
+ _vm->_screen->markAllDirty();
getFrame();
if (++_videoFrame == _frameCount) {
diff --git a/engines/access/video/movie_decoder.cpp b/engines/access/video/movie_decoder.cpp
index 05ec25d54c..1406e549ad 100644
--- a/engines/access/video/movie_decoder.cpp
+++ b/engines/access/video/movie_decoder.cpp
@@ -719,7 +719,7 @@ bool AccessEngine::playMovie(const Common::String &filename, const Common::Point
g_system->getPaletteManager()->setPalette(palette, 0, 256);
}
- _screen->updateScreen();
+ _screen->update();
}
}
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index 72629a833e..7a09f662d1 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -41,8 +41,8 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa
title = g.extra;
extra = "";
} else {
- while (sg->gameid) {
- if (!scumm_stricmp(g.gameid, sg->gameid))
+ while (sg->gameId) {
+ if (!scumm_stricmp(g.gameId, sg->gameId))
title = sg->description;
sg++;
}
@@ -56,7 +56,7 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa
else if (g.flags & ADGF_TESTING)
gsl = kTestingGame;
- GameDescriptor gd(g.gameid, title, g.language, g.platform, 0, gsl);
+ GameDescriptor gd(g.gameId, title, g.language, g.platform, 0, gsl);
gd.updateDesc(extra);
return gd;
}
@@ -89,21 +89,38 @@ static Common::String generatePreferredTarget(const Common::String &id, const AD
return res;
}
+static Common::String sanitizeName(const char *name) {
+ Common::String res;
+
+ while (*name) {
+ if (Common::isAlnum(*name))
+ res += tolower(*name);
+ name++;
+ }
+
+ return res;
+}
+
void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const {
- if (_singleid != NULL) {
+ if (_singleId != NULL) {
desc["preferredtarget"] = desc["gameid"];
- desc["gameid"] = _singleid;
+ desc["gameid"] = _singleId;
}
if (!desc.contains("preferredtarget"))
desc["preferredtarget"] = desc["gameid"];
+ if (realDesc->flags & ADGF_AUTOGENTARGET) {
+ if (*realDesc->extra)
+ desc["preferredtarget"] = sanitizeName(realDesc->extra);
+ }
+
desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc);
if (_flags & kADFlagUseExtraAsHint)
desc["extra"] = realDesc->extra;
- desc.setGUIOptions(realDesc->guioptions + _guioptions);
+ desc.setGUIOptions(realDesc->guiOptions + _guiOptions);
desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language));
if (realDesc->flags & ADGF_ADDENGLISH)
@@ -149,7 +166,7 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
// Use fallback detector if there were no matches by other means
const ADGameDescription *fallbackDesc = fallbackDetect(allFiles, fslist);
if (fallbackDesc != 0) {
- GameDescriptor desc(toGameDescriptor(*fallbackDesc, _gameids));
+ GameDescriptor desc(toGameDescriptor(*fallbackDesc, _gameIds));
updateGameDescriptor(desc, fallbackDesc);
detectedGames.push_back(desc);
}
@@ -157,7 +174,7 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
// Otherwise use the found matches
cleanupPirated(matches);
for (uint i = 0; i < matches.size(); i++) {
- GameDescriptor desc(toGameDescriptor(*matches[i], _gameids));
+ GameDescriptor desc(toGameDescriptor(*matches[i], _gameIds));
updateGameDescriptor(desc, matches[i]);
detectedGames.push_back(desc);
}
@@ -252,10 +269,10 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
if (cleanupPirated(matches))
return Common::kNoGameDataFoundError;
- if (_singleid == NULL) {
+ if (_singleId == NULL) {
// Find the first match with correct gameid.
for (uint i = 0; i < matches.size(); i++) {
- if (matches[i]->gameid == gameid) {
+ if (matches[i]->gameId == gameid) {
agdDesc = matches[i];
break;
}
@@ -270,7 +287,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
if (agdDesc != 0) {
// Seems we found a fallback match. But first perform a basic
// sanity check: the gameid must match.
- if (_singleid == NULL && agdDesc->gameid != gameid)
+ if (_singleId == NULL && agdDesc->gameId != gameid)
agdDesc = 0;
}
}
@@ -284,9 +301,9 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
if (agdDesc->flags & ADGF_ADDENGLISH)
lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY);
- Common::updateGameGUIOptions(agdDesc->guioptions + _guioptions, lang);
+ Common::updateGameGUIOptions(agdDesc->guiOptions + _guiOptions, lang);
- GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameids);
+ GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameIds);
bool showTestingWarning = false;
@@ -407,7 +424,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
// Check which files are included in some ADGameDescription *and* are present.
// Compute MD5s and file sizes for these files.
- for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += _descItemSize) {
+ for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize) {
g = (const ADGameDescription *)descPtr;
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
@@ -430,7 +447,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
// MD5 based matching
uint i;
- for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameid != 0; descPtr += _descItemSize, ++i) {
+ for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize, ++i) {
g = (const ADGameDescription *)descPtr;
bool fileMissing = false;
@@ -487,7 +504,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
gotAnyMatchesWithAllFiles = true;
if (!fileMissing) {
- debug(2, "Found game: %s (%s %s/%s) (%d)", g->gameid, g->extra,
+ debug(2, "Found game: %s (%s %s/%s) (%d)", g->gameId, g->extra,
getPlatformDescription(g->platform), getLanguageDescription(g->language), i);
if (curFilesMatched > maxFilesMatched) {
@@ -503,7 +520,7 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
}
} else {
- debug(5, "Skipping game: %s (%s %s/%s) (%d)", g->gameid, g->extra,
+ debug(5, "Skipping game: %s (%s %s/%s) (%d)", g->gameId, g->extra,
getPlatformDescription(g->platform), getLanguageDescription(g->language), i);
}
}
@@ -543,7 +560,7 @@ const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &
}
if (!fileMissing) {
- debug(4, "Matched: %s", agdesc->gameid);
+ debug(4, "Matched: %s", agdesc->gameId);
if (numMatchedFiles > maxNumMatchedFiles) {
matchedDesc = agdesc;
@@ -568,27 +585,27 @@ const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &
}
GameList AdvancedMetaEngine::getSupportedGames() const {
- if (_singleid != NULL) {
+ if (_singleId != NULL) {
GameList gl;
- const PlainGameDescriptor *g = _gameids;
- while (g->gameid) {
- if (0 == scumm_stricmp(_singleid, g->gameid)) {
- gl.push_back(GameDescriptor(g->gameid, g->description));
+ const PlainGameDescriptor *g = _gameIds;
+ while (g->gameId) {
+ if (0 == scumm_stricmp(_singleId, g->gameId)) {
+ gl.push_back(GameDescriptor(g->gameId, g->description));
return gl;
}
g++;
}
- error("Engine %s doesn't have its singleid specified in ids list", _singleid);
+ error("Engine %s doesn't have its singleid specified in ids list", _singleId);
}
- return GameList(_gameids);
+ return GameList(_gameIds);
}
-GameDescriptor AdvancedMetaEngine::findGame(const char *gameid) const {
+GameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const {
// First search the list of supported gameids for a match.
- const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, _gameids);
+ const PlainGameDescriptor *g = findPlainGameDescriptor(gameId, _gameIds);
if (g)
return GameDescriptor(*g);
@@ -596,14 +613,14 @@ GameDescriptor AdvancedMetaEngine::findGame(const char *gameid) const {
return GameDescriptor();
}
-AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameids, const ADExtraGuiOptionsMap *extraGuiOptions)
- : _gameDescriptors((const byte *)descs), _descItemSize(descItemSize), _gameids(gameids),
+AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds, const ADExtraGuiOptionsMap *extraGuiOptions)
+ : _gameDescriptors((const byte *)descs), _descItemSize(descItemSize), _gameIds(gameIds),
_extraGuiOptions(extraGuiOptions) {
_md5Bytes = 5000;
- _singleid = NULL;
+ _singleId = NULL;
_flags = 0;
- _guioptions = GUIO_NONE;
+ _guiOptions = GUIO_NONE;
_maxScanDepth = 1;
_directoryGlobs = NULL;
}
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index ad551698f6..ab3ec22bdc 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -81,6 +81,7 @@ typedef Common::HashMap<Common::String, ADFileProperties, Common::IgnoreCase_Has
enum ADGameFlags {
ADGF_NO_FLAGS = 0,
+ ADGF_AUTOGENTARGET = (1 << 20), // automatically generate gameid from extra
ADGF_UNSTABLE = (1 << 21), // flag to designate not yet officially-supported games that are not fit for public testing
ADGF_TESTING = (1 << 22), // flag to designate not yet officially-supported games that are fit for public testing
ADGF_PIRATED = (1 << 23), ///< flag to designate well known pirated versions with cracks
@@ -94,7 +95,7 @@ enum ADGameFlags {
};
struct ADGameDescription {
- const char *gameid;
+ const char *gameId;
const char *extra;
ADGameFileDescription filesDescriptions[14];
Common::Language language;
@@ -107,7 +108,7 @@ struct ADGameDescription {
*/
uint32 flags;
- const char *guioptions;
+ const char *guiOptions;
};
/**
@@ -191,7 +192,7 @@ protected:
* A list of all gameids (and their corresponding descriptions) supported
* by this engine.
*/
- const PlainGameDescriptor *_gameids;
+ const PlainGameDescriptor *_gameIds;
/**
* A map containing all the extra game GUI options the engine supports.
@@ -219,7 +220,7 @@ protected:
* address a more generic problem. We should find a better way to
* disambiguate gameids.
*/
- const char *_singleid;
+ const char *_singleId;
/**
* A bitmask of flags which can be used to configure the behavior
@@ -233,7 +234,7 @@ protected:
* entry in addition to per-game options. Refer to GameGUIOption
* enum for the list.
*/
- Common::String _guioptions;
+ Common::String _guiOptions;
/**
* Maximum depth of directories to look up.
@@ -251,7 +252,7 @@ protected:
const char * const *_directoryGlobs;
public:
- AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameids, const ADExtraGuiOptionsMap *extraGuiOptions = 0);
+ AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds, const ADExtraGuiOptionsMap *extraGuiOptions = 0);
/**
* Returns list of targets supported by the engine.
@@ -259,7 +260,7 @@ public:
*/
virtual GameList getSupportedGames() const;
- virtual GameDescriptor findGame(const char *gameid) const;
+ virtual GameDescriptor findGame(const char *gameId) const;
virtual GameList detectGames(const Common::FSList &fslist) const;
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index bcf84840d2..6e63cd3e71 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -283,18 +283,7 @@ void AgiBase::initRenderMode() {
switch (platform) {
case Common::kPlatformDOS:
- switch (configRenderMode) {
- case Common::kRenderCGA:
- _renderMode = Common::kRenderCGA;
- break;
- // Hercules is not supported atm
- //case Common::kRenderHercA:
- //case Common::kRenderHercG:
- // _renderMode = Common::kRenderHercG;
- // break;
- default:
- break;
- }
+ // Keep EGA
break;
case Common::kPlatformAmiga:
_renderMode = Common::kRenderAmiga;
@@ -323,6 +312,12 @@ void AgiBase::initRenderMode() {
case Common::kRenderVGA:
_renderMode = Common::kRenderVGA;
break;
+ case Common::kRenderHercG:
+ _renderMode = Common::kRenderHercG;
+ break;
+ case Common::kRenderHercA:
+ _renderMode = Common::kRenderHercA;
+ break;
case Common::kRenderAmiga:
_renderMode = Common::kRenderAmiga;
break;
@@ -401,6 +396,11 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
setupOpcodes();
_game._curLogic = NULL;
+ _veryFirstInitialCycle = true;
+ _instructionCounter = 0;
+ resetGetVarSecondsHeuristic();
+
+ _setVolumeBrokenFangame = false; // for further study see AgiEngine::setVolumeViaScripts()
_lastSaveTime = 0;
@@ -461,7 +461,7 @@ void AgiEngine::initialize() {
_console = new Console(this);
_words = new Words(this);
_font = new GfxFont(this);
- _gfx = new GfxMgr(this);
+ _gfx = new GfxMgr(this, _font);
_sound = new SoundMgr(this, _mixer);
_picture = new PictureMgr(this, _gfx);
_sprites = new SpritesMgr(this, _gfx);
@@ -470,6 +470,8 @@ void AgiEngine::initialize() {
_inventory = new InventoryMgr(this, _gfx, _text, _systemUI);
_font->init();
+ _gfx->initVideo();
+
_text->init(_systemUI);
_game.gameFlags = 0;
@@ -478,8 +480,6 @@ void AgiEngine::initialize() {
_game.name[0] = '\0';
- _gfx->initVideo();
-
_lastSaveTime = 0;
debugC(2, kDebugLevelMain, "Detect game");
@@ -507,19 +507,6 @@ void AgiEngine::redrawScreen() {
_text->promptRedraw();
}
-// Adjust a given coordinate to the local game screen
-// Used on mouse cursor coordinates before passing them to scripts
-void AgiEngine::adjustPosToGameScreen(int16 &x, int16 &y) {
- x = x / 2; // 320 -> 160
- y = y - _gfx->getRenderStartOffsetY(); // remove status bar line
- if (y < 0) {
- y = 0;
- }
- if (y >= SCRIPT_HEIGHT) {
- y = SCRIPT_HEIGHT + 1; // 1 beyond
- }
-}
-
AgiEngine::~AgiEngine() {
agiDeinit();
delete _loader;
@@ -563,17 +550,28 @@ void AgiEngine::syncSoundSettings() {
setVolumeViaSystemSetting();
}
+// WORKAROUND:
+// Sometimes Sierra printed some text on the screen and did a room change immediately afterwards expecting the
+// interpreter to load the data for a bit of time. This of course doesn't happen in our AGI, so we try to
+// detect such situations via heuristic and then delay the game for a bit.
+// In those cases a wait mouse cursor will be shown.
+//
// Scenes that need this:
//
+// Gold Rush:
+// - During Stagecoach path, after getting solving the steep hill "Congratulations!!!" (NewRoom)
+// - when following your mule "Yet right on his tail!!!" (NewRoom/NewPicture - but room 123 stays the same)
// Manhunter 1:
// - intro text screen (DrawPic)
// - MAD "zooming in..." during intro and other scenes, for example room 124 (NewRoom)
// The NewRoom call is not done during the same cycle as the "zooming in..." print call.
// Space Quest 1:
// - right at the start of the game (NewRoom)
+// - right at the end of the asteroids "That was mighty close!" (NewRoom)
// Space Quest 2
// - right at the start of the game (NewRoom)
// - after exiting the very first room, a message pops up, that isn't readable without it (NewRoom)
+// - Climbing into shuttle on planet Labion. "You open the hatch and head on in." (NewRoom)
// Games, that must not be triggered:
@@ -590,7 +588,14 @@ void AgiEngine::nonBlockingText_Forget() {
_game.nonBlockingTextShown = false;
_game.nonBlockingTextCyclesLeft = 0;
}
-void AgiEngine::nonBlockingText_CycleDone() {
+
+void AgiEngine::artificialDelay_Reset() {
+ nonBlockingText_Forget();
+ _artificialDelayCurrentRoom = -1;
+ _artificialDelayCurrentPicture = -1;
+}
+
+void AgiEngine::artificialDelay_CycleDone() {
if (_game.nonBlockingTextCyclesLeft) {
_game.nonBlockingTextCyclesLeft--;
@@ -601,30 +606,97 @@ void AgiEngine::nonBlockingText_CycleDone() {
}
}
-void AgiEngine::loadingTrigger_NewRoom(int16 newRoomNr) {
- if (_game.nonBlockingTextShown) {
- _game.nonBlockingTextShown = false;
+// WORKAROUND:
+// On Apple IIgs, there are situations like for example the Police Quest 1 intro, where music is playing
+// and then the scripts switch to a new room, expecting it to load for a bit of time. In ScummVM this results
+// in music getting cut off, because our loading is basically done in an instant. This also happens in the
+// original interpreter, when you use a faster CPU in emulation.
+//
+// That's why there is an additional table, where one can add such situations to it.
+// These issues are basically impossible to detect, because sometimes music is also supposed to play throughout
+// multiple rooms.
+//
+// Normally all text-based issues should get detected by the current heuristic. Do not add those in here.
+
+// script, description, signature patch
+static const AgiArtificialDelayEntry artificialDelayTable[] = {
+ { GID_GOLDRUSH, Common::kPlatformApple2GS, ARTIFICIALDELAYTYPE_NEWROOM, 14, 21, 2200 }, // Stagecoach path: right after getting on it in Brooklyn
+ { GID_PQ1, Common::kPlatformApple2GS, ARTIFICIALDELAYTYPE_NEWPICTURE, 1, 2, 2200 }, // Intro: music track is supposed to finish before credits screen. Developers must have assumed that room loading would take that long.
+ { GID_MH1, Common::kPlatformApple2GS, ARTIFICIALDELAYTYPE_NEWPICTURE, 155, 183, 2200 }, // Happens, when hitting fingers at bar
+ { GID_AGIDEMO, Common::kPlatformUnknown, ARTIFICIALDELAYTYPE_END, -1, -1, 0 }
+};
- int16 curRoomNr = getVar(VM_VAR_CURRENT_ROOM);
+uint16 AgiEngine::artificialDelay_SearchTable(AgiArtificialDelayTriggerType triggerType, int16 orgNr, int16 newNr) {
+ if (getPlatform() != Common::kPlatformApple2GS) {
+ return 0;
+ }
+
+ const AgiArtificialDelayEntry *delayEntry = artificialDelayTable;
- if (newRoomNr != curRoomNr) {
- if (!_game.automaticRestoreGame) {
- // wait a bit, we detected non-blocking text
- wait(2000, true); // 2 seconds, set busy
+ while (delayEntry->triggerType != ARTIFICIALDELAYTYPE_END) {
+ if (triggerType == delayEntry->triggerType) {
+ if ((orgNr == delayEntry->orgNr) && (newNr == delayEntry->newNr)) {
+ if ((getGameID() == delayEntry->gameId) && (getPlatform() == delayEntry->platform)) {
+ warning("artificial delay forced");
+ return delayEntry->millisecondsDelay;
+ }
}
}
+
+ delayEntry++;
}
+ return 0;
}
-void AgiEngine::loadingTrigger_DrawPicture() {
- if (_game.nonBlockingTextShown) {
- _game.nonBlockingTextShown = false;
+void AgiEngine::artificialDelayTrigger_NewRoom(int16 newRoomNr) {
+ uint16 millisecondsDelay = 0;
- if (!_game.automaticRestoreGame) {
- // wait a bit, we detected non-blocking text
- wait(2000, true); // 2 seconds, set busy
+ //warning("artificial delay trigger: room %d -> new room %d", _artificialDelayCurrentRoom, newRoomNr);
+
+ if (!_game.automaticRestoreGame) {
+ millisecondsDelay = artificialDelay_SearchTable(ARTIFICIALDELAYTYPE_NEWROOM, _artificialDelayCurrentRoom, newRoomNr);
+
+ if (_game.nonBlockingTextShown) {
+ if (newRoomNr != _artificialDelayCurrentRoom) {
+ if (millisecondsDelay < 2000) {
+ // wait a bit, we detected non-blocking text
+ millisecondsDelay = 2000; // 2 seconds
+ }
+ }
+ }
+
+ if (millisecondsDelay) {
+ wait(millisecondsDelay, true); // set busy mouse cursor
+ _game.nonBlockingTextShown = false;
+ }
+ }
+
+ _artificialDelayCurrentRoom = newRoomNr;
+}
+
+void AgiEngine::artificialDelayTrigger_DrawPicture(int16 newPictureNr) {
+ uint16 millisecondsDelay = 0;
+
+ //warning("artificial delay trigger: picture %d -> new picture %d", _artificialDelayCurrentPicture, newPictureNr);
+
+ if (!_game.automaticRestoreGame) {
+ millisecondsDelay = artificialDelay_SearchTable(ARTIFICIALDELAYTYPE_NEWPICTURE, _artificialDelayCurrentPicture, newPictureNr);
+
+ if (_game.nonBlockingTextShown) {
+ if (newPictureNr != _artificialDelayCurrentPicture) {
+ if (millisecondsDelay < 2000) {
+ // wait a bit, we detected non-blocking text
+ millisecondsDelay = 2000; // 2 seconds, set busy
+ }
+ }
+ }
+
+ if (millisecondsDelay) {
+ wait(millisecondsDelay, true); // set busy mouse cursor
+ _game.nonBlockingTextShown = false;
}
}
+ _artificialDelayCurrentPicture = newPictureNr;
}
} // End of namespace Agi
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 93017af099..b288557f57 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -148,17 +148,17 @@ enum BooterDisks {
// position and position.v.
//
enum AgiGameFeatures {
- GF_AGIMOUSE = (1 << 0),
+ GF_AGIMOUSE = (1 << 0), // this disables "Click-to-walk mouse interface"
GF_AGDS = (1 << 1),
- GF_AGI256 = (1 << 2),
- GF_AGI256_2 = (1 << 3),
- GF_AGIPAL = (1 << 4),
- GF_MACGOLDRUSH = (1 << 5),
- GF_FANMADE = (1 << 6),
- GF_MENUS = (1 << 7),
- GF_ESCPAUSE = (1 << 8),
+ GF_AGI256 = (1 << 2), // marks fanmade AGI-256 games
+ GF_AGI256_2 = (1 << 3), // marks fanmade AGI-256-2 games
+ GF_AGIPAL = (1 << 4), // marks game using fanmade AGIPAL extension
+ GF_MACGOLDRUSH = (1 << 5), // use "grdir" instead of "dir" for volume loading
+ GF_FANMADE = (1 << 6), // marks fanmade games
+ GF_MENUS = (1 << 7), // not used anymore
+ GF_ESCPAUSE = (1 << 8), // not used anymore, we detect this internally
GF_OLDAMIGAV20 = (1 << 9),
- GF_CLIPCOORDS = (1 << 10),
+ GF_CLIPCOORDS = (1 << 10), // not used atm
GF_2GSOLDSOUND = (1 << 11)
};
@@ -704,6 +704,21 @@ public:
}
};
+enum AgiArtificialDelayTriggerType {
+ ARTIFICIALDELAYTYPE_NEWROOM = 0,
+ ARTIFICIALDELAYTYPE_NEWPICTURE = 1,
+ ARTIFICIALDELAYTYPE_END = -1
+};
+
+struct AgiArtificialDelayEntry {
+ uint32 gameId;
+ Common::Platform platform;
+ AgiArtificialDelayTriggerType triggerType;
+ int16 orgNr;
+ int16 newNr;
+ uint16 millisecondsDelay;
+};
+
typedef void (*AgiCommand)(AgiGame *state, AgiEngine *vm, uint8 *p);
class AgiEngine : public AgiBase {
@@ -724,8 +739,6 @@ public:
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &description);
- void adjustPosToGameScreen(int16 &x, int16 &y);
-
private:
int _keyQueue[KEY_QUEUE_SIZE];
int _keyQueueStart;
@@ -746,7 +759,7 @@ public:
SavedGameSlotIdArray getSavegameSlotIds();
Common::String getSavegameFilename(int16 slotId) const;
- bool getSavegameInformation(int16 slotId, Common::String &saveDescription, uint32 &saveDate, uint16 &saveTime, bool &saveIsValid);
+ bool getSavegameInformation(int16 slotId, Common::String &saveDescription, uint32 &saveDate, uint32 &saveTime, bool &saveIsValid);
int saveGame(const Common::String &fileName, const Common::String &descriptionString);
int loadGame(const Common::String &fileName, bool checkId = true);
@@ -847,6 +860,21 @@ public:
int testIfCode(int);
void executeAgiCommand(uint8, uint8 *);
+private:
+ bool _veryFirstInitialCycle; /**< signals, that currently the very first cycle is executed (restarts, etc. do not count!) */
+ uint32 _instructionCounter; /**< counts every instruction, that got executed, can wrap around */
+
+ bool _setVolumeBrokenFangame;
+
+ void resetGetVarSecondsHeuristic();
+ void getVarSecondsHeuristicTrigger();
+ uint32 _getVarSecondsHeuristicLastInstructionCounter; /**< last time VM_VAR_SECONDS were read */
+ uint16 _getVarSecondsHeuristicCounter; /**< how many times heuristic was triggered */
+
+ uint32 _playTimeInSecondsAdjust; /**< milliseconds to adjust for calculating current play time in seconds, see setVarSecondsTrigger() */
+
+ void setVarSecondsTrigger(byte newSeconds);
+
public:
// Some submethods of testIfCode
void skipInstruction(byte op);
@@ -899,6 +927,8 @@ private:
void checkMotion(ScreenObjEntry *screenObj);
public:
+ void motionActivated(ScreenObjEntry *screenObj);
+ void cyclerActivated(ScreenObjEntry *screenObj);
void checkAllMotions();
void moveObj(ScreenObjEntry *screenObj);
void inDestination(ScreenObjEntry *screenObj);
@@ -924,10 +954,18 @@ public:
void nonBlockingText_IsShown();
void nonBlockingText_Forget();
- void nonBlockingText_CycleDone();
- void loadingTrigger_NewRoom(int16 newRoomNr);
- void loadingTrigger_DrawPicture();
+ void artificialDelay_Reset();
+ void artificialDelay_CycleDone();
+
+ uint16 artificialDelay_SearchTable(AgiArtificialDelayTriggerType triggerType, int16 orgNr, int16 newNr);
+
+ void artificialDelayTrigger_NewRoom(int16 newRoomNr);
+ void artificialDelayTrigger_DrawPicture(int16 newPictureNr);
+
+private:
+ int16 _artificialDelayCurrentRoom;
+ int16 _artificialDelayCurrentPicture;
public:
void redrawScreen();
diff --git a/engines/agi/appleIIgs_timedelay_overwrite.h b/engines/agi/appleIIgs_timedelay_overwrite.h
new file mode 100644
index 0000000000..c24d7cb5bd
--- /dev/null
+++ b/engines/agi/appleIIgs_timedelay_overwrite.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 AGI_APPLEIIGS_DELAY_OVERWRITE_H
+#define AGI_APPLEIIGS_DELAY_OVERWRITE_H
+
+namespace Agi {
+
+struct AgiAppleIIgsDelayOverwriteRoomEntry {
+ int16 fromRoom;
+ int16 toRoom;
+ int16 timeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles
+ bool onlyWhenPlayerNotInControl;
+};
+
+struct AgiAppleIIgsDelayOverwriteGameEntry {
+ uint32 gameId;
+ int16 defaultTimeDelayOverwrite; // time delay here is like on PC, so 0 - unlimited, 1 - 20 cycles, 2 - 10 cycles
+ const AgiAppleIIgsDelayOverwriteRoomEntry *roomTable;
+};
+
+static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteKQ4[] = {
+ { 120, 121, -1, true }, // Part of the intro: Graham gets his hat, throws it and breaks down, don't touch speed (3 is set)
+ { 128, 128, -1, true }, // Part of the intro: first actual room for gameplay, but during intro, don't touch speed (3 is set)
+ { 92, 92, -1, true }, // Part of caught by gargoyle w/ Lolotte cutscene (3 is set)
+ // room 54 sets the speed for a short time to 3 right after entering "clean" command. It doesn't seem to hurt that we switch it down to 2
+ // room 92 is dual use, part of cutscenes, part of gameplay, that's why we only stop touching it, when player is not in control
+ { 135, 135, -1, true }, // Part of ending cutscene. Don't touch speed (3 is set)
+ { -1, -1, -1, false }
+};
+
+static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteMH1[] = {
+ //{ 153, 153, 2, false }, // Intro w/ credits
+ //{ 104, 104, 2, false }, // Intro cutscene
+ //{ 117, 117, 2, false }, // Intro cutscene (ego waking up)
+ { 114, 114, -1, false }, // interactive MAD map
+ { 124, 125, -1, false }, // MAD during intro (tracking), seem to work properly at given speed
+ { 132, 133, -1, false }, // MAD day 2 intro (tracking)
+ { 137, 137, -1, false }, // Night Club 4th arcade game - game sets speed to 7
+ { 115, 116, -1, false }, // MAD day 3 intro (tracking)
+ { 148, 148, -1, false }, // day 3: arcade sequence under pawn shop (game sets speed to 6)
+ { 103, 103, -1, false }, // MAD day 4 intro (tracking)
+ { 105, 105, -1, false }, // day 4 tracking mini game right at the start (game sets speed to 3)
+ { 107, 107, -1, false }, // MAD day 4 intro (tracking)
+ { 112, 112, -1, false }, // MAD day 4 intro (tracking)
+ { -1, -1, -1, false }
+};
+
+static const AgiAppleIIgsDelayOverwriteRoomEntry appleIIgsDelayOverwriteSQ2[] = {
+ { 1, 1, -1, false }, // Intro: space ship entering space port, don't touch speed
+ { -1, -1, -1, false }
+};
+
+static const AgiAppleIIgsDelayOverwriteGameEntry appleIIgsDelayOverwriteGameTable[] = {
+ { GID_BC, 2, nullptr }, // sets the speed at the start and doesn't modify it
+ { GID_GOLDRUSH, 2, nullptr },
+ { GID_KQ1, 2, nullptr },
+ // KQ2 seems to work fine at speed given by scripts
+ { GID_KQ3, 2, nullptr },
+ { GID_KQ4, 2, appleIIgsDelayOverwriteKQ4 },
+ { GID_LSL1, 2, nullptr }, // Switch Larry 1 to 10 cycles per second (that's around PC Larry 1's "normal" speed
+ { GID_MH1, 2, appleIIgsDelayOverwriteMH1 },
+ { GID_MIXEDUP, 2, nullptr },
+ { GID_PQ1, 2, nullptr },
+ { GID_SQ1, 2, nullptr }, // completed, no issues using these settings
+ { GID_SQ2, 2, appleIIgsDelayOverwriteSQ2 },
+ { GID_AGIDEMO, -1, nullptr }
+};
+
+} // End of namespace Agi
+
+#endif /* AGI_APPLEIIGS_DELAY_OVERWRITE_H */
diff --git a/engines/agi/checks.cpp b/engines/agi/checks.cpp
index 1e1670f674..c67b6a5810 100644
--- a/engines/agi/checks.cpp
+++ b/engines/agi/checks.cpp
@@ -129,7 +129,7 @@ bool AgiEngine::checkPriority(ScreenObjEntry *screenObj) {
screenPriority = _gfx->getPriority(curX, curY);
if (screenPriority == 0) { // unconditional black. no go at all!
- touchedControl = 0;
+ touchedControl = false;
break;
}
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index 6419e60219..9a4a357b44 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -33,27 +33,28 @@ namespace Agi {
Console::Console(AgiEngine *vm) : GUI::Debugger() {
_vm = vm;
- registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug));
- registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont));
- registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver));
- registerCmd("version", WRAP_METHOD(Console, Cmd_Version));
- registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags));
- registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0));
- registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs));
- registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
- registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode));
- registerCmd("step", WRAP_METHOD(Console, Cmd_Step));
- registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger));
- registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars));
- registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar));
- registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
- registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj));
- registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
- registerCmd("bt", WRAP_METHOD(Console, Cmd_BT));
- registerCmd("show_map", WRAP_METHOD(Console, Cmd_ShowMap));
- registerCmd("screenobj", WRAP_METHOD(Console, Cmd_ScreenObj));
- registerCmd("vmvars", WRAP_METHOD(Console, Cmd_VmVars));
- registerCmd("vmflags", WRAP_METHOD(Console, Cmd_VmFlags));
+ registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug));
+ registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont));
+ registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver));
+ registerCmd("version", WRAP_METHOD(Console, Cmd_Version));
+ registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags));
+ registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0));
+ registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs));
+ registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode));
+ registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode));
+ registerCmd("step", WRAP_METHOD(Console, Cmd_Step));
+ registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger));
+ registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars));
+ registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar));
+ registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag));
+ registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj));
+ registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
+ registerCmd("bt", WRAP_METHOD(Console, Cmd_BT));
+ registerCmd("show_map", WRAP_METHOD(Console, Cmd_ShowMap));
+ registerCmd("screenobj", WRAP_METHOD(Console, Cmd_ScreenObj));
+ registerCmd("vmvars", WRAP_METHOD(Console, Cmd_VmVars));
+ registerCmd("vmflags", WRAP_METHOD(Console, Cmd_VmFlags));
+ registerCmd("disableautosave", WRAP_METHOD(Console, Cmd_DisableAutomaticSave));
}
bool Console::Cmd_SetVar(int argc, const char **argv) {
@@ -609,6 +610,18 @@ bool Console::Cmd_VmFlags(int argc, const char **argv) {
return true;
}
+bool Console::Cmd_DisableAutomaticSave(int argc, const char **argv) {
+ if (!_vm->_game.automaticSave) {
+ debugPrintf("Automatic saving is currently not enabled\n");
+ return true;
+ }
+
+ _vm->_game.automaticSave = false;
+
+ debugPrintf("Automatic saving DISABLED!\n");
+ return true;
+}
+
bool Console::parseInteger(const char *argument, int &result) {
char *endPtr = 0;
int idxLen = strlen(argument);
diff --git a/engines/agi/console.h b/engines/agi/console.h
index 41dc9ddabc..ccc17b31de 100644
--- a/engines/agi/console.h
+++ b/engines/agi/console.h
@@ -66,6 +66,7 @@ private:
bool Cmd_ScreenObj(int argc, const char **argv);
bool Cmd_VmVars(int argc, const char **argv);
bool Cmd_VmFlags(int argc, const char **argv);
+ bool Cmd_DisableAutomaticSave(int argc, const char **argv);
bool parseInteger(const char *argument, int &result);
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 17c9c873cc..19aca6f2c4 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -30,6 +30,7 @@
#include "agi/keyboard.h"
#include "agi/menu.h"
#include "agi/systemui.h"
+#include "agi/appleIIgs_timedelay_overwrite.h"
namespace Agi {
@@ -44,7 +45,7 @@ void AgiEngine::newRoom(int16 newRoomNr) {
int i;
// Loading trigger
- loadingTrigger_NewRoom(newRoomNr);
+ artificialDelayTrigger_NewRoom(newRoomNr);
debugC(4, kDebugLevelMain, "*** room %d ***", newRoomNr);
_sound->stopSound();
@@ -141,6 +142,9 @@ void AgiEngine::interpretCycle() {
oldScore = getVar(VM_VAR_SCORE);
oldSound = getFlag(VM_FLAG_SOUND_ON);
+ // Reset script heuristic here
+ resetGetVarSecondsHeuristic();
+
_game.exitAllLogics = false;
while (runLogic(0) == 0 && !(shouldQuit() || _restartGame)) {
setVar(VM_VAR_WORD_NOT_FOUND, 0);
@@ -149,10 +153,12 @@ void AgiEngine::interpretCycle() {
oldScore = getVar(VM_VAR_SCORE);
setFlag(VM_FLAG_ENTERED_CLI, false);
_game.exitAllLogics = false;
- nonBlockingText_CycleDone();
+ _veryFirstInitialCycle = false;
+ artificialDelay_CycleDone();
resetControllers();
}
- nonBlockingText_CycleDone();
+ _veryFirstInitialCycle = false;
+ artificialDelay_CycleDone();
resetControllers();
screenObjEgo->direction = getVar(VM_VAR_EGO_DIRECTION);
@@ -219,9 +225,10 @@ uint16 AgiEngine::processAGIEvents() {
// no inner loop active at the moment, regular processing
if (key) {
- setVar(VM_VAR_KEY, key & 0xFF);
if (!handleController(key)) {
if (key) {
+ // Only set VAR_KEY, when no controller/direction was detected
+ setVar(VM_VAR_KEY, key & 0xFF);
if (_text->promptIsEnabled()) {
_text->promptKeyPress(key);
}
@@ -288,6 +295,8 @@ uint16 AgiEngine::processAGIEvents() {
int AgiEngine::playGame() {
int ec = errOK;
+ const AgiAppleIIgsDelayOverwriteGameEntry *appleIIgsDelayOverwrite = nullptr;
+ const AgiAppleIIgsDelayOverwriteRoomEntry *appleIIgsDelayRoomOverwrite = nullptr;
debugC(2, kDebugLevelMain, "initializing...");
debugC(2, kDebugLevelMain, "game version = 0x%x", getVersion());
@@ -306,7 +315,7 @@ int AgiEngine::playGame() {
setFlag(VM_FLAG_LOGIC_ZERO_FIRST_TIME, true); // not in 2.917
setFlag(VM_FLAG_NEW_ROOM_EXEC, true); // needed for MUMG and SQ2!
setFlag(VM_FLAG_SOUND_ON, true); // enable sound
- setVar(VM_VAR_TIME_DELAY, 2); // "normal" speed
+ // do not set VM_VAR_TIME_DELAY, original AGI did not do it (in the data segment it was simply set to 0)
_game.gfxMode = true;
_text->promptRow_Set(22);
@@ -335,7 +344,17 @@ int AgiEngine::playGame() {
}
}
- nonBlockingText_Forget();
+ artificialDelay_Reset();
+
+ if (getPlatform() == Common::kPlatformApple2GS) {
+ // Look up, if there is a time delay overwrite table for the current game
+ appleIIgsDelayOverwrite = appleIIgsDelayOverwriteGameTable;
+ while (appleIIgsDelayOverwrite->gameId != GID_AGIDEMO) {
+ if (appleIIgsDelayOverwrite->gameId == getGameID())
+ break; // game found
+ appleIIgsDelayOverwrite++;
+ }
+ }
do {
processAGIEvents();
@@ -352,6 +371,46 @@ int AgiEngine::playGame() {
// Normally that game runs at TIME_DELAY 1.
// Maybe a script patch for this game would make sense.
// TODO: needs further investigation
+
+ int16 timeDelayOverwrite = -99;
+
+ // Now check, if we got a time delay overwrite entry for current room
+ if (appleIIgsDelayOverwrite->roomTable) {
+ byte curRoom = getVar(VM_VAR_CURRENT_ROOM);
+
+ appleIIgsDelayRoomOverwrite = appleIIgsDelayOverwrite->roomTable;
+ while (appleIIgsDelayRoomOverwrite->fromRoom >= 0) {
+ if ((appleIIgsDelayRoomOverwrite->fromRoom <= curRoom) && (appleIIgsDelayRoomOverwrite->toRoom >= curRoom)) {
+ if (appleIIgsDelayRoomOverwrite->onlyWhenPlayerNotInControl) {
+ if (_game.playerControl) {
+ // Player is actually currently in control? -> then skip this entry
+ appleIIgsDelayRoomOverwrite++;
+ continue;
+ }
+ }
+ timeDelayOverwrite = appleIIgsDelayRoomOverwrite->timeDelayOverwrite;
+ break;
+ }
+ appleIIgsDelayRoomOverwrite++;
+ }
+
+ if (timeDelayOverwrite == -99) {
+ // use default time delay in case no room specific one was found
+ timeDelayOverwrite = appleIIgsDelayOverwrite->defaultTimeDelayOverwrite;
+ }
+ } else {
+ timeDelayOverwrite = appleIIgsDelayOverwrite->defaultTimeDelayOverwrite;
+ }
+
+ if (timeDelayOverwrite >= 0) {
+ if (timeDelayOverwrite != timeDelay) {
+ // delayOverwrite is not the same as the delay taken from the scripts? overwrite it
+ //warning("AppleIIgs: time delay overwrite from %d to %d", timeDelay, timeDelayOverwrite);
+
+ setVar(VM_VAR_TIME_DELAY, timeDelayOverwrite - 1); // adjust for Apple IIgs
+ timeDelay = timeDelayOverwrite;
+ }
+ }
}
if (_passedPlayTimeCycles >= timeDelay) {
@@ -396,7 +455,7 @@ int AgiEngine::runGame() {
if (_restartGame) {
setFlag(VM_FLAG_RESTART_GAME, true);
- setVar(VM_VAR_TIME_DELAY, 2); // "normal" speed
+ // do not set VM_VAR_TIME_DELAY, original AGI did not do it
// Reset in-game timer
inGameTimerReset();
@@ -438,7 +497,13 @@ int AgiEngine::runGame() {
break;
case Common::kRenderHercA:
case Common::kRenderHercG:
- setVar(VM_VAR_MONITOR, kAgiMonitorHercules);
+ // Set EGA for now. Some games place text differently, when this is set to kAgiMonitorHercules.
+ // Text placement was different for Hercules rendering (16x12 instead of 16x16). There also was
+ // not enough space left for the prompt at the bottom. This was caused by the Hercules resolution.
+ // We don't have this restriction and we also support the regular prompt for Hercules mode.
+ // In theory Sierra could have had special Hercules code inside their games.
+ // TODO: check this.
+ setVar(VM_VAR_MONITOR, kAgiMonitorEga);
break;
// Don't know if Amiga AGI games use a different value than kAgiMonitorEga
// for vMonitor so I just use kAgiMonitorEga for them (As was done before too).
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 6fca86db63..9f66d78d80 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -171,6 +171,26 @@ static const ADExtraGuiOptionsMap optionsList[] = {
}
},
+ {
+ GAMEOPTION_USE_HERCULES_FONT,
+ {
+ _s("Use Hercules hires font"),
+ _s("Uses Hercules hires font, when font file is available."),
+ "herculesfont",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_COMMAND_PROMPT_WINDOW,
+ {
+ _s("Pause when entering commands"),
+ _s("Shows a command prompt window and pauses the game (like in SCI) instead of a real-time prompt."),
+ "commandpromptwindow",
+ false
+ }
+ },
+
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
@@ -182,8 +202,8 @@ class AgiMetaEngine : public AdvancedMetaEngine {
public:
AgiMetaEngine() : AdvancedMetaEngine(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames, optionsList) {
- _singleid = "agi";
- _guioptions = GUIO1(GUIO_NOSPEECH);
+ _singleId = "agi";
+ _guiOptions = GUIO1(GUIO_NOSPEECH);
}
virtual const char *getName() const {
@@ -261,7 +281,6 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -299,6 +318,8 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -359,6 +380,9 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
uint32 saveDate = in->readUint32BE();
uint16 saveTime = in->readUint16BE();
+ if (saveVersion >= 9) {
+ in->readByte(); // skip over seconds of saveTime (not needed here)
+ }
if (saveVersion >= 6) {
uint32 playTime = in->readUint32BE();
descriptor.setPlayTime(playTime * 1000);
@@ -543,13 +567,13 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
// Override the gameid & extra values in g_fallbackDesc.desc. This only works
// until the fallback detector is called again, and while the MetaEngine instance
// is alive (as else the string storage is modified/deleted).
- g_fallbackDesc.desc.gameid = _gameid.c_str();
+ g_fallbackDesc.desc.gameId = _gameid.c_str();
g_fallbackDesc.desc.extra = _extra.c_str();
Common::String fallbackWarning;
fallbackWarning = "Your game version has been detected using fallback matching as a\n";
- fallbackWarning += Common::String::format("variant of %s (%s).\n", g_fallbackDesc.desc.gameid, g_fallbackDesc.desc.extra);
+ fallbackWarning += Common::String::format("variant of %s (%s).\n", g_fallbackDesc.desc.gameId, g_fallbackDesc.desc.extra);
fallbackWarning += "If this is an original and unmodified version or new made Fanmade game,\n";
fallbackWarning += "please report any, information previously printed by ScummVM to the team.\n";
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 8da255d9ee..0938e9d4d6 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -24,12 +24,14 @@ namespace Agi {
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
#define GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE GUIO_GAMEOPTIONS2
-#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
+#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
+#define GAMEOPTION_USE_HERCULES_FONT GUIO_GAMEOPTIONS4
+#define GAMEOPTION_COMMAND_PROMPT_WINDOW GUIO_GAMEOPTIONS5
// TODO: properly implement GAMEOPTIONs
-#define GAMEOPTIONS_DEFAULT GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE)
-#define GAMEOPTIONS_AMIGA GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE)
-#define GAMEOPTIONS_FANMADE_MOUSE GUIO1(GAMEOPTION_ORIGINAL_SAVELOAD)
+#define GAMEOPTIONS_DEFAULT GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
+#define GAMEOPTIONS_AMIGA GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
+#define GAMEOPTIONS_FANMADE_MOUSE GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW)
#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \
{ \
@@ -573,7 +575,14 @@ static const AGIGameDescription gameDescriptions[] = {
GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2),
// Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
- GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS),
+ // We have to see this as AGI < 2.936, because otherwise a set.pri.base call would somewhat break
+ // priority in SQ2, when entering Vohaul's vault.
+ // The Apple IIgs AGI included with SQ2 is the same as the one included with KQ3.
+ // We currently consider KQ3 IIgs to be a 2.917-equivalent.
+ // The SQ2 IIgs AGI definitely has 177 kernel functions, but it seems that Sierra shuffled the last few around / added a few extras at the end.
+ // For KQ3 set.pri.base is called with parameters that seem to be sound resources, which means
+ // set.pri.base was possibly discard.sound. For KQ4 onwards it seems this was cleaned up.
+ GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2917, GID_SQ2, Common::kPlatformApple2GS),
{
// Space Quest 2 (Amiga) 2.0F
@@ -849,6 +858,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"),
FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"),
FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"),
+ FANMADE("The 13th Disciple (v1.01)", "58e3ec1b9ac1a79901c472aaa59db832"),
FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"),
FANMADE("The Gourd of the Beans", "246f4d94946afb547482d44a53616d06"),
FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"),
diff --git a/engines/agi/font.cpp b/engines/agi/font.cpp
index 670c1bf575..f9605e4a3d 100644
--- a/engines/agi/font.cpp
+++ b/engines/agi/font.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/config-manager.h"
#include "agi/agi.h"
#include "agi/font.h"
#include "agi/text.h"
@@ -31,6 +32,7 @@ GfxFont::GfxFont(AgiBase *vm) {
_fontData = nullptr;
_fontDataAllocated = nullptr;
+ _fontIsHires = false;
}
GfxFont::~GfxFont() {
@@ -619,52 +621,71 @@ static const uint8 fontData_ExtendedRussian[] = {
};
void GfxFont::init() {
- switch (_vm->_renderMode) {
- case Common::kRenderAmiga:
- // Try user-file first, if that fails use our internal inaccurate topaz font
- loadFontScummVMFile("agi-font-amiga.bin");
- if (!_fontData) {
- loadFontAmigaPseudoTopaz();
+ if (ConfMan.getBool("herculesfont")) {
+ // User wants, that we use Hercules hires font, try to load it
+ loadFontHercules();
+ } else {
+ switch (_vm->_renderMode) {
+ case Common::kRenderHercA:
+ case Common::kRenderHercG:
+ // Render mode is Hercules, we try to load Hercules hires font
+ loadFontHercules();
+ break;
+ default:
+ break;
}
- break;
- case Common::kRenderApple2GS:
- // Special font, stored in file AGIFONT
- loadFontAppleIIgs();
- break;
- case Common::kRenderAtariST:
- // TODO: Atari ST uses another font
- // Seems to be the standard Atari ST 8x8 system font
- loadFontScummVMFile("agi-font-atarist.bin");
- if (!_fontData) {
- loadFontAtariST("agi-font-atarist-system.fnt");
+ }
+
+ if (!_fontData) {
+ switch (_vm->_renderMode) {
+ case Common::kRenderAmiga:
+ // Try user-file first, if that fails use our internal inaccurate topaz font
+ loadFontScummVMFile("agi-font-amiga.bin");
if (!_fontData) {
- // TODO: in case we find a recreation of the font, add it in here
+ loadFontAmigaPseudoTopaz();
}
- }
- break;
- case Common::kRenderCGA:
- case Common::kRenderEGA:
- case Common::kRenderVGA:
- switch (_vm->getGameID()) {
- case GID_MICKEY:
- // load mickey mouse font from interpreter file
- loadFontMickey();
break;
+ case Common::kRenderApple2GS:
+ // Special font, stored in file AGIFONT
+ loadFontAppleIIgs();
+ break;
+ case Common::kRenderAtariST:
+ // TODO: Atari ST uses another font
+ // Seems to be the standard Atari ST 8x8 system font
+ loadFontScummVMFile("agi-font-atarist.bin");
+ if (!_fontData) {
+ loadFontAtariST("agi-font-atarist-system.fnt");
+ if (!_fontData) {
+ // TODO: in case we find a recreation of the font, add it in here
+ }
+ }
+ break;
+ case Common::kRenderHercA:
+ case Common::kRenderHercG:
+ case Common::kRenderCGA:
+ case Common::kRenderEGA:
+ case Common::kRenderVGA:
+ switch (_vm->getGameID()) {
+ case GID_MICKEY:
+ // load mickey mouse font from interpreter file
+ loadFontMickey();
+ break;
+ default:
+ loadFontScummVMFile("agi-font-dos.bin");
+ break;
+ }
+ break;
+
default:
- loadFontScummVMFile("agi-font-dos.bin");
break;
}
- break;
-
- default:
- break;
- }
- if (!_fontData) {
- // no font assigned?
- // use regular PC-BIOS font (taken from Dos-Box with a few modifications)
- _fontData = fontData_PCBIOS;
- debug("AGI: Using PC-BIOS font");
+ if (!_fontData) {
+ // no font assigned?
+ // use regular PC-BIOS font (taken from Dos-Box with a few modifications)
+ _fontData = fontData_PCBIOS;
+ debug("AGI: Using PC-BIOS font");
+ }
}
if (_vm->getLanguage() == Common::RU_RUS) {
@@ -678,6 +699,10 @@ const byte *GfxFont::getFontData() {
return _fontData;
}
+bool GfxFont::isFontHires() {
+ return _fontIsHires;
+}
+
void GfxFont::overwriteSaveRestoreDialogCharacter() {
// overwrite character 0x1A with the standard Sierra arrow to the right character
// required for the original save/restore dialogs
@@ -686,6 +711,11 @@ void GfxFont::overwriteSaveRestoreDialogCharacter() {
// Overwrite extended character set (0x80-0xFF) with Russian characters
void GfxFont::overwriteExtendedWithRussianSet() {
+ if (_fontIsHires) {
+ // TODO: Implement overwriting hires font characters too
+ return;
+ }
+
if (!_fontDataAllocated) {
// nothing allocated, we need to allocate space ourselves to be able to modify an internal font
_fontDataAllocated = (uint8 *)calloc(256, 8);
@@ -829,6 +859,11 @@ void GfxFont::loadFontAmigaPseudoTopaz() {
assert((topazBitOffset & 7) == 0);
topazByteOffset = topazBitOffset >> 3;
+
+ // Security check, although we are working on static const data from within ScummVM
+ uint maxOffset = (topazByteOffset + ((topazHeight - 1) * topazModulo));
+ assert(maxOffset < sizeof(fontData_AmigaPseudoTopaz));
+
for (uint16 curHeight = 0; curHeight < topazHeight; curHeight++) {
*fontData = topazData[topazByteOffset];
fontData++;
@@ -1160,4 +1195,102 @@ void GfxFont::loadFontAtariST(Common::String fontFilename) {
debug("AGI: Using Atari ST 8x8 system font");
}
+// Loads a Sierra Hercules font file
+void GfxFont::loadFontHercules() {
+ Common::File fontFile;
+ int32 fontFileSize = 0;
+ byte *fontData = nullptr;
+ byte *rawData = nullptr;
+
+ uint16 rawDataPos = 0;
+ uint16 curCharNr = 0;
+ uint16 curCharLine = 0;
+
+ if (fontFile.open("hgc_font")) {
+ // hgc_font file found, this is interleaved font data 16x12, should be 3072 bytes
+ // 24 bytes per character, 128 characters
+ fontFileSize = fontFile.size();
+ if (fontFileSize == (128 * 24)) {
+ // size seems to be fine
+ fontData = (uint8 *)calloc(256, 32);
+ _fontDataAllocated = fontData;
+
+ rawData = (byte *)calloc(128, 24);
+ fontFile.read(rawData, 128 * 24);
+
+ // convert interleaved 16x12 -> non-interleaved 16x16
+ for (curCharNr = 0; curCharNr < 128; curCharNr++) {
+ fontData += 4; // skip the first 2 lines
+ for (curCharLine = 0; curCharLine < 6; curCharLine++) {
+ fontData[0] = rawData[rawDataPos + 2 + 0];
+ fontData[1] = rawData[rawDataPos + 2 + 1];
+ fontData[2] = rawData[rawDataPos + 0 + 0];
+ fontData[3] = rawData[rawDataPos + 0 + 1];
+ rawDataPos += 4;
+ fontData += 4;
+ }
+ fontData += 4; // skip the last 2 lines
+ }
+
+ free(rawData);
+ } else {
+ warning("Fontfile 'hgc_font': unexpected file size");
+ }
+ fontFile.close();
+
+ }
+
+ // It seems hgc_graf.ovl holds a low-res font. It makes no real sense to use it.
+ // This was only done to AGI3 games and those rendered differently (2 pixel lines -> 3 pixel lines instead of 4)
+ // User could copy hgc_font from another AGI game over to get the hires font working.
+#if 0
+ if (!_fontDataAllocated) {
+ if (fontFile.open("hgc_graf.ovl")) {
+ // hgc_graf.ovl file found, this is font data + code. non-interleaved font data, should be 3075 bytes
+ // 16 bytes per character, 128 characters, 2048 bytes of font data, starting offset 21
+ fontFileSize = fontFile.size();
+ if (fontFileSize == 3075) {
+ // size seems to be fine
+ fontData = (uint8 *)calloc(256, 32);
+ _fontDataAllocated = fontData;
+
+ fontFile.seek(21);
+ rawData = (byte *)calloc(128, 16);
+ fontFile.read(rawData, 128 * 16);
+
+ // repeat every line 2 times to get 16x16 pixels
+ for (curCharNr = 0; curCharNr < 128; curCharNr++) {
+ for (curCharLine = 0; curCharLine < 8; curCharLine++) {
+ fontData[0] = rawData[rawDataPos + 0];
+ fontData[1] = rawData[rawDataPos + 1];
+ fontData[2] = rawData[rawDataPos + 0];
+ fontData[3] = rawData[rawDataPos + 1];
+ rawDataPos += 2;
+ fontData += 4;
+ }
+ }
+
+ free(rawData);
+
+ } else {
+ warning("Fontfile 'hgc_graf.ovl': unexpected file size");
+ }
+ fontFile.close();
+ }
+ }
+#endif
+
+ if (_fontDataAllocated) {
+ // font loaded
+ _fontData = _fontDataAllocated;
+ _fontIsHires = true;
+
+ debug("AGI: Using Hercules hires font");
+
+ } else {
+ // Continue, if no file was not found
+ warning("Could not open/use file 'hgc_font' for Hercules hires font");
+ }
+}
+
} // End of namespace Agi
diff --git a/engines/agi/font.h b/engines/agi/font.h
index 0bb1bbb18d..485b139858 100644
--- a/engines/agi/font.h
+++ b/engines/agi/font.h
@@ -36,6 +36,7 @@ private:
public:
void init();
const byte *getFontData();
+ bool isFontHires();
private:
void overwriteSaveRestoreDialogCharacter();
@@ -46,9 +47,11 @@ private:
void loadFontAmigaPseudoTopaz();
void loadFontAppleIIgs();
void loadFontAtariST(Common::String fontFilename);
+ void loadFontHercules();
const uint8 *_fontData; // pointer to the currently used font
uint8 *_fontDataAllocated;
+ bool _fontIsHires;
};
} // End of namespace Agi
diff --git a/engines/agi/global.cpp b/engines/agi/global.cpp
index 0f10976988..23256f27fb 100644
--- a/engines/agi/global.cpp
+++ b/engines/agi/global.cpp
@@ -23,6 +23,7 @@
#include "common/config-manager.h"
#include "agi/agi.h"
+#include "agi/graphics.h"
namespace Agi {
@@ -53,14 +54,21 @@ void AgiBase::flipFlag(int16 flagNr) {
void AgiEngine::setVar(int16 varNr, byte newValue) {
_game.vars[varNr] = newValue;
- if (varNr == VM_VAR_VOLUME) {
+ switch (varNr) {
+ case VM_VAR_SECONDS:
+ setVarSecondsTrigger(newValue);
+ break;
+ case VM_VAR_VOLUME:
setVolumeViaScripts(newValue);
+ break;
}
}
byte AgiEngine::getVar(int16 varNr) {
switch (varNr) {
case VM_VAR_SECONDS:
+ getVarSecondsHeuristicTrigger();
+ // is supposed to fall through
case VM_VAR_MINUTES:
case VM_VAR_HOURS:
case VM_VAR_DAYS:
@@ -79,7 +87,32 @@ byte AgiEngine::getVar(int16 varNr) {
// 15 - mute
void AgiEngine::setVolumeViaScripts(byte newVolume) {
newVolume = CLIP<byte>(newVolume, 0, 15);
- newVolume = 15 - newVolume; // turn volume around
+
+ if (_veryFirstInitialCycle) {
+ // WORKAROUND:
+ // The very first cycle is currently running and volume got changed
+ // This is surely the initial value. For plenty of fan games, a default of 15 is set
+ // Which actually means "mute" in AGI, but AGI on PC used PC speaker, which did not use
+ // volume setting. We do. So we detect such a situation and set a flag, so that the
+ // volume will get interpreted "correctly" for those fan games.
+ // Note: not all fan games are broken in that regard!
+ // See bug #7035
+ if (getFeatures() & GF_FANMADE) {
+ // We only check for fan games, Sierra always did it properly of course
+ if (newVolume == 15) {
+ // Volume gets set to mute at the start?
+ // Probably broken fan game detected, set flag
+ debug("Broken volume in fan game detected, enabling workaround");
+ _setVolumeBrokenFangame = true;
+ }
+ }
+ }
+
+ if (!_setVolumeBrokenFangame) {
+ // In AGI 15 is mute, 0 is loudest
+ // Some fan games set this incorrectly as 15 for loudest, 0 for mute
+ newVolume = 15 - newVolume; // turn volume around
+ }
int scummVMVolume = newVolume * Audio::Mixer::kMaxMixerVolume / 15;
bool scummVMMute = false;
@@ -135,10 +168,42 @@ void AgiEngine::setVolumeViaSystemSetting() {
_game.vars[VM_VAR_VOLUME] = internalVolume;
}
+void AgiEngine::resetGetVarSecondsHeuristic() {
+ _getVarSecondsHeuristicLastInstructionCounter = 0;
+ _getVarSecondsHeuristicCounter = 0;
+}
+
+// Called, when the scripts read VM_VAR_SECONDS
+void AgiEngine::getVarSecondsHeuristicTrigger() {
+ uint32 counterDifference = _instructionCounter - _getVarSecondsHeuristicLastInstructionCounter;
+
+ if (counterDifference <= 3) {
+ // Seconds were read within 3 instructions
+ _getVarSecondsHeuristicCounter++;
+ if (_getVarSecondsHeuristicCounter > 20) {
+ // More than 20 times in a row? This really seems to be an inner loop waiting for seconds to change
+ // This happens in at least:
+ // Police Quest 1 - Poker game (room 75, responsible script 81)
+
+ // Wait a few milliseconds, get events and update screen
+ // We MUST NOT process AGI events in here
+ wait(10);
+ processScummVMEvents();
+ _gfx->updateScreen();
+
+ _getVarSecondsHeuristicCounter = 0;
+ }
+ } else {
+ _getVarSecondsHeuristicCounter = 0;
+ }
+ _getVarSecondsHeuristicLastInstructionCounter = _instructionCounter;
+}
+
// In-Game timer, used for timer VM Variables
void AgiEngine::inGameTimerReset(uint32 newPlayTime) {
_lastUsedPlayTimeInCycles = newPlayTime / 50;
_lastUsedPlayTimeInSeconds = newPlayTime / 1000;
+ _playTimeInSecondsAdjust = 0; // no adjust for now
setTotalPlayTime(newPlayTime);
inGameTimerResetPassedCycles();
}
@@ -158,6 +223,24 @@ uint32 AgiEngine::inGameTimerGetPassedCycles() {
return _passedPlayTimeCycles;
}
+// Seconds got set by the game
+// This happens in Mixed Up Mother Goose. The game syncs the songs to VM_VAR_SECONDS, but instead
+// of only reading them, it sets it to 0 and then checks if it reached a certain second.
+// The original interpreter didn't reset the internal cycles counter. Which means the timing was never accurate,
+// because the cycles counter may just overflow right after setting the seconds, which means a second
+// increase almost immediately happened. We even fix this issue by adjusting for it.
+void AgiEngine::setVarSecondsTrigger(byte newSeconds) {
+ // Adjust in game timer, so that VM timer variables are accurate
+ inGameTimerUpdate();
+
+ // Adjust VM seconds again
+ _game.vars[VM_VAR_SECONDS] = newSeconds;
+
+ // Calculate milliseconds adjust (see comment above)
+ uint32 curPlayTimeMilliseconds = inGameTimerGet();
+ _playTimeInSecondsAdjust = curPlayTimeMilliseconds % 1000;
+}
+
// This is called, when one of the timer variables is read
// We calculate the latest variables, according to current official playtime
// This is also called in the main loop, because the game needs to be sync'd to 20 cycles per second
@@ -178,6 +261,14 @@ void AgiEngine::inGameTimerUpdate() {
_lastUsedPlayTimeInCycles = curPlayTimeCycles;
// Now calculate current play time in seconds
+ if (_playTimeInSecondsAdjust) {
+ // Apply adjust from setVarSecondsTrigger()
+ if (curPlayTimeMilliseconds >= _playTimeInSecondsAdjust) {
+ curPlayTimeMilliseconds -= _playTimeInSecondsAdjust;
+ } else {
+ curPlayTimeMilliseconds = 0;
+ }
+ }
uint32 curPlayTimeSeconds = curPlayTimeMilliseconds / 1000;
if (curPlayTimeSeconds == _lastUsedPlayTimeInSeconds) {
@@ -185,26 +276,50 @@ void AgiEngine::inGameTimerUpdate() {
return;
}
- uint32 secondsLeft = 0;
- byte curDays = 0;
- byte curHours = 0;
- byte curMinutes = 0;
- byte curSeconds = 0;
-
- curDays = curPlayTimeSeconds / 86400;
- secondsLeft = curPlayTimeSeconds % 86400;
-
- curHours = secondsLeft / 3600;
- secondsLeft = secondsLeft % 3600;
-
- curMinutes = secondsLeft / 60;
- curSeconds = secondsLeft % 60;
-
- // directly set them, otherwise we would go into an endless loop
- _game.vars[VM_VAR_SECONDS] = curSeconds;
- _game.vars[VM_VAR_MINUTES] = curMinutes;
- _game.vars[VM_VAR_HOURS] = curHours;
- _game.vars[VM_VAR_DAYS] = curDays;
+ int32 playTimeSecondsDelta = curPlayTimeSeconds - _lastUsedPlayTimeInSeconds;
+
+ if (playTimeSecondsDelta > 0) {
+ // Read and write to VM vars directly to avoid endless loop
+ uint32 secondsLeft = playTimeSecondsDelta;
+ byte curSeconds = _game.vars[VM_VAR_SECONDS];
+ byte curMinutes = _game.vars[VM_VAR_MINUTES];
+ byte curHours = _game.vars[VM_VAR_HOURS];
+ byte curDays = _game.vars[VM_VAR_DAYS];
+
+ // Add delta to VM variables
+ if (secondsLeft >= 86400) {
+ curDays += secondsLeft / 86400;
+ secondsLeft = secondsLeft % 86400;
+ }
+ if (secondsLeft >= 3600) {
+ curHours += secondsLeft / 3600;
+ secondsLeft = secondsLeft % 3600;
+ }
+ if (secondsLeft >= 60) {
+ curMinutes += secondsLeft / 60;
+ secondsLeft = secondsLeft % 60;
+ }
+ curSeconds += secondsLeft;
+
+ while (curSeconds > 59) {
+ curSeconds -= 60;
+ curMinutes++;
+ }
+ while (curMinutes > 59) {
+ curMinutes -= 60;
+ curHours++;
+ }
+ while (curHours > 23) {
+ curHours -= 24;
+ curDays++;
+ }
+
+ // directly set them
+ _game.vars[VM_VAR_SECONDS] = curSeconds;
+ _game.vars[VM_VAR_MINUTES] = curMinutes;
+ _game.vars[VM_VAR_HOURS] = curHours;
+ _game.vars[VM_VAR_DAYS] = curDays;
+ }
_lastUsedPlayTimeInSeconds = curPlayTimeSeconds;
}
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index ba5895ccd1..6d3563a451 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -39,7 +39,7 @@ namespace Agi {
#include "agi/font.h"
-GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
+GfxMgr::GfxMgr(AgiBase *vm, GfxFont *font) : _vm(vm), _font(font) {
_agipalFileNum = 0;
memset(&_paletteGfxMode, 0, sizeof(_paletteGfxMode));
@@ -50,7 +50,17 @@ GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
initPriorityTable();
- _renderStartOffsetY = 0;
+ _renderStartVisualOffsetY = 0;
+ _renderStartDisplayOffsetY = 0;
+
+ _upscaledHires = DISPLAY_UPSCALED_DISABLED;
+ _displayScreenWidth = DISPLAY_DEFAULT_WIDTH;
+ _displayScreenHeight = DISPLAY_DEFAULT_HEIGHT;
+ _displayFontWidth = 8;
+ _displayFontHeight = 8;
+
+ _displayWidthMulAdjust = 0; // visualPos * (2+0) = displayPos
+ _displayHeightMulAdjust = 0; // visualPos * (1+0) = displayPos
}
/**
@@ -59,6 +69,8 @@ GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
* @see deinit_video()
*/
int GfxMgr::initVideo() {
+ bool forceHires = false;
+
// Set up palettes
initPalette(_paletteTextMode, PALETTE_EGA);
@@ -72,6 +84,14 @@ int GfxMgr::initVideo() {
case Common::kRenderVGA:
initPalette(_paletteGfxMode, PALETTE_VGA, 256, 8);
break;
+ case Common::kRenderHercG:
+ initPalette(_paletteGfxMode, PALETTE_HERCULES_GREEN, 2, 8);
+ forceHires = true;
+ break;
+ case Common::kRenderHercA:
+ initPalette(_paletteGfxMode, PALETTE_HERCULES_AMBER, 2, 8);
+ forceHires = true;
+ break;
case Common::kRenderAmiga:
if (!ConfMan.getBool("altamigapalette")) {
// Set the correct Amiga palette depending on AGI interpreter version
@@ -87,7 +107,16 @@ int GfxMgr::initVideo() {
}
break;
case Common::kRenderApple2GS:
- initPalette(_paletteGfxMode, PALETTE_APPLE_II_GS, 16, 4);
+ switch (_vm->getGameID()) {
+ case GID_SQ1:
+ // Special one, only used for Space Quest 1 on Apple IIgs. Is the same as Amiga v1 palette
+ initPalette(_paletteGfxMode, PALETTE_APPLE_II_GS_SQ1, 16, 4);
+ break;
+ default:
+ // Regular "standard" Apple IIgs palette, used by everything else
+ initPalette(_paletteGfxMode, PALETTE_APPLE_II_GS, 16, 4);
+ break;
+ }
break;
case Common::kRenderAtariST:
initPalette(_paletteGfxMode, PALETTE_ATARI_ST, 16, 3);
@@ -116,31 +145,47 @@ int GfxMgr::initVideo() {
break;
}
+ //bool forcedUpscale = true;
+
+ if (_font->isFontHires() || forceHires) {
+ // Upscaling enable
+ _upscaledHires = DISPLAY_UPSCALED_640x400;
+ _displayScreenWidth = 640;
+ _displayScreenHeight = 400;
+ _displayFontWidth = 16;
+ _displayFontHeight = 16;
+
+ _displayWidthMulAdjust = 2;
+ _displayHeightMulAdjust = 1;
+ }
+
// set up mouse cursors
switch (_vm->_renderMode) {
case Common::kRenderEGA:
case Common::kRenderCGA:
case Common::kRenderVGA:
- initMouseCursor(&_mouseCursor, MOUSECURSOR_SCI, 11, 16, 1, 1);
+ case Common::kRenderHercG:
+ case Common::kRenderHercA:
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_SCI, 11, 16, 0, 0);
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
break;
case Common::kRenderAmiga:
- initMouseCursor(&_mouseCursor, MOUSECURSOR_AMIGA, 8, 11, 1, 1);
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_AMIGA, 8, 11, 0, 0);
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_AMIGA_BUSY, 13, 16, 7, 8);
break;
case Common::kRenderApple2GS:
// had no special busy mouse cursor
- initMouseCursor(&_mouseCursor, MOUSECURSOR_APPLE_II_GS, 9, 11, 1, 1);
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_APPLE_II_GS, 9, 11, 0, 0);
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
break;
case Common::kRenderAtariST:
- initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 1, 1);
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 0, 0);
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_SCI_BUSY, 15, 16, 7, 8);
break;
case Common::kRenderMacintosh:
// It looks like Atari ST + Macintosh used the same standard mouse cursor
// TODO: Verify by checking actual hardware
- initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 1, 1);
+ initMouseCursor(&_mouseCursor, MOUSECURSOR_ATARI_ST, 11, 16, 0, 0);
initMouseCursor(&_mouseCursorBusy, MOUSECURSOR_MACINTOSH_BUSY, 10, 14, 7, 8);
break;
default:
@@ -149,15 +194,15 @@ int GfxMgr::initVideo() {
}
_pixels = SCRIPT_WIDTH * SCRIPT_HEIGHT;
- _visualScreen = (byte *)calloc(_pixels, 1);
+ _gameScreen = (byte *)calloc(_pixels, 1);
_priorityScreen = (byte *)calloc(_pixels, 1);
- _activeScreen = _visualScreen;
+ _activeScreen = _gameScreen;
//_activeScreen = _priorityScreen;
- _displayPixels = DISPLAY_WIDTH * DISPLAY_HEIGHT;
+ _displayPixels = _displayScreenWidth * _displayScreenHeight;
_displayScreen = (byte *)calloc(_displayPixels, 1);
- initGraphics(DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_WIDTH > 320);
+ initGraphics(_displayScreenWidth, _displayScreenHeight, _displayScreenWidth > 320);
setPalette(true); // set gfx-mode palette
@@ -174,27 +219,151 @@ int GfxMgr::initVideo() {
* @see init_video()
*/
int GfxMgr::deinitVideo() {
+ // Free mouse cursors in case they were allocated
+ if (_mouseCursor.bitmapDataAllocated)
+ free(_mouseCursor.bitmapDataAllocated);
+ if (_mouseCursorBusy.bitmapDataAllocated)
+ free(_mouseCursorBusy.bitmapDataAllocated);
+
free(_displayScreen);
- free(_visualScreen);
+ free(_gameScreen);
free(_priorityScreen);
return errOK;
}
void GfxMgr::setRenderStartOffset(uint16 offsetY) {
- if (offsetY >= (DISPLAY_HEIGHT - SCRIPT_HEIGHT))
+ if (offsetY >= (VISUAL_HEIGHT - SCRIPT_HEIGHT))
error("invalid render start offset");
- _renderStartOffsetY = offsetY;
+ _renderStartVisualOffsetY = offsetY;
+ _renderStartDisplayOffsetY = offsetY * (1 + _displayHeightMulAdjust);
+}
+uint16 GfxMgr::getRenderStartDisplayOffsetY() {
+ return _renderStartDisplayOffsetY;
+}
+
+// Translates a game screen coordinate to a display screen coordinate
+// Game screen to 320x200 -> x * 2, y + renderStart
+// Game screen to 640x400 -> x * 4, (y * 2) + renderStart
+void GfxMgr::translateGamePosToDisplayScreen(int16 &x, int16 &y) {
+ x = x * (2 + _displayWidthMulAdjust);
+ y = y * (1 + _displayHeightMulAdjust) + _renderStartDisplayOffsetY;
+}
+
+// Translates a visual coordinate to a display screen coordinate
+// Visual to 320x200 -> x * 2, y
+// Visual to 640x400 -> x * 4, y * 2
+void GfxMgr::translateVisualPosToDisplayScreen(int16 &x, int16 &y) {
+ x = x * (2 + _displayWidthMulAdjust);
+ y = y * (1 + _displayHeightMulAdjust);
+}
+
+// Translates a display screen coordinate to a game screen coordinate
+// Display screen to 320x200 -> x / 2, y - renderStart
+// Display screen to 640x400 -> x / 4, (y / 2) - renderStart
+void GfxMgr::translateDisplayPosToGameScreen(int16 &x, int16 &y) {
+ y -= _renderStartDisplayOffsetY; // remove status bar line
+ x = x / (2 + _displayWidthMulAdjust);
+ y = y / (1 + _displayHeightMulAdjust);
+ if (y < 0)
+ y = 0;
+ if (y >= SCRIPT_HEIGHT)
+ y = SCRIPT_HEIGHT + 1; // 1 beyond
+}
+
+// Translates dimension from visual screen to display screen
+void GfxMgr::translateVisualDimensionToDisplayScreen(int16 &width, int16 &height) {
+ width = width * (2 + _displayWidthMulAdjust);
+ height = height * (1 + _displayHeightMulAdjust);
+}
+
+// Translates dimension from display screen to visual screen
+void GfxMgr::translateDisplayDimensionToVisualScreen(int16 &width, int16 &height) {
+ width = width / (2 + _displayWidthMulAdjust);
+ height = height / (1 + _displayHeightMulAdjust);
+}
+
+// Translates a rect from game screen to display screen
+void GfxMgr::translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
+ translateGamePosToDisplayScreen(x, y);
+ translateVisualDimensionToDisplayScreen(width, height);
}
-uint16 GfxMgr::getRenderStartOffsetY() {
- return _renderStartOffsetY;
+
+// Translates a rect from visual screen to display screen
+void GfxMgr::translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
+ translateVisualPosToDisplayScreen(x, y);
+ translateVisualDimensionToDisplayScreen(width, height);
+}
+
+uint32 GfxMgr::getDisplayOffsetToGameScreenPos(int16 x, int16 y) {
+ translateGamePosToDisplayScreen(x, y);
+ return (y * _displayScreenWidth) + x;
+}
+
+uint32 GfxMgr::getDisplayOffsetToVisualScreenPos(int16 x, int16 y) {
+ translateVisualPosToDisplayScreen(x, y);
+ return (y * _displayScreenWidth) + x;
+}
+
+// Attention: uses display screen coordinates!
+void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height) {
+ g_system->copyRectToScreen(_displayScreen + y * _displayScreenWidth + x, _displayScreenWidth, x, y, width, height);
+}
+void GfxMgr::copyDisplayRectToScreen(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight) {
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ adjX *= 2; adjY *= 2;
+ adjWidth *= 2; adjHeight *= 2;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ x += adjX; y += adjY;
+ width += adjWidth; height += adjHeight;
+ g_system->copyRectToScreen(_displayScreen + y * _displayScreenWidth + x, _displayScreenWidth, x, y, width, height);
+}
+void GfxMgr::copyDisplayRectToScreenUsingGamePos(int16 x, int16 y, int16 width, int16 height) {
+ translateGameRectToDisplayScreen(x, y, width, height);
+ g_system->copyRectToScreen(_displayScreen + (y * _displayScreenWidth) + x, _displayScreenWidth, x, y, width, height);
+}
+void GfxMgr::copyDisplayRectToScreenUsingVisualPos(int16 x, int16 y, int16 width, int16 height) {
+ translateVisualRectToDisplayScreen(x, y, width, height);
+ g_system->copyRectToScreen(_displayScreen + (y * _displayScreenWidth) + x, _displayScreenWidth, x, y, width, height);
+}
+void GfxMgr::copyDisplayToScreen() {
+ g_system->copyRectToScreen(_displayScreen, _displayScreenWidth, 0, 0, _displayScreenWidth, _displayScreenHeight);
+}
+
+void GfxMgr::translateFontPosToDisplayScreen(int16 &x, int16 &y) {
+ x *= _displayFontWidth;
+ y *= _displayFontHeight;
+}
+void GfxMgr::translateDisplayPosToFontScreen(int16 &x, int16 &y) {
+ x /= _displayFontWidth;
+ y /= _displayFontHeight;
+}
+void GfxMgr::translateFontDimensionToDisplayScreen(int16 &width, int16 &height) {
+ width *= _displayFontWidth;
+ height *= _displayFontHeight;
+}
+void GfxMgr::translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height) {
+ translateFontPosToDisplayScreen(x, y);
+ translateFontDimensionToDisplayScreen(width, height);
+}
+Common::Rect GfxMgr::getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height) {
+ Common::Rect displayRect(width * _displayFontWidth, height * _displayFontHeight);
+ displayRect.moveTo(column * _displayFontWidth, row * _displayFontHeight);
+ return displayRect;
}
void GfxMgr::debugShowMap(int mapNr) {
switch (mapNr) {
case 0:
- _activeScreen = _visualScreen;
+ _activeScreen = _gameScreen;
break;
case 1:
_activeScreen = _priorityScreen;
@@ -203,11 +372,11 @@ void GfxMgr::debugShowMap(int mapNr) {
break;
}
- render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
+ render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
}
void GfxMgr::clear(byte color, byte priority) {
- memset(_visualScreen, color, _pixels);
+ memset(_gameScreen, color, _pixels);
memset(_priorityScreen, priority, _pixels);
}
@@ -215,7 +384,7 @@ void GfxMgr::clearDisplay(byte color, bool copyToScreen) {
memset(_displayScreen, color, _displayPixels);
if (copyToScreen) {
- g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ copyDisplayToScreen();
}
}
@@ -223,7 +392,7 @@ void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority
int offset = y * SCRIPT_WIDTH + x;
if (drawMask & GFX_SCREEN_MASK_VISUAL) {
- _visualScreen[offset] = color;
+ _gameScreen[offset] = color;
}
if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
_priorityScreen[offset] = priority;
@@ -231,15 +400,72 @@ void GfxMgr::putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority
}
void GfxMgr::putPixelOnDisplay(int16 x, int16 y, byte color) {
- int offset = y * DISPLAY_WIDTH + x;
+ uint32 offset = 0;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ offset = y * _displayScreenWidth + x;
+
+ _displayScreen[offset] = color;
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ offset = (y * _displayScreenWidth) + x;
- _displayScreen[offset] = color;
+ _displayScreen[offset + 0] = color;
+ _displayScreen[offset + 1] = color;
+ _displayScreen[offset + _displayScreenWidth + 0] = color;
+ _displayScreen[offset + _displayScreenWidth + 1] = color;
+ break;
+ default:
+ break;
+ }
+}
+
+void GfxMgr::putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte color) {
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ adjX *= 2; adjY *= 2;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ x += adjX;
+ y += adjY;
+ putPixelOnDisplay(x, y, color);
+}
+
+void GfxMgr::putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 addY, byte color, bool isHires) {
+ uint32 offset = 0;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ offset = ((baseY + addY) * _displayScreenWidth) + (baseX + addX);
+ _displayScreen[offset] = color;
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ if (isHires) {
+ offset = ((baseY + addY) * _displayScreenWidth) + (baseX + addX);
+ _displayScreen[offset] = color;
+ } else {
+ offset = ((baseY + addY * 2) * _displayScreenWidth) + (baseX + addX * 2);
+ _displayScreen[offset + 0] = color;
+ _displayScreen[offset + 1] = color;
+ _displayScreen[offset + _displayScreenWidth + 0] = color;
+ _displayScreen[offset + _displayScreenWidth + 1] = color;
+ }
+ break;
+ default:
+ break;
+ }
}
byte GfxMgr::getColor(int16 x, int16 y) {
int offset = y * SCRIPT_WIDTH + x;
- return _visualScreen[offset];
+ return _gameScreen[offset];
}
byte GfxMgr::getPriority(int16 x, int16 y) {
@@ -279,12 +505,17 @@ byte GfxMgr::getCGAMixtureColor(byte color) {
return CGA_MixtureColorTable[color & 0x0F];
}
-// Attention: y-coordinate points to the LOWER left!
+// Attention: in our implementation, y-coordinate is upper left.
+// Sierra passed the lower left instead. We changed it to make upscaling easier.
void GfxMgr::render_Block(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
if (!render_Clip(x, y, width, height))
return;
switch (_vm->_renderMode) {
+ case Common::kRenderHercG:
+ case Common::kRenderHercA:
+ render_BlockHercules(x, y, width, height, copyToScreen);
+ break;
case Common::kRenderCGA:
render_BlockCGA(x, y, width, height, copyToScreen);
break;
@@ -295,17 +526,26 @@ void GfxMgr::render_Block(int16 x, int16 y, int16 width, int16 height, bool copy
}
if (copyToScreen) {
- int16 upperY = y - height + 1 + _renderStartOffsetY;
- g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x * 2, DISPLAY_WIDTH, x * 2, upperY, width * 2, height);
+ copyDisplayRectToScreenUsingGamePos(x, y, width, height);
}
}
bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16 clipAgainstWidth, int16 clipAgainstHeight) {
if ((x >= clipAgainstWidth) || ((x + width - 1) < 0) ||
- (y < 0) || ((y - (height - 1)) >= clipAgainstHeight)) {
+ (y < 0) || ((y + (height - 1)) >= clipAgainstHeight)) {
return false;
}
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+
+ if ((y + height - 1) >= clipAgainstHeight) {
+ height = clipAgainstHeight - y;
+ }
+
+#if 0
if ((y - height + 1) < 0)
height = y + 1;
@@ -313,6 +553,7 @@ bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16
height -= y - (clipAgainstHeight - 1);
y = clipAgainstHeight - 1;
}
+#endif
if (x < 0) {
width += x;
@@ -326,52 +567,212 @@ bool GfxMgr::render_Clip(int16 &x, int16 &y, int16 &width, int16 &height, int16
}
void GfxMgr::render_BlockEGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
- int offsetVisual = SCRIPT_WIDTH * y + x;
- int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
+ uint32 offsetVisual = SCRIPT_WIDTH * y + x;
+ uint32 offsetDisplay = getDisplayOffsetToGameScreenPos(x, y);
int16 remainingWidth = width;
int16 remainingHeight = height;
byte curColor = 0;
+ int16 displayWidth = width * (2 + _displayWidthMulAdjust);
while (remainingHeight) {
remainingWidth = width;
- while (remainingWidth) {
- curColor = _activeScreen[offsetVisual++];
- _displayScreen[offsetDisplay++] = curColor;
- _displayScreen[offsetDisplay++] = curColor;
- remainingWidth--;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ _displayScreen[offsetDisplay++] = curColor;
+ _displayScreen[offsetDisplay++] = curColor;
+ remainingWidth--;
+ }
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ memset(&_displayScreen[offsetDisplay], curColor, 4);
+ memset(&_displayScreen[offsetDisplay + _displayScreenWidth], curColor, 4);
+ offsetDisplay += 4;
+ remainingWidth--;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ offsetVisual += SCRIPT_WIDTH - width;
+ offsetDisplay += _displayScreenWidth - displayWidth;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_640x400:
+ offsetDisplay += _displayScreenWidth;;
+ break;
+ default:
+ break;
}
- offsetVisual -= SCRIPT_WIDTH + width;
- offsetDisplay -= DISPLAY_WIDTH + width * 2;
remainingHeight--;
}
}
void GfxMgr::render_BlockCGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
- int offsetVisual = SCRIPT_WIDTH * y + x;
- int offsetDisplay = (DISPLAY_WIDTH * (y + _renderStartOffsetY)) + x * 2;
+ uint32 offsetVisual = SCRIPT_WIDTH * y + x;
+ uint32 offsetDisplay = getDisplayOffsetToGameScreenPos(x, y);
+ int16 remainingWidth = width;
+ int16 remainingHeight = height;
+ byte curColor = 0;
+ int16 displayWidth = width * (2 + _displayWidthMulAdjust);
+
+ while (remainingHeight) {
+ remainingWidth = width;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ _displayScreen[offsetDisplay++] = curColor & 0x03; // we process CGA mixture
+ _displayScreen[offsetDisplay++] = curColor >> 2;
+ remainingWidth--;
+ }
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ while (remainingWidth) {
+ curColor = _activeScreen[offsetVisual++];
+ _displayScreen[offsetDisplay + 0] = curColor & 0x03; // we process CGA mixture
+ _displayScreen[offsetDisplay + 1] = curColor >> 2;
+ _displayScreen[offsetDisplay + 2] = curColor & 0x03;
+ _displayScreen[offsetDisplay + 3] = curColor >> 2;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 0] = curColor & 0x03;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 1] = curColor >> 2;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 2] = curColor & 0x03;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 3] = curColor >> 2;
+ offsetDisplay += 4;
+ remainingWidth--;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ offsetVisual += SCRIPT_WIDTH - width;
+ offsetDisplay += _displayScreenWidth - displayWidth;
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_640x400:
+ offsetDisplay += _displayScreenWidth;;
+ break;
+ default:
+ break;
+ }
+
+ remainingHeight--;
+ }
+}
+
+static const uint8 herculesColorMapping[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x88, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+ 0x80, 0x10, 0x02, 0x20, 0x01, 0x08, 0x40, 0x04,
+ 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
+ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+ 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00,
+ 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88,
+ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88, 0x00,
+ 0xD7, 0xFF, 0x7D, 0xFF, 0xD7, 0xFF, 0x7D, 0xFF,
+ 0xDD, 0x55, 0x77, 0xAA, 0xDD, 0x55, 0x77, 0xAA,
+ 0x7F, 0xEF, 0xFD, 0xDF, 0xFE, 0xF7, 0xBF, 0xFB,
+ 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
+ 0x77, 0xBB, 0xDD, 0xEE, 0x77, 0xBB, 0xDD, 0xEE,
+ 0x77, 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+// Sierra actually seems to have rendered the whole screen all the time
+void GfxMgr::render_BlockHercules(int16 x, int16 y, int16 width, int16 height, bool copyToScreen) {
+ uint32 offsetVisual = SCRIPT_WIDTH * y + x;
+ uint32 offsetDisplay = getDisplayOffsetToGameScreenPos(x, y);
int16 remainingWidth = width;
int16 remainingHeight = height;
byte curColor = 0;
+ int16 displayWidth = width * (2 + _displayWidthMulAdjust);
+
+ assert(_upscaledHires == DISPLAY_UPSCALED_640x400);
+
+ uint16 lookupOffset1 = (y * 2 & 0x07);
+ uint16 lookupOffset2 = 0;
+ bool getUpperNibble = false;
+ byte herculesColors1 = 0;
+ byte herculesColors2 = 0;
while (remainingHeight) {
remainingWidth = width;
+
+ lookupOffset1 = (lookupOffset1 + 0) & 0x07;
+ lookupOffset2 = (lookupOffset1 + 1) & 0x07;
+
+ getUpperNibble = (x & 1) ? false : true;
while (remainingWidth) {
- curColor = _activeScreen[offsetVisual++];
- _displayScreen[offsetDisplay++] = curColor & 0x03; // we process CGA mixture
- _displayScreen[offsetDisplay++] = curColor >> 2;
+ curColor = _activeScreen[offsetVisual++] & 0x0F;
+
+ if (getUpperNibble) {
+ herculesColors1 = herculesColorMapping[curColor * 8 + lookupOffset1] & 0x0F;
+ herculesColors2 = herculesColorMapping[curColor * 8 + lookupOffset2] & 0x0F;
+ } else {
+ herculesColors1 = herculesColorMapping[curColor * 8 + lookupOffset1] >> 4;
+ herculesColors2 = herculesColorMapping[curColor * 8 + lookupOffset2] >> 4;
+ }
+ getUpperNibble ^= true;
+
+ _displayScreen[offsetDisplay + 0] = (herculesColors1 & 0x08) ? 1 : 0;
+ _displayScreen[offsetDisplay + 1] = (herculesColors1 & 0x04) ? 1 : 0;
+ _displayScreen[offsetDisplay + 2] = (herculesColors1 & 0x02) ? 1 : 0;
+ _displayScreen[offsetDisplay + 3] = (herculesColors1 & 0x01) ? 1 : 0;
+
+ _displayScreen[offsetDisplay + _displayScreenWidth + 0] = (herculesColors2 & 0x08) ? 1 : 0;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 1] = (herculesColors2 & 0x04) ? 1 : 0;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 2] = (herculesColors2 & 0x02) ? 1 : 0;
+ _displayScreen[offsetDisplay + _displayScreenWidth + 3] = (herculesColors2 & 0x01) ? 1 : 0;
+
+ offsetDisplay += 4;
remainingWidth--;
}
- offsetVisual -= SCRIPT_WIDTH + width;
- offsetDisplay -= DISPLAY_WIDTH + width * 2;
+
+ lookupOffset1 += 2;
+
+ offsetVisual += SCRIPT_WIDTH - width;
+ offsetDisplay += _displayScreenWidth - displayWidth;
+ offsetDisplay += _displayScreenWidth;;
remainingHeight--;
}
}
+// Table used for at least Manhunter 2, it renders 2 lines -> 3 lines instead of 4
+// Manhunter 1 is shipped with a broken Hercules font
+// King's Quest 4 aborts right at the start, when Hercules rendering is active
+#if 0
+static const uint8 herculesCoordinateOffset[] = {
+ 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x01, 0x02,
+ 0x04, 0x05, 0x07, 0x00, 0x02, 0x03, 0x05, 0x06
+};
+
+static const uint8 herculesColorMapping[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x08, 0x00,
+ 0x80, 0x10, 0x02, 0x20, 0x01, 0x08, 0x40, 0x04, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00,
+ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00,
+ 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0xD7, 0xFF, 0x7D, 0xFF, 0xD7, 0xFF, 0x7D, 0xFF,
+ 0xDD, 0x55, 0x77, 0xAA, 0xDD, 0x55, 0x77, 0xAA, 0x7F, 0xEF, 0xFD, 0xDF, 0xFE, 0xF7, 0xBF, 0xFB,
+ 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0x77, 0xBB, 0xDD, 0xEE, 0x77, 0xBB, 0xDD, 0xEE,
+ 0x7F, 0xEF, 0xFB, 0xBF, 0xEF, 0xFE, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+#endif
+
void GfxMgr::transition_Amiga() {
uint16 screenPos = 1;
- uint16 screenStepPos = 1;
+ uint32 screenStepPos = 1;
int16 posY = 0, posX = 0;
int16 stepCount = 0;
@@ -393,15 +794,29 @@ void GfxMgr::transition_Amiga() {
posY = screenStepPos / SCRIPT_WIDTH;
posX = screenStepPos - (posY * SCRIPT_WIDTH);
- posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
- posX *= 2; // adjust for display screen
-
- screenStepPos = (screenStepPos * 2) + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
- for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
- g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 2, 1);
- screenStepPos += (0x1A40 * 2); // 6720d
- posY += 42;
+ // Adjust to only update the game screen, not the status bar
+ translateGamePosToDisplayScreen(posX, posY);
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
+ screenStepPos = (posY * _displayScreenWidth) + posX;
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 2, 1);
+ posY += 42;
+ }
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ for (int16 multiPixel = 0; multiPixel < 4; multiPixel++) {
+ screenStepPos = (posY * _displayScreenWidth) + posX;
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 4, 2);
+ posY += 42 * 2;
+ }
+ break;
+ default:
+ assert(0);
+ break;
}
+
stepCount++;
if (stepCount == 220) {
// 30 times for the whole transition, so should take around 0.5 seconds
@@ -424,7 +839,7 @@ void GfxMgr::transition_Amiga() {
// Atari ST definitely had a hi-res transition using the full resolution unlike the Amiga transition.
void GfxMgr::transition_AtariSt() {
uint16 screenPos = 1;
- uint16 screenStepPos = 1;
+ uint32 screenStepPos = 1;
int16 posY = 0, posX = 0;
int16 stepCount = 0;
@@ -443,17 +858,31 @@ void GfxMgr::transition_AtariSt() {
if ((screenPos < 13440) && (screenPos & 1)) {
screenStepPos = screenPos >> 1;
- posY = screenStepPos / DISPLAY_WIDTH;
- posX = screenStepPos - (posY * DISPLAY_WIDTH);
-
- posY += _renderStartOffsetY; // adjust to only update the main area, not the status bar
-
- screenStepPos = screenStepPos + (_renderStartOffsetY * DISPLAY_WIDTH); // adjust here too for display screen
- for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
- g_system->copyRectToScreen(_displayScreen + screenStepPos, DISPLAY_WIDTH, posX, posY, 1, 1);
- screenStepPos += 0x1a40; // 6720d
- posY += 21;
+ posY = screenStepPos / DISPLAY_DEFAULT_WIDTH;
+ posX = screenStepPos - (posY * DISPLAY_DEFAULT_WIDTH);
+
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ posY += _renderStartDisplayOffsetY; // adjust to only update the main area, not the status bar
+ for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
+ screenStepPos = (posY * _displayScreenWidth) + posX;
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 1, 1);
+ posY += 21;
+ }
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ posX *= 2; posY *= 2;
+ posY += _renderStartDisplayOffsetY; // adjust to only update the main area, not the status bar
+ for (int16 multiPixel = 0; multiPixel < 8; multiPixel++) {
+ screenStepPos = (posY * _displayScreenWidth) + posX;
+ g_system->copyRectToScreen(_displayScreen + screenStepPos, _displayScreenWidth, posX, posY, 2, 2);
+ posY += 21 * 2;
+ }
+ break;
+ default:
+ break;
}
+
stepCount++;
if (stepCount == 168) {
// 40 times for the whole transition, so should take around 0.7 seconds
@@ -484,7 +913,7 @@ void GfxMgr::block_save(int16 x, int16 y, int16 width, int16 height, byte *buffe
//warning("block_save: %d, %d -> %d, %d", x, y, width, height);
while (remainingHeight) {
- memcpy(curBufferPtr, _visualScreen + offset, width);
+ memcpy(curBufferPtr, _gameScreen + offset, width);
offset += SCRIPT_WIDTH;
curBufferPtr += width;
remainingHeight--;
@@ -510,7 +939,7 @@ void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bu
//warning("block_restore: %d, %d -> %d, %d", x, y, width, height);
while (remainingHeight) {
- memcpy(_visualScreen + offset, curBufferPtr, width);
+ memcpy(_gameScreen + offset, curBufferPtr, width);
offset += SCRIPT_WIDTH;
curBufferPtr += width;
remainingHeight--;
@@ -526,12 +955,8 @@ void GfxMgr::block_restore(int16 x, int16 y, int16 width, int16 height, byte *bu
}
}
-// Attention: uses visual screen coordinates!
-void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height) {
- g_system->copyRectToScreen(_displayScreen + y * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, y, width, height);
-}
-
// coordinates are for visual screen, but are supposed to point somewhere inside the playscreen
+// x, y is the upper left. Sierra passed them as lower left. We change that to make upscaling easier.
// attention: Clipping is done here against 160x200 instead of 160x168
// Original interpreter didn't do any clipping, we do it for security.
// Clipping against the regular script width/height must not be done,
@@ -539,13 +964,13 @@ void GfxMgr::copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height
// Going beyond 160x168 will result in messageboxes not getting fully removed
// In KQ4's case, the scripts clear the screen that's why it works.
void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor) {
- if (!render_Clip(x, y, width, height, SCRIPT_WIDTH, DISPLAY_HEIGHT - _renderStartOffsetY))
+ if (!render_Clip(x, y, width, height, VISUAL_WIDTH, VISUAL_HEIGHT - _renderStartVisualOffsetY))
return;
// coordinate translation: visual-screen -> display-screen
- x = x * 2;
- y = y + _renderStartOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
- width = width * 2; // width was given as visual width, we need display width
+ translateVisualRectToDisplayScreen(x, y, width, height);
+
+ y = y + _renderStartDisplayOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
// draw box background
drawDisplayRect(x, y, width, height, backgroundColor);
@@ -555,75 +980,87 @@ void GfxMgr::drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroun
case Common::kRenderApple2GS:
case Common::kRenderAmiga:
// Slightly different window frame, and actually using 1-pixel width, which is "hi-res"
- drawDisplayRect(x + 2, y - 2, width - 4, 1, lineColor);
- drawDisplayRect(x + width - 3, y - 2, 1, height - 4, lineColor);
- drawDisplayRect(x + 2, y - height + 3, width - 4, 1, lineColor);
- drawDisplayRect(x + 2, y - 2, 1, height - 4, lineColor);
+ drawDisplayRect(x, +2, y, +2, width, -4, 0, 1, lineColor);
+ drawDisplayRect(x + width, -3, y, +2, 0, 1, height, -4, lineColor);
+ drawDisplayRect(x, +2, y + height, -3, width, -4, 0, 1, lineColor);
+ drawDisplayRect(x, +2, y, +2, 0, 1, height, -4, lineColor);
break;
case Common::kRenderMacintosh:
// 1 pixel between box and frame lines. Frame lines were black
- drawDisplayRect(x + 1, y - 1, width - 2, 1, 0);
- drawDisplayRect(x + width - 2, y - 1, 1, height - 2, 0);
- drawDisplayRect(x + 1, y - height + 2, width - 2, 1, 0);
- drawDisplayRect(x + 1, y - 1, 1, height - 2, 0);
+ drawDisplayRect(x, +1, y, +1, width, -2, 0, 1, 0);
+ drawDisplayRect(x + width, -2, y, +1, 0, 1, height, -2, 0);
+ drawDisplayRect(x, +1, y + height, -2, width, -2, 0, 1, 0);
+ drawDisplayRect(x, +1, y, +1, 0, 1, height, -2, 0);
break;
+ case Common::kRenderHercA:
+ case Common::kRenderHercG:
+ lineColor = 0; // change linecolor to black
+ // supposed to fall through
case Common::kRenderCGA:
case Common::kRenderEGA:
case Common::kRenderVGA:
case Common::kRenderAtariST:
default:
- drawDisplayRect(x + 2, y - 1, width - 4, 1, lineColor);
- drawDisplayRect(x + width - 4, y - 2, 2, height - 4, lineColor);
- drawDisplayRect(x + 2, y - height + 2, width - 4, 1, lineColor);
- drawDisplayRect(x + 2, y - 2, 2, height - 4, lineColor);
+ drawDisplayRect(x, +2, y, +1, width, -4, 0, 1, lineColor);
+ drawDisplayRect(x + width, -4, y, +2, 0, 2, height, -4, lineColor);
+ drawDisplayRect(x, +2, y + height, -2, width, -4, 0, 1, lineColor);
+ drawDisplayRect(x, +2, y, +2, 0, 2, height, -4, lineColor);
break;
}
}
-// coordinates for visual screen
-void GfxMgr::drawRect(int16 x, int16 y, int16 width, int16 height, byte color) {
- if (!render_Clip(x, y, width, height, SCRIPT_WIDTH, DISPLAY_HEIGHT - _renderStartOffsetY))
- return;
-
- // coordinate translation: visual-screen -> display-screen
- x = x * 2;
- y = y + _renderStartOffsetY; // drawDisplayRect paints anywhere on the whole screen, our coordinate is within playscreen
- width = width * 2; // width was given as visual width, we need display width
-
- drawDisplayRect(x, y, width, height, color);
-}
-
// coordinates are directly for display screen
void GfxMgr::drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte color, bool copyToScreen) {
switch (_vm->_renderMode) {
case Common::kRenderCGA:
drawDisplayRectCGA(x, y, width, height, color);
break;
+ case Common::kRenderHercG:
+ case Common::kRenderHercA:
+ if (color)
+ color = 1; // change any color except black to green/amber
+ // supposed to fall through
case Common::kRenderEGA:
default:
drawDisplayRectEGA(x, y, width, height, color);
break;
}
if (copyToScreen) {
- int16 upperY = y - height + 1;
- g_system->copyRectToScreen(_displayScreen + upperY * DISPLAY_WIDTH + x, DISPLAY_WIDTH, x, upperY, width, height);
+ copyDisplayRectToScreen(x, y, width, height);
}
}
+void GfxMgr::drawDisplayRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight, byte color, bool copyToScreen) {
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ x += adjX; y += adjY;
+ width += adjWidth; height += adjHeight;
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ x += adjX * 2; y += adjY * 2;
+ width += adjWidth * 2; height += adjHeight * 2;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ drawDisplayRect(x, y, width, height, color, copyToScreen);
+}
+
void GfxMgr::drawDisplayRectEGA(int16 x, int16 y, int16 width, int16 height, byte color) {
- int offsetDisplay = (DISPLAY_WIDTH * y) + x;
+ uint32 offsetDisplay = (y * _displayScreenWidth) + x;
int16 remainingHeight = height;
while (remainingHeight) {
memset(_displayScreen + offsetDisplay, color, width);
- offsetDisplay -= DISPLAY_WIDTH;
+ offsetDisplay += _displayScreenWidth;
remainingHeight--;
}
}
void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byte color) {
- int offsetDisplay = (DISPLAY_WIDTH * y) + x;
+ uint32 offsetDisplay = (y * _displayScreenWidth) + x;
int16 remainingHeight = height;
int16 remainingWidth = width;
byte CGAMixtureColor = getCGAMixtureColor(color);
@@ -644,18 +1081,20 @@ void GfxMgr::drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byt
remainingWidth -= 2;
}
- offsetDisplay -= DISPLAY_WIDTH;
+ offsetDisplay += _displayScreenWidth;
remainingHeight--;
}
}
// row + column are text-coordinates
void GfxMgr::drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook) {
- int16 x = column * FONT_DISPLAY_WIDTH;
- int16 y = row * FONT_DISPLAY_HEIGHT;
+ int16 x = column;
+ int16 y = row;
byte transformXOR = 0;
byte transformOR = 0;
+ translateFontPosToDisplayScreen(x, y);
+
// Now figure out, if special handling needs to be done
if (_vm->_game.gfxMode) {
if (background & 0x08) {
@@ -676,22 +1115,43 @@ void GfxMgr::drawStringOnDisplay(int16 x, int16 y, const char *text, byte foregr
while (*text) {
drawCharacterOnDisplay(x, y, *text, foregroundColor, backgroundColor);
text++;
- x += FONT_DISPLAY_WIDTH;
+ x += _displayFontWidth;
+ }
+}
+
+void GfxMgr::drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const char *text, byte foregroundColor, byte backgroundColor) {
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ x += adjX;
+ y += adjY;
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ x += adjX * 2;
+ y += adjY * 2;
+ break;
+ default:
+ assert(0);
+ break;
}
+ drawStringOnDisplay(x, y, text, foregroundColor, backgroundColor);
}
void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte foreground, byte background, byte transformXOR, byte transformOR) {
int16 curX, curY;
const byte *fontData;
+ bool fontIsHires = _font->isFontHires();
+ int16 fontHeight = fontIsHires ? 16 : FONT_DISPLAY_HEIGHT;
+ int16 fontWidth = fontIsHires ? 16 : FONT_DISPLAY_WIDTH;
+ int16 fontBytesPerCharacter = fontIsHires ? 32 : FONT_BYTES_PER_CHARACTER;
byte curByte = 0;
uint16 curBit;
// get font data of specified character
- fontData = _vm->getFontData() + character * FONT_BYTES_PER_CHARACTER;
+ fontData = _font->getFontData() + character * fontBytesPerCharacter;
curBit = 0;
- for (curY = 0; curY < FONT_DISPLAY_HEIGHT; curY++) {
- for (curX = 0; curX < FONT_DISPLAY_WIDTH; curX++) {
+ for (curY = 0; curY < fontHeight; curY++) {
+ for (curX = 0; curX < fontWidth; curX++) {
if (!curBit) {
curByte = *fontData;
// do transformations in case they are needed (invert/disabled look)
@@ -701,9 +1161,9 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte
curBit = 0x80;
}
if (curByte & curBit) {
- putPixelOnDisplay(x + curX, y + curY, foreground);
+ putFontPixelOnDisplay(x, y, curX, curY, foreground, fontIsHires);
} else {
- putPixelOnDisplay(x + curX, y + curY, background);
+ putFontPixelOnDisplay(x, y, curX, curY, background, fontIsHires);
}
curBit = curBit >> 1;
}
@@ -711,18 +1171,20 @@ void GfxMgr::drawCharacterOnDisplay(int16 x, int16 y, const byte character, byte
transformOR ^= 0xFF;
}
- copyDisplayRectToScreen(x, y, FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
+ copyDisplayRectToScreen(x, y, _displayFontWidth, _displayFontHeight);
}
#define SHAKE_VERTICAL_PIXELS 4
-#define SHAKE_HORIZONTAL_PIXELS 8
+#define SHAKE_HORIZONTAL_PIXELS 4
// Sierra used some EGA port trickery to do it, we have to do it by copying pixels around
void GfxMgr::shakeScreen(int16 repeatCount) {
int shakeNr, shakeCount;
uint8 *blackSpace;
+ int16 shakeHorizontalPixels = SHAKE_HORIZONTAL_PIXELS * (2 + _displayWidthMulAdjust);
+ int16 shakeVerticalPixels = SHAKE_VERTICAL_PIXELS * (1 + _displayHeightMulAdjust);
- if ((blackSpace = (uint8 *)calloc(SHAKE_HORIZONTAL_PIXELS * DISPLAY_WIDTH, 1)) == NULL)
+ if ((blackSpace = (uint8 *)calloc(shakeVerticalPixels * _displayScreenWidth, 1)) == NULL)
return;
shakeCount = repeatCount * 8; // effectively 4 shakes per repeat
@@ -732,12 +1194,12 @@ void GfxMgr::shakeScreen(int16 repeatCount) {
for (shakeNr = 0; shakeNr < shakeCount; shakeNr++) {
if (shakeNr & 1) {
// move back
- copyDisplayRectToScreen(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ copyDisplayToScreen();
} else {
- g_system->copyRectToScreen(_displayScreen, DISPLAY_WIDTH, SHAKE_HORIZONTAL_PIXELS, SHAKE_VERTICAL_PIXELS, DISPLAY_WIDTH - SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT - SHAKE_VERTICAL_PIXELS);
+ g_system->copyRectToScreen(_displayScreen, _displayScreenWidth, shakeHorizontalPixels, shakeVerticalPixels, _displayScreenWidth - shakeHorizontalPixels, _displayScreenHeight - shakeVerticalPixels);
// additionally fill the remaining space with black
- g_system->copyRectToScreen(blackSpace, DISPLAY_WIDTH, 0, 0, DISPLAY_WIDTH, SHAKE_VERTICAL_PIXELS);
- g_system->copyRectToScreen(blackSpace, SHAKE_HORIZONTAL_PIXELS, 0, 0, SHAKE_HORIZONTAL_PIXELS, DISPLAY_HEIGHT);
+ g_system->copyRectToScreen(blackSpace, _displayScreenWidth, 0, 0, _displayScreenWidth, shakeVerticalPixels);
+ g_system->copyRectToScreen(blackSpace, shakeHorizontalPixels, 0, 0, shakeHorizontalPixels, _displayScreenHeight);
}
g_system->updateScreen();
g_system->delayMillis(66); // Sierra waited for 4 V'Syncs, which is around 66 milliseconds
@@ -751,13 +1213,18 @@ void GfxMgr::updateScreen() {
}
void GfxMgr::initPriorityTable() {
+ _priorityTableSet = false;
+
+ createDefaultPriorityTable(_priorityTable);
+}
+
+void GfxMgr::createDefaultPriorityTable(uint8 *priorityTable) {
int16 priority, step;
int16 yPos = 0;
- _priorityTableSet = false;
for (priority = 1; priority < 15; priority++) {
for (step = 0; step < 12; step++) {
- _priorityTable[yPos++] = priority < 4 ? 4 : priority;
+ priorityTable[yPos++] = priority < 4 ? 4 : priority;
}
}
}
@@ -776,11 +1243,35 @@ void GfxMgr::setPriorityTable(int16 priorityBase) {
}
}
+// used for saving
+int16 GfxMgr::saveLoadGetPriority(int16 yPos) {
+ assert(yPos < SCRIPT_HEIGHT);
+ return _priorityTable[yPos];
+}
+bool GfxMgr::saveLoadWasPriorityTableModified() {
+ return _priorityTableSet;
+}
+
// used for restoring
-void GfxMgr::setPriority(int16 yPos, int16 priority) {
+void GfxMgr::saveLoadSetPriority(int16 yPos, int16 priority) {
assert(yPos < SCRIPT_HEIGHT);
_priorityTable[yPos] = priority;
}
+void GfxMgr::saveLoadSetPriorityTableModifiedBool(bool wasModified) {
+ _priorityTableSet = wasModified;
+}
+void GfxMgr::saveLoadFigureOutPriorityTableModifiedBool() {
+ uint8 defaultPriorityTable[SCRIPT_HEIGHT]; /**< priority table */
+
+ createDefaultPriorityTable(defaultPriorityTable);
+
+ if (memcmp(defaultPriorityTable, _priorityTable, sizeof(_priorityTable)) == 0) {
+ // Match, it is the default table, so reset the flag
+ _priorityTableSet = false;
+ } else {
+ _priorityTableSet = true;
+ }
+}
/**
* Convert sprite priority to y value.
@@ -793,7 +1284,8 @@ int16 GfxMgr::priorityToY(int16 priority) {
return (priority - 5) * 12 + 48;
}
- // dynamic priority bands were introduced in 3.002.086 (effectively AGI3)
+ // Dynamic priority bands were introduced in 2.425, but removed again until 2.936 (effectively last version of AGI2)
+ // They are available from 2.936 onwards.
// It seems there was a glitch, that caused priority bands to not get calculated properly.
// It was caused by this function starting with Y = 168 instead of 167, which meant it always
// returned with 168 as result.
@@ -804,6 +1296,8 @@ int16 GfxMgr::priorityToY(int16 priority) {
// drawn first, followed by ego, which would then draw ego over the dwarf.
// For more information see bug #1712585 (dwarf sprite priority)
//
+ // This glitch is definitely present in 2.425, 2.936 and 3.002.086.
+ //
// Priority bands were working properly in: 3.001.098 (Black Cauldron)
uint16 agiVersion = _vm->getVersion();
@@ -925,7 +1419,38 @@ int GfxMgr::getAGIPalFileNum() {
}
void GfxMgr::initMouseCursor(MouseCursorData *mouseCursor, const byte *bitmapData, uint16 width, uint16 height, int hotspotX, int hotspotY) {
- mouseCursor->bitmapData = bitmapData;
+ switch (_upscaledHires) {
+ case DISPLAY_UPSCALED_DISABLED:
+ mouseCursor->bitmapData = bitmapData;
+ break;
+ case DISPLAY_UPSCALED_640x400: {
+ mouseCursor->bitmapDataAllocated = (byte *)malloc(width * height * 4);
+ mouseCursor->bitmapData = mouseCursor->bitmapDataAllocated;
+
+ // Upscale mouse cursor
+ byte *upscaledData = mouseCursor->bitmapDataAllocated;
+
+ for (uint16 y = 0; y < height; y++) {
+ for (uint16 x = 0; x < width; x++) {
+ byte curColor = *bitmapData++;
+ upscaledData[x * 2 + 0] = curColor;
+ upscaledData[x * 2 + 1] = curColor;
+ upscaledData[x * 2 + (width * 2) + 0] = curColor;
+ upscaledData[x * 2 + (width * 2) + 1] = curColor;
+ }
+ upscaledData += width * 2 * 2;
+ }
+
+ width *= 2;
+ height *= 2;
+ hotspotX *= 2;
+ hotspotY *= 2;
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
mouseCursor->width = width;
mouseCursor->height = height;
mouseCursor->hotspotX = hotspotX;
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index fb596626c6..1cb595cdfa 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -29,13 +29,15 @@ namespace Agi {
#define SCRIPT_WIDTH 160
#define SCRIPT_HEIGHT 168
-#define DISPLAY_WIDTH 320
-#define DISPLAY_HEIGHT 200
-
-#define GFX_WIDTH 320
-#define GFX_HEIGHT 200
-#define CHAR_COLS 8
-#define CHAR_LINES 8
+#define VISUAL_WIDTH 160
+#define VISUAL_HEIGHT 200
+#define DISPLAY_DEFAULT_WIDTH 320
+#define DISPLAY_DEFAULT_HEIGHT 200
+
+enum GfxScreenUpscaledMode {
+ DISPLAY_UPSCALED_DISABLED = 0,
+ DISPLAY_UPSCALED_640x400 = 1
+};
class AgiEngine;
@@ -47,6 +49,7 @@ enum GfxScreenMasks {
struct MouseCursorData {
const byte *bitmapData;
+ byte *bitmapDataAllocated;
uint16 width;
uint16 height;
int hotspotX;
@@ -56,6 +59,7 @@ struct MouseCursorData {
class GfxMgr {
private:
AgiBase *_vm;
+ GfxFont *_font;
uint8 _paletteGfxMode[256 * 3];
uint8 _paletteTextMode[256 * 3];
@@ -64,7 +68,7 @@ private:
int _agipalFileNum;
public:
- GfxMgr(AgiBase *vm);
+ GfxMgr(AgiBase *vm, GfxFont *font);
int initVideo();
int deinitVideo();
@@ -78,18 +82,58 @@ public:
void setMouseCursor(bool busy = false);
void setRenderStartOffset(uint16 offsetY);
- uint16 getRenderStartOffsetY();
+ uint16 getRenderStartDisplayOffsetY();
+
+ void translateGamePosToDisplayScreen(int16 &x, int16 &y);
+ void translateVisualPosToDisplayScreen(int16 &x, int16 &y);
+ void translateDisplayPosToGameScreen(int16 &x, int16 &y);
+
+ void translateVisualDimensionToDisplayScreen(int16 &width, int16 &height);
+ void translateDisplayDimensionToVisualScreen(int16 &width, int16 &height);
+
+ void translateGameRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
+ void translateVisualRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
+ void translateDisplayRectToVisualScreen(int16 &x, int16 &y, int16 &width, int16 &height);
+
+ uint32 getDisplayOffsetToGameScreenPos(int16 x, int16 y);
+ uint32 getDisplayOffsetToVisualScreenPos(int16 x, int16 y);
+
+ void copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height);
+ void copyDisplayRectToScreen(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight);
+ void copyDisplayRectToScreenUsingGamePos(int16 x, int16 y, int16 width, int16 height);
+ void copyDisplayRectToScreenUsingVisualPos(int16 x, int16 y, int16 width, int16 height);
+ void copyDisplayToScreen();
+
+ void translateFontPosToDisplayScreen(int16 &x, int16 &y);
+ void translateDisplayPosToFontScreen(int16 &x, int16 &y);
+ void translateFontDimensionToDisplayScreen(int16 &width, int16 &height);
+ void translateFontRectToDisplayScreen(int16 &x, int16 &y, int16 &width, int16 &height);
+ Common::Rect getFontRectForDisplayScreen(int16 column, int16 row, int16 width, int16 height);
private:
uint _pixels;
- //uint16 _displayWidth;
- //uint16 _displayHeight;
uint _displayPixels;
byte *_activeScreen;
- byte *_visualScreen; // 160x168
- byte *_priorityScreen; // 160x168
- byte *_displayScreen; // 320x200
+ byte *_gameScreen; // 160x168 - screen, where the actual game content is drawn to (actual graphics, not including status line, prompt, etc.)
+ byte *_priorityScreen; // 160x168 - screen contains priority information of the game screen
+ // the term "visual screen" is effectively the display screen, but at 160x200 resolution. Used for coordinate translation
+ byte *_displayScreen; // 320x200 or 640x400 - screen, that the game is rendered to and which is then copied to framebuffer
+
+ uint16 _displayScreenWidth;
+ uint16 _displayScreenHeight;
+
+ uint16 _displayFontWidth;
+ uint16 _displayFontHeight;
+
+ uint16 _displayWidthMulAdjust;
+ uint16 _displayHeightMulAdjust;
+
+ /**
+ * This variable defines, if upscaled hires is active and what upscaled mode
+ * is used.
+ */
+ GfxScreenUpscaledMode _upscaledHires;
bool _priorityTableSet;
uint8 _priorityTable[SCRIPT_HEIGHT]; /**< priority table */
@@ -97,15 +141,32 @@ private:
MouseCursorData _mouseCursor;
MouseCursorData _mouseCursorBusy;
- uint16 _renderStartOffsetY;
+ uint16 _renderStartVisualOffsetY;
+ uint16 _renderStartDisplayOffsetY;
public:
+ uint16 getDisplayScreenWidth() {
+ return _displayScreenWidth;
+ }
+ uint16 getDisplayFontWidth() {
+ return _displayFontWidth;
+ }
+ uint16 getDisplayFontHeight() {
+ return _displayFontHeight;
+ }
+
+ GfxScreenUpscaledMode getUpscaledHires() {
+ return _upscaledHires;
+ }
+
void debugShowMap(int mapNr);
void clear(byte color, byte priority);
void clearDisplay(byte color, bool copyToScreen = true);
void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority);
void putPixelOnDisplay(int16 x, int16 y, byte color);
+ void putPixelOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, byte color);
+ void putFontPixelOnDisplay(int16 baseX, int16 baseY, int16 addX, int16 addY, byte color, bool isHires);
byte getColor(int16 x, int16 y);
byte getPriority(int16 x, int16 y);
@@ -119,6 +180,7 @@ public:
private:
void render_BlockEGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen);
void render_BlockCGA(int16 x, int16 y, int16 width, int16 height, bool copyToScreen);
+ void render_BlockHercules(int16 x, int16 y, int16 width, int16 height, bool copyToScreen);
public:
void transition_Amiga();
@@ -127,11 +189,9 @@ public:
void block_save(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
void block_restore(int16 x, int16 y, int16 width, int16 height, byte *bufferPtr);
- void copyDisplayRectToScreen(int16 x, int16 y, int16 width, int16 height);
-
void drawBox(int16 x, int16 y, int16 width, int16 height, byte backgroundColor, byte lineColor);
- void drawRect(int16 x, int16 y, int16 width, int16 height, byte color);
void drawDisplayRect(int16 x, int16 y, int16 width, int16 height, byte color, bool copyToScreen = true);
+ void drawDisplayRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight, byte color, bool copyToScreen = true);
private:
void drawDisplayRectEGA(int16 x, int16 y, int16 width, int16 height, byte color);
void drawDisplayRectCGA(int16 x, int16 y, int16 width, int16 height, byte color);
@@ -139,14 +199,21 @@ private:
public:
void drawCharacter(int16 row, int16 column, byte character, byte foreground, byte background, bool disabledLook);
void drawStringOnDisplay(int16 x, int16 y, const char *text, byte foreground, byte background);
+ void drawStringOnDisplay(int16 x, int16 adjX, int16 y, int16 adjY, const char *text, byte foregroundColor, byte backgroundColor);
void drawCharacterOnDisplay(int16 x, int16 y, byte character, byte foreground, byte background, byte transformXOR = 0, byte transformOR = 0);
void shakeScreen(int16 repeatCount);
void updateScreen();
void initPriorityTable();
+ void createDefaultPriorityTable(uint8 *priorityTable);
void setPriorityTable(int16 priorityBase);
- void setPriority(int16 yPos, int16 priority);
+ bool saveLoadWasPriorityTableModified();
+ int16 saveLoadGetPriority(int16 yPos);
+ void saveLoadSetPriorityTableModifiedBool(bool wasModified);
+ void saveLoadSetPriority(int16 yPos, int16 priority);
+ void saveLoadFigureOutPriorityTableModifiedBool();
+
int16 priorityToY(int16 priority);
int16 priorityFromY(int16 yPos);
};
diff --git a/engines/agi/inv.cpp b/engines/agi/inv.cpp
index 1df5282622..834fa9badc 100644
--- a/engines/agi/inv.cpp
+++ b/engines/agi/inv.cpp
@@ -34,6 +34,8 @@ InventoryMgr::InventoryMgr(AgiEngine *agi, GfxMgr *gfx, TextMgr *text, SystemUI
_gfx = gfx;
_text = text;
_systemUI = systemUI;
+
+ _activeItemNr = -1;
}
InventoryMgr::~InventoryMgr() {
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 5a73afe6fb..3bc45af5d4 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -130,7 +130,7 @@ void AgiEngine::processScummVMEvents() {
}
break;
case Common::EVENT_KEYDOWN:
- if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) {
+ if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && event.kbd.keycode == Common::KEYCODE_d) {
_console->attach();
break;
}
@@ -256,7 +256,28 @@ void AgiEngine::processScummVMEvents() {
// Original AGI actually created direction events in here
// We don't do that, that's why we create a stationary event instead, which will
// result in a direction change to 0 in handleController().
- keyEnqueue(AGI_KEY_STATIONARY);
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_HOME:
+ case Common::KEYCODE_END:
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_KP9:
+ case Common::KEYCODE_KP3:
+ case Common::KEYCODE_KP7:
+ case Common::KEYCODE_KP1:
+ keyEnqueue(AGI_KEY_STATIONARY);
+ break;
+ default:
+ break;
+ }
}
break;
@@ -292,7 +313,8 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
if (!cycleInnerLoopIsActive()) {
// Only do this, when no inner loop is currently active
- Common::Rect displayLineRect(DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
+ Common::Rect displayLineRect = _gfx->getFontRectForDisplayScreen(0, 0, FONT_COLUMN_CHARACTERS, 1);
+// Common::Rect displayLineRect(_gfx->getDisplayScreenWidth(), _gfx->getDisplayFontHeight());
if (displayLineRect.contains(_mouse.pos)) {
// Mouse is inside first line of the screen
@@ -307,7 +329,7 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
// Prompt is currently enabled
int16 promptRow = _text->promptRow_Get();
- displayLineRect.moveTo(0, promptRow * FONT_DISPLAY_HEIGHT);
+ displayLineRect.moveTo(0, promptRow * _gfx->getDisplayFontHeight());
if (displayLineRect.contains(_mouse.pos)) {
// and user clicked within the line of the prompt
@@ -330,9 +352,7 @@ bool AgiEngine::handleMouseClicks(uint16 &key) {
_text->stringPos_Get(stringRow, stringColumn);
stringMaxLen = _text->stringGetMaxLen();
- Common::Rect displayRect(stringMaxLen * FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
- displayRect.moveTo(stringColumn * FONT_DISPLAY_WIDTH, stringRow * FONT_DISPLAY_HEIGHT);
-
+ Common::Rect displayRect = _gfx->getFontRectForDisplayScreen(stringColumn, stringRow, stringMaxLen, 1);
if (displayRect.contains(_mouse.pos)) {
// user clicked inside the input space
showPredictiveDialog();
@@ -472,7 +492,7 @@ bool AgiEngine::handleController(uint16 key) {
// in case you walked to the log by using the mouse, so don't!!!
int16 egoDestinationX = _mouse.pos.x;
int16 egoDestinationY = _mouse.pos.y;
- adjustPosToGameScreen(egoDestinationX, egoDestinationY);
+ _gfx->translateDisplayPosToGameScreen(egoDestinationX, egoDestinationY);
screenObjEgo->motionType = kMotionEgo;
if (egoDestinationX < (screenObjEgo->xSize / 2)) {
diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp
index 803efd757e..49c2d0eeab 100644
--- a/engines/agi/menu.cpp
+++ b/engines/agi/menu.cpp
@@ -49,8 +49,8 @@ GfxMenu::GfxMenu(AgiEngine *vm, GfxMgr *gfx, PictureMgr *picture, TextMgr *text)
_drawnMenuNr = -1;
_drawnMenuHeight = 0;
_drawnMenuWidth = 0;
- _drawnMenuRow = 0;
- _drawnMenuColumn = 0;
+ _drawnMenuY = 0;
+ _drawnMenuX = 0;
}
GfxMenu::~GfxMenu() {
@@ -64,6 +64,8 @@ GfxMenu::~GfxMenu() {
}
void GfxMenu::addMenu(const char *menuText) {
+ int16 curColumnEnd = _setupMenuColumn;
+
// already submitted? in that case no further changes possible
if (_submitted)
return;
@@ -72,6 +74,18 @@ void GfxMenu::addMenu(const char *menuText) {
menuEntry->text = menuText;
menuEntry->textLen = menuEntry->text.size();
+
+ // Cut menu name in case menu bar is full
+ // Happens in at least the fan game Get Outta Space Quest
+ // Original interpreter had graphical issues in this case
+ // TODO: this whole code needs to get reworked anyway to support different types of menu bars depending on platform
+ curColumnEnd += menuEntry->textLen;
+ while ((menuEntry->textLen) && (curColumnEnd > 40)) {
+ menuEntry->text.deleteLastChar();
+ menuEntry->textLen--;
+ curColumnEnd--;
+ }
+
menuEntry->row = 0;
menuEntry->column = _setupMenuColumn;
menuEntry->itemCount = 0;
@@ -309,8 +323,9 @@ void GfxMenu::execute() {
// Unless we are in "via mouse" mode. In that case check current mouse position
if (viaMouse) {
- int16 mouseRow = _vm->_mouse.pos.y / FONT_DISPLAY_HEIGHT;
- int16 mouseColumn = _vm->_mouse.pos.x / FONT_DISPLAY_WIDTH;
+ int16 mouseRow = _vm->_mouse.pos.y;
+ int16 mouseColumn = _vm->_mouse.pos.x;
+ _gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
mouseFindMenuSelection(mouseRow, mouseColumn, _drawnMenuNr, _mouseModeItemNr);
}
@@ -354,7 +369,7 @@ void GfxMenu::execute() {
// WORKAROUND: Playarea starts right at the stop, so instead of clearing that part, render it from playarea
// Required for at least Donald Duck
// This was not done by original AGI, which means the upper pixel line were cleared in this case.
- _gfx->render_Block(0, (1 * FONT_VISUAL_HEIGHT) - 1, SCRIPT_WIDTH, FONT_VISUAL_HEIGHT);
+ _gfx->render_Block(0, 0, SCRIPT_WIDTH, FONT_VISUAL_HEIGHT);
} else {
_text->clearLine(0, 0);
}
@@ -365,6 +380,10 @@ void GfxMenu::drawMenuName(int16 menuNr, bool inverted) {
GuiMenuEntry *menuEntry = _array[menuNr];
bool disabledLook = false;
+ // Don't draw in case there is no text
+ if (!menuEntry->text.size())
+ return;
+
if (!inverted) {
_text->charAttrib_Set(0, _text->calculateTextBackground(15));
} else {
@@ -409,10 +428,11 @@ void GfxMenu::drawMenu(int16 selectedMenuNr, int16 selectedMenuItemNr) {
// calculate active menu dimensions
_drawnMenuHeight = (menuEntry->itemCount + 2) * FONT_VISUAL_HEIGHT;
_drawnMenuWidth = (menuEntry->maxItemTextLen * FONT_VISUAL_WIDTH) + 8;
- _drawnMenuRow = (menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
- _drawnMenuColumn = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
+ _drawnMenuY = (1 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT;
+ //(menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
+ _drawnMenuX = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
- _gfx->drawBox(_drawnMenuColumn, _drawnMenuRow, _drawnMenuWidth, _drawnMenuHeight, 15, 0);
+ _gfx->drawBox(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight, 15, 0);
while (itemCount) {
if (itemNr == selectedMenuItemNr) {
@@ -430,7 +450,7 @@ void GfxMenu::removeActiveMenu(int16 selectedMenuNr) {
drawMenuName(selectedMenuNr, false);
// overwrite actual menu items by rendering play screen
- _gfx->render_Block(_drawnMenuColumn, _drawnMenuRow, _drawnMenuWidth, _drawnMenuHeight);
+ _gfx->render_Block(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight);
}
void GfxMenu::keyPress(uint16 newKey) {
@@ -531,8 +551,10 @@ void GfxMenu::keyPress(uint16 newKey) {
// In "via mouse" mode, we check if user let go of the left mouse button and then select the item that way
void GfxMenu::mouseEvent(uint16 newKey) {
// Find out, where current mouse cursor actually is
- int16 mouseRow = _vm->_mouse.pos.y / FONT_DISPLAY_HEIGHT;
- int16 mouseColumn = _vm->_mouse.pos.x / FONT_DISPLAY_WIDTH;
+ int16 mouseRow = _vm->_mouse.pos.y;
+ int16 mouseColumn = _vm->_mouse.pos.x;
+
+ _gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
int16 activeMenuNr, activeItemNr;
mouseFindMenuSelection(mouseRow, mouseColumn, activeMenuNr, activeItemNr);
@@ -620,7 +642,7 @@ void GfxMenu::mouseFindMenuSelection(int16 mouseRow, int16 mouseColumn, int16 &a
if (mouseRow == menuEntry->row) {
// line match
- if ((mouseColumn >= menuEntry->column) && (mouseColumn <= (menuEntry->column + menuEntry->textLen))) {
+ if ((mouseColumn >= menuEntry->column) && (mouseColumn < (menuEntry->column + menuEntry->textLen))) {
// full match
activeMenuNr = menuNr;
activeMenuItemNr = -1; // no item selected
@@ -642,7 +664,7 @@ void GfxMenu::mouseFindMenuSelection(int16 mouseRow, int16 mouseColumn, int16 &a
if (mouseRow == itemEntry->row) {
// line match
- if ((mouseColumn >= itemEntry->column) && (mouseColumn <= (itemEntry->column + itemEntry->textLen))) {
+ if ((mouseColumn >= itemEntry->column) && (mouseColumn < (itemEntry->column + itemEntry->textLen))) {
// full match
if (itemEntry->enabled) {
// Only see it, when it's currently enabled
diff --git a/engines/agi/menu.h b/engines/agi/menu.h
index a621d7f0f2..b47289180b 100644
--- a/engines/agi/menu.h
+++ b/engines/agi/menu.h
@@ -111,8 +111,8 @@ private:
uint16 _drawnMenuHeight;
uint16 _drawnMenuWidth;
- int16 _drawnMenuRow;
- int16 _drawnMenuColumn;
+ int16 _drawnMenuY;
+ int16 _drawnMenuX;
// Following variables are used in "via mouse" mode
int16 _mouseModeItemNr;
diff --git a/engines/agi/motion.cpp b/engines/agi/motion.cpp
index 7f49028701..f408ba35e6 100644
--- a/engines/agi/motion.cpp
+++ b/engines/agi/motion.cpp
@@ -62,6 +62,60 @@ void AgiEngine::changePos(ScreenObjEntry *screenObj) {
}
}
+// WORKAROUND:
+// A motion was just activated, check if "end.of.loop"/"reverse.loop" is currently active for the same screen object
+// If this is the case, it would result in some random flag getting overwritten in original AGI after the loop was
+// completed, because in original AGI loop_flag + wander_count/follow_stepSize/move_X shared the same memory location.
+// This is basically an implementation error in the original interpreter.
+// Happens in at least:
+// - BC: right at the end when the witches disappear at least on Apple IIgs (room 12, screen object 13, view 84)
+// - KQ1: when grabbing the eagle (room 22).
+// - KQ2: happened somewhere in the game, LordHoto couldn't remember exactly where
+void AgiEngine::motionActivated(ScreenObjEntry *screenObj) {
+ if (screenObj->flags & fCycling) {
+ // Cycling active too
+ switch (screenObj->cycle) {
+ case kCycleEndOfLoop: // "end.of.loop"
+ case kCycleRevLoop: // "reverse.loop"
+ // Disable it
+ screenObj->flags &= ~fCycling;
+ screenObj->cycle = kCycleNormal;
+
+ warning("Motion activated for screen object %d, but cycler also active", screenObj->objectNr);
+ warning("This would have resulted in flag corruption in original AGI. Cycler disabled.");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+// WORKAROUND:
+// See comment for motionActivated()
+// This way no flag would have been overwritten, but certain other variables of the motions.
+void AgiEngine::cyclerActivated(ScreenObjEntry *screenObj) {
+ switch (screenObj->motionType) {
+ case kMotionWander:
+ // this would have resulted in wander_count to get corrupted
+ // We don't stop it.
+ break;
+ case kMotionFollowEgo:
+ // this would have resulted in follow_stepSize to get corrupted
+ // do not stop motion atm - screenObj->direction = 0;
+ // do not stop motion atm - screenObj->motionType = kMotionNormal;
+ break;
+ case kMotionMoveObj:
+ // this would have resulted in move_x to get corrupted
+ // do not stop motion atm - motionMoveObjStop(screenObj);
+ break;
+ default:
+ return;
+ break;
+ }
+ warning("Cycler activated for screen object %d, but motion also active", screenObj->objectNr);
+ warning("This would have resulted in corruption in original AGI. Motion disabled.");
+}
+
void AgiEngine::motionWander(ScreenObjEntry *screenObj) {
uint8 originalWanderCount = screenObj->wander_count;
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 3f8630521d..fed07ea986 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -37,7 +37,6 @@
namespace Agi {
-#define getGameID() state->_vm->getGameID()
#define getFeatures() state->_vm->getFeatures()
#define getVersion() state->_vm->getVersion()
#define getLanguage() state->_vm->getLanguage()
@@ -82,7 +81,7 @@ void cmdAssignN(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// variable to the correct value here
// Fixes bug #1942476 - "AGI: Fan(Get Outta SQ) - Score
// is lost on restart"
- if (getGameID() == GID_GETOUTTASQ && varNr == 7)
+ if (vm->getGameID() == GID_GETOUTTASQ && varNr == 7)
vm->setVar(varNr, 8);
}
@@ -890,6 +889,19 @@ void cmdObjStatusF(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// unk_181: Deactivate keypressed control (default control of ego)
void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
if (!(getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
+ // set.simple is called by Larry 1 on Apple IIgs at the store, after answering the 555-6969 phone.
+ // load.sound(16) is called right before it. Interpreter is 2.440-like.
+ // it's called with parameter 16.
+ // Original interpreter doesn't seem to play any sound.
+ // TODO: Figure out what's going on. It can't be automatic saving of course.
+ // Also getting called in KQ1, when planting beans - parameter 12.
+ // And when killing the witch - parameter 40.
+ if ((getVersion() < 0x2425) || (getVersion() == 0x2440)) {
+ // was not available before 2.2425, but also not available in 2.440
+ warning("set.simple called, although not available for current AGI version");
+ return;
+ }
+
int16 stringNr = parameter[0];
const char *textPtr = nullptr;
@@ -897,7 +909,10 @@ void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// Try to get description for automatic saves
textPtr = state->strings[stringNr];
+
strncpy(state->automaticSaveDescription, textPtr, sizeof(state->automaticSaveDescription));
+ state->automaticSaveDescription[sizeof(state->automaticSaveDescription) - 1] = 0;
+
if (state->automaticSaveDescription[0]) {
// We got it and it's set, so enable automatic saving
state->automaticSave = true;
@@ -917,21 +932,26 @@ void cmdSetSimple(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
spritesMgr->drawAllSpriteLists();
state->pictureShown = false;
+ // Loading trigger
+ vm->artificialDelayTrigger_DrawPicture(resourceNr);
+
// Show the picture. Similar to void cmdShow_pic(AgiGame *state, AgiEngine *vm, uint8 *p).
vm->setFlag(VM_FLAG_OUTPUT_MODE, false);
vm->_text->closeWindow();
vm->_picture->showPic();
state->pictureShown = true;
-
- // Loading trigger
- vm->loadingTrigger_DrawPicture();
}
}
+// push.script was not available until 2.425, and also not available in 2.440
void cmdPopScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (getVersion() >= 0x2915) {
- debug(0, "pop.script");
+ if ((getVersion() < 0x2425) || (getVersion() == 0x2440)) {
+ // was not available before 2.2425, but also not available in 2.440
+ warning("pop.script called, although not available for current AGI version");
+ return;
}
+
+ debug(0, "pop.script");
}
void cmdDiscardSound(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -953,8 +973,18 @@ void cmdShowMouse(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// but show.mouse is never called afterwards. Game running under emulator doesn't seem to hide the mouse cursor.
// TODO: figure out, what exactly happens. Probably some hacked-in command and not related to mouse cursor for that game?
void cmdHideMouse(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (getVersion() < 0x3000)
+ if (getVersion() < 0x3000) {
+ // was not available before 3.086
+ warning("hide.mouse, although not available for current AGI version");
+ return;
+ }
+
+ if ((vm->getGameID() == GID_MH1) && (vm->getPlatform() == Common::kPlatformApple2GS)) {
+ // Called right after beating arcade sequence on day 4 in the hospital Parameter is "1".
+ // Right before cutscene. show.mouse isn't called. Probably different function.
+ warning("hide.mouse called, disabled for MH1 Apple IIgs");
return;
+ }
// WORKAROUND: Turns off current movement that's being caused with the mouse.
// This fixes problems with too many popup boxes appearing in the Amiga
@@ -972,14 +1002,18 @@ void cmdHideMouse(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
}
void cmdAllowMenu(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
+ if (getVersion() < 0x3098) {
+ // was not available before 3.098
+ warning("allow.menu called, although not available for current AGI version");
+ return;
+ }
+
uint16 allowed = parameter[0];
- if (getVersion() >= 0x3098) {
- if (allowed) {
- state->_vm->_menu->accessAllow();
- } else {
- state->_vm->_menu->accessDeny();
- }
+ if (allowed) {
+ state->_vm->_menu->accessAllow();
+ } else {
+ state->_vm->_menu->accessDeny();
}
}
@@ -997,15 +1031,21 @@ void cmdFenceMouse(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// HoldKey was added in 2.425
// There was no way to disable this mode until 3.098 though
void cmdHoldKey(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (getVersion() < 0x2425)
+ if ((getVersion() < 0x2425) || (getVersion() == 0x2440)) {
+ // was not available before 2.425, but also not available in 2.440
+ warning("hold.key called, although not available for current AGI version");
return;
+ }
vm->_keyHoldMode = true;
}
void cmdReleaseKey(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
- if (getVersion() < 0x3098)
+ if (getVersion() < 0x3098) {
+ // was not available before 3.098
+ warning("release.key called, although not available for current AGI version");
return;
+ }
vm->_keyHoldMode = false;
}
@@ -1094,7 +1134,7 @@ void cmdDrawPicV1(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
vm->_text->promptClear();
// Loading trigger
- vm->loadingTrigger_DrawPicture();
+ vm->artificialDelayTrigger_DrawPicture(resourceNr);
}
void cmdDrawPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1106,6 +1146,7 @@ void cmdDrawPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
spritesMgr->eraseSprites();
vm->_picture->decodePicture(resourceNr, true);
+
spritesMgr->buildAllSpriteLists();
spritesMgr->drawAllSpriteLists();
state->pictureShown = false;
@@ -1123,11 +1164,11 @@ void cmdDrawPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// above the ground), flag 103 is reset, thereby fixing this issue. Note
// that this is a script bug and occurs in the original interpreter as well.
// Fixes bug #3056: AGI: SQ1 (2.2 DOS ENG) bizzare exploding roger
- if (getGameID() == GID_SQ1 && resourceNr == 20)
+ if (vm->getGameID() == GID_SQ1 && resourceNr == 20)
vm->setFlag(103, false);
// Loading trigger
- vm->loadingTrigger_DrawPicture();
+ vm->artificialDelayTrigger_DrawPicture(resourceNr);
}
void cmdShowPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1179,7 +1220,7 @@ void cmdOverlayPic(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
state->pictureShown = false;
// Loading trigger
- vm->loadingTrigger_DrawPicture();
+ vm->artificialDelayTrigger_DrawPicture(resourceNr);
}
void cmdShowPriScreen(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1454,6 +1495,8 @@ void cmdReverseLoop(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
screenObj->flags |= (fDontupdate | fUpdate | fCycling);
screenObj->loop_flag = loopFlag;
state->_vm->setFlag(screenObj->loop_flag, false);
+
+ vm->cyclerActivated(screenObj);
}
void cmdReverseLoopV1(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1479,6 +1522,8 @@ void cmdEndOfLoop(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
screenObj->flags |= (fDontupdate | fUpdate | fCycling);
screenObj->loop_flag = loopFlag;
vm->setFlag(screenObj->loop_flag, false);
+
+ vm->cyclerActivated(screenObj);
}
void cmdEndOfLoopV1(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1591,6 +1636,8 @@ void cmdFollowEgo(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
vm->setFlag(screenObj->follow_flag, false);
screenObj->flags |= fUpdate;
}
+
+ vm->motionActivated(screenObj);
}
void cmdMoveObj(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1619,6 +1666,8 @@ void cmdMoveObj(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
screenObj->flags |= fUpdate;
}
+ vm->motionActivated(screenObj);
+
if (objectNr == 0)
state->playerControl = false;
@@ -1647,6 +1696,8 @@ void cmdMoveObjF(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
vm->setFlag(screenObj->move_flag, false);
screenObj->flags |= fUpdate;
+ vm->motionActivated(screenObj);
+
if (objectNr == 0)
state->playerControl = false;
@@ -1668,6 +1719,8 @@ void cmdWander(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
} else {
screenObj->flags |= fUpdate;
}
+
+ vm->motionActivated(screenObj);
}
void cmdSetGameID(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
@@ -1857,7 +1910,7 @@ void cmdDistance(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// wouldn't chase Rosella around anymore. If it had worked correctly the zombie
// wouldn't have come up at all or it would have come up and gone back down
// immediately. The latter approach is the one implemented here.
- if (getGameID() == GID_KQ4 && (vm->getVar(VM_VAR_CURRENT_ROOM) == 16 || vm->getVar(VM_VAR_CURRENT_ROOM) == 18) && destVarNr >= 221 && destVarNr <= 223) {
+ if (vm->getGameID() == GID_KQ4 && (vm->getVar(VM_VAR_CURRENT_ROOM) == 16 || vm->getVar(VM_VAR_CURRENT_ROOM) == 18) && destVarNr >= 221 && destVarNr <= 223) {
// Rooms 16 and 18 are graveyards where three zombies come up at night. They use logics 16 and 18.
// Variables 221-223 are used to save the distance between each zombie and Rosella.
// Variables 155, 156 and 162 are used to save the state of each zombie in room 16.
@@ -2132,6 +2185,7 @@ void cmdPrintAtV(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
state->_vm->_text->printAt(textNr, textRow, textColumn, textWidth);
}
+// push.script was not available until 2.425, and also not available in 2.440
void cmdPushScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
// We run AGIMOUSE always as a side effect
//if (getFeatures() & GF_AGIMOUSE || true) {
@@ -2146,6 +2200,20 @@ void cmdPushScript(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
}
void cmdSetPriBase(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
+ if ((getVersion() != 0x2425) && (getVersion() < 0x2936)) {
+ // was only available in the 2.425 interpreter and from 2.936 (last AGI2 version) onwards
+ // Called during KQ3 (Apple IIgs):
+ // - picking up chicken (parameter = 50)
+ // - opening store/tavern door (parameter = 19)
+ // - when pirates say "Land Ho" (parameter = 16)
+ // - when killing the dragon (parameter = 4)
+ // Also called by SQ2 (Apple IIgs):
+ // - in Vohaul's lair (SQ2 currently gets this call through, which breaks some priority)
+ // TODO: Figure out what's going on
+ warning("set.pri.base called, although not available for current AGI version");
+ return;
+ }
+
uint16 priorityBase = parameter[0];
debug(0, "Priority base set to %d", priorityBase);
@@ -2159,7 +2227,7 @@ void cmdMousePosn(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
int16 mouseX = vm->_mouse.pos.x;
int16 mouseY = vm->_mouse.pos.y;
- state->_vm->adjustPosToGameScreen(mouseX, mouseY);
+ vm->_gfx->translateDisplayPosToGameScreen(mouseX, mouseY);
vm->setVar(destVarNr1, mouseX);
vm->setVar(destVarNr2, mouseY);
@@ -2285,6 +2353,9 @@ int AgiEngine::runLogic(int16 logicNr) {
}
#endif
+ // Just a counter for every instruction, that got executed
+ _instructionCounter++;
+
_game.execStack.back().curIP = state->_curLogic->cIP;
char st[101];
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 359d79ee4a..472917de77 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -343,18 +343,18 @@ AgiInstruction insV2[] = {
{ "div.n", "vn", &cmdDivN }, // B7
{ "div.v", "vv", &cmdDivV }, // B8
{ "close.window", "", &cmdCloseWindow }, // B9
- { "set.simple", "n", &cmdSetSimple }, // BA
+ { "set.simple", "n", &cmdSetSimple }, // BA AGI2.425+, *BUT* not included in AGI2.440
{ "push.script", "", &cmdPushScript }, // BB
{ "pop.script", "", &cmdPopScript }, // BC
{ "hold.key", "", &cmdHoldKey }, // BD
- { "set.pri.base", "n", &cmdSetPriBase }, // BE
- { "discard.sound", "n", &cmdDiscardSound }, // BF
- { "hide.mouse", "", &cmdHideMouse }, // 1 arg for AGI version 3.002.086
+ { "set.pri.base", "n", &cmdSetPriBase }, // BE AGI2.936+ *AND* also inside AGI2.425
+ { "discard.sound", "n", &cmdDiscardSound }, // BF was skip for PC
+ { "hide.mouse", "", &cmdHideMouse }, // C0 1 arg for AGI version 3.002.086 AGI3+ only starts here
{ "allow.menu", "n", &cmdAllowMenu }, // C1
{ "show.mouse", "", &cmdShowMouse }, // C2
{ "fence.mouse", "nnnn", &cmdFenceMouse }, // C3
{ "mouse.posn", "vv", &cmdMousePosn }, // C4
- { "release.key", "", &cmdReleaseKey }, // 2 args for at least the Amiga GR (v2.05 1989-03-09) using AGI 2.316
+ { "release.key", "", &cmdReleaseKey }, // C5 2 args for at least the Amiga GR (v2.05 1989-03-09) using AGI 2.316
{ "adj.ego.move.to.xy", "", &cmdAdjEgoMoveToXY } // C6
};
diff --git a/engines/agi/palette.h b/engines/agi/palette.h
index f66582b9b6..40c31da425 100644
--- a/engines/agi/palette.h
+++ b/engines/agi/palette.h
@@ -60,6 +60,22 @@ static const uint8 PALETTE_CGA[4 * 3] = {
};
/**
+ * 2 color Hercules (green) palette. Using 8-bit RGB values.
+ */
+static const uint8 PALETTE_HERCULES_GREEN[2 * 3] = {
+ 0x00, 0x00, 0x00, // black
+ 0x00, 0xdc, 0x28 // green
+};
+
+/**
+ * 2 color Hercules (amber) palette. Using 8-bit RGB values.
+ */
+static const uint8 PALETTE_HERCULES_AMBER[2 * 3] = {
+ 0x00, 0x00, 0x00, // black
+ 0xdc, 0xb4, 0x00 // amber
+};
+
+/**
* Atari ST AGI palette.
* Used by all of the tested Atari ST AGI games
* from Donald Duck's Playground (1986) to Manhunter II (1989).
@@ -122,6 +138,9 @@ static const uint8 PALETTE_APPLE_II_GS[16 * 3] = {
0xF, 0xF, 0xF
};
+// Re-use Amiga v1 palette for Apple IIgs Space Quest 1
+#define PALETTE_APPLE_II_GS_SQ1 PALETTE_AMIGA_V1
+
/**
* First generation Amiga & Apple IIGS AGI palette.
* A 16-color, 12-bit RGB palette.
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index 36eb587f68..a80e811f44 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -394,9 +394,6 @@ void PictureMgr::drawPictureC64() {
_patCode = getNextByte();
plotBrush();
break;
- case 0xfb:
- draw_LineShort();
- break;
case 0xff: // end of data
return;
default:
@@ -433,6 +430,9 @@ void PictureMgr::drawPictureV1() {
_scrOn = true;
_priOn = false;
break;
+ case 0xfb:
+ draw_LineShort();
+ break;
case 0xff: // end of data
return;
default:
@@ -1001,7 +1001,7 @@ void PictureMgr::clear() {
void PictureMgr::showPic() {
debugC(8, kDebugLevelMain, "Show picture!");
- _gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
+ _gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
}
/**
@@ -1014,8 +1014,7 @@ void PictureMgr::showPic(int16 x, int16 y, int16 pic_width, int16 pic_height) {
debugC(8, kDebugLevelMain, "Show picture!");
- // render block requires lower left coordinate!
- _gfx->render_Block(x, pic_height + y - 1, pic_width, pic_height);
+ _gfx->render_Block(x, y, pic_width, pic_height);
}
void PictureMgr::showPicWithTransition() {
@@ -1038,13 +1037,13 @@ void PictureMgr::showPicWithTransition() {
case Common::kRenderAmiga:
case Common::kRenderApple2GS:
// Platform Amiga/Apple II GS -> render and do Amiga transition
- _gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
+ _gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
_gfx->transition_Amiga();
return;
break;
case Common::kRenderAtariST:
// Platform Atari ST used a different transition, looks "high-res" (full 320x168)
- _gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
+ _gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT, false);
_gfx->transition_AtariSt();
return;
default:
@@ -1054,7 +1053,7 @@ void PictureMgr::showPicWithTransition() {
}
}
- _gfx->render_Block(0, 167, SCRIPT_WIDTH, SCRIPT_HEIGHT);
+ _gfx->render_Block(0, 0, SCRIPT_WIDTH, SCRIPT_HEIGHT);
}
// preagi needed functions (for plotPattern)
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index 104b442f5d..bb5d3b8896 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -58,7 +58,7 @@ void PreAgiEngine::initialize() {
initRenderMode();
_font = new GfxFont(this);
- _gfx = new GfxMgr(this);
+ _gfx = new GfxMgr(this, _font);
_picture = new PictureMgr(this, _gfx);
_font->init();
@@ -112,7 +112,7 @@ void PreAgiEngine::clearScreen(int attr, bool overrideDefault) {
}
void PreAgiEngine::clearGfxScreen(int attr) {
- _gfx->drawDisplayRect(0, 0, GFX_WIDTH - 1, IDI_MAX_ROW_PIC * 8 - 1, (attr & 0xF0) / 0x10);
+ _gfx->drawDisplayRect(0, 0, DISPLAY_DEFAULT_WIDTH - 1, IDI_MAX_ROW_PIC * 8 - 1, (attr & 0xF0) / 0x10);
}
// String functions
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index 8b1ae81b8e..620d5e0baf 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -957,7 +957,7 @@ void MickeyEngine::drawLogo() {
}
}
- _gfx->copyDisplayRectToScreen(0, 0, DISPLAY_WIDTH, height);
+ _gfx->copyDisplayToScreen();
delete[] fileBuffer;
}
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 1bf0dbcc02..0658609cd0 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -45,23 +45,25 @@
#include "agi/systemui.h"
#include "agi/words.h"
-#define SAVEGAME_CURRENT_VERSION 8
+#define SAVEGAME_CURRENT_VERSION 11
//
-// Version 0 (Sarien): view table has 64 entries
-// Version 1 (Sarien): view table has 256 entries (needed in KQ3)
-// Version 2 (ScummVM): first ScummVM version
-// Version 3 (ScummVM): added AGIPAL save/load support
-// Version 4 (ScummVM): added thumbnails and save creation date/time
-// Version 5 (ScummVM): Added game md5
-// Version 6 (ScummVM): Added game played time
-// Version 7 (ScummVM): Added controller key mappings
-// required for some games for quick-loading from ScummVM main menu
-// for games, that do not set all key mappings right at the start
-// Added automatic save data (for command SetSimple)
-// Version 8 (ScummVM): Added Hold-Key-Mode boolean
-// required for at least Mixed Up Mother Goose
-// gets set at the start of the game only
+// Version 0 (Sarien): view table has 64 entries
+// Version 1 (Sarien): view table has 256 entries (needed in KQ3)
+// Version 2 (ScummVM): first ScummVM version
+// Version 3 (ScummVM): added AGIPAL save/load support
+// Version 4 (ScummVM): added thumbnails and save creation date/time
+// Version 5 (ScummVM): Added game md5
+// Version 6 (ScummVM): Added game played time
+// Version 7 (ScummVM): Added controller key mappings
+// required for some games for quick-loading from ScummVM main menu
+// for games, that do not set all key mappings right at the start
+// Added automatic save data (for command SetSimple)
+// Version 8 (ScummVM): Added Hold-Key-Mode boolean
+// required for at least Mixed Up Mother Goose
+// gets set at the start of the game only
+// Version 9 (ScummVM): Added seconds to saved game time stamp
+// Version 10 (ScummVM): Added priorityTableSet boolean
namespace Agi {
@@ -109,6 +111,8 @@ int AgiEngine::saveGame(const Common::String &fileName, const Common::String &de
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save date (%d)", saveDate);
out->writeUint16BE(saveTime);
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save time (%d)", saveTime);
+ // Version 9+: save seconds of current time as well
+ out->writeByte(curTime.tm_sec & 0xFF);
out->writeUint32BE(playTime);
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing play time (%d)", playTime);
@@ -171,9 +175,11 @@ int AgiEngine::saveGame(const Common::String &fileName, const Common::String &de
out->writeSint16BE(0);
}
- // TODO: save if priority table was modified
for (i = 0; i < SCRIPT_HEIGHT; i++)
- out->writeByte(_gfx->priorityFromY(i));
+ out->writeByte(_gfx->saveLoadGetPriority(i));
+
+ // Version 10+: Save, if priority table got modified (set.pri.base opcode)
+ out->writeSint16BE((int16)_gfx->saveLoadWasPriorityTableModified());
out->writeSint16BE((int16)_game.gfxMode);
out->writeByte(_text->inputGetCursorChar());
@@ -260,6 +266,8 @@ int AgiEngine::saveGame(const Common::String &fileName, const Common::String &de
out->writeByte(screenObj->motionType);
out->writeByte(screenObj->cycle);
+ // Version 11+: loop_flag, was saved previously under vt.parm1
+ out->writeByte(screenObj->loop_flag);
out->writeByte(screenObj->priority);
out->writeUint16BE(screenObj->flags);
@@ -338,6 +346,7 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
int16 parm[7];
Common::InSaveFile *in;
bool totalPlayTimeWasSet = false;
+ byte oldLoopFlag = 0;
debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::loadGame(%s)", fileName.c_str());
@@ -384,7 +393,10 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
Graphics::skipThumbnail(*in);
in->readUint32BE(); // save date
- in->readUint16BE(); // save time
+ in->readUint16BE(); // save time (hour + minute)
+ if (saveVersion >= 9) {
+ in->readByte(); // save time seconds
+ }
if (saveVersion >= 6) {
uint32 playTime = in->readUint32BE();
inGameTimerReset(playTime * 1000);
@@ -494,7 +506,21 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
}
for (i = 0; i < SCRIPT_HEIGHT; i++)
- _gfx->setPriority(i, in->readByte());
+ _gfx->saveLoadSetPriority(i, in->readByte());
+
+ if (saveVersion >= 10) {
+ // Version 10+: priority table was modified by scripts
+ int16 priorityTableWasModified = in->readSint16BE();
+
+ if (priorityTableWasModified) {
+ _gfx->saveLoadSetPriorityTableModifiedBool(true);
+ } else {
+ _gfx->saveLoadSetPriorityTableModifiedBool(false);
+ }
+ } else {
+ // Try to figure it out by ourselves
+ _gfx->saveLoadFigureOutPriorityTableModifiedBool();
+ }
_text->closeWindow();
@@ -611,6 +637,10 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
screenObj->motionType = (MotionType)in->readByte();
screenObj->cycle = (CycleType)in->readByte();
+ if (saveVersion >= 11) {
+ // Version 11+: loop_flag, was previously vt.parm1
+ screenObj->loop_flag = in->readByte();
+ }
screenObj->priority = in->readByte();
screenObj->flags = in->readUint16BE();
@@ -618,7 +648,7 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
// this was done so that saved games compatibility isn't broken
switch (screenObj->motionType) {
case kMotionNormal:
- in->readByte();
+ oldLoopFlag = in->readByte();
in->readByte();
in->readByte();
in->readByte();
@@ -628,12 +658,14 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
in->readByte();
in->readByte();
in->readByte();
+ oldLoopFlag = screenObj->wander_count;
break;
case kMotionFollowEgo:
screenObj->follow_stepSize = in->readByte();
screenObj->follow_flag = in->readByte();
screenObj->follow_count = in->readByte();
in->readByte();
+ oldLoopFlag = screenObj->follow_stepSize;
break;
case kMotionEgo:
case kMotionMoveObj:
@@ -641,10 +673,21 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
screenObj->move_y = in->readByte();
screenObj->move_stepSize = in->readByte();
screenObj->move_flag = in->readByte();
+ oldLoopFlag = screenObj->move_x;
break;
default:
error("unknown motion-type");
}
+ if (saveVersion < 11) {
+ if (saveVersion < 7) {
+ // Recreate loop_flag from motion-type (was previously vt.parm1)
+ // vt.parm1 was shared for multiple uses
+ screenObj->loop_flag = oldLoopFlag;
+ } else {
+ // for Version 7-10 we can't really do anything, it was not saved
+ screenObj->loop_flag = 0; // set it to 0
+ }
+ }
}
for (i = vtEntries; i < SCREENOBJECTS_MAX; i++) {
memset(&_game.screenObjTable[i], 0, sizeof(ScreenObjEntry));
@@ -693,7 +736,7 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
_words->clearEgoWords();
// don't delay anything right after restoring a game
- nonBlockingText_Forget();
+ artificialDelay_Reset();
_sprites->eraseSprites();
_sprites->buildAllSpriteLists();
@@ -704,7 +747,7 @@ int AgiEngine::loadGame(const Common::String &fileName, bool checkId) {
_text->promptRedraw();
// copy everything over (we should probably only copy over the remaining parts of the screen w/o play screen
- _gfx->copyDisplayRectToScreen(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ _gfx->copyDisplayToScreen();
// Sync volume settings from ScummVM system settings, so that VM volume variable is overwritten
setVolumeViaSystemSetting();
@@ -813,7 +856,7 @@ Common::String AgiEngine::getSavegameFilename(int16 slotId) const {
return saveLoadSlot;
}
-bool AgiEngine::getSavegameInformation(int16 slotId, Common::String &saveDescription, uint32 &saveDate, uint16 &saveTime, bool &saveIsValid) {
+bool AgiEngine::getSavegameInformation(int16 slotId, Common::String &saveDescription, uint32 &saveDate, uint32 &saveTime, bool &saveIsValid) {
Common::InSaveFile *in;
Common::String fileName = getSavegameFilename(slotId);
char saveGameDescription[31];
@@ -875,7 +918,10 @@ bool AgiEngine::getSavegameInformation(int16 slotId, Common::String &saveDescrip
Graphics::skipThumbnail(*in);
saveDate = in->readUint32BE();
- saveTime = in->readUint16BE();
+ saveTime = in->readUint16BE() << 8;
+ if (saveVersion >= 9) {
+ saveTime |= in->readByte(); // add seconds (only available since saved game version 9+)
+ }
// save date is DDMMYYYY, we need a proper format
byte saveDateDay = saveDate >> 24;
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index b33591343a..b1bcee3920 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -482,6 +482,8 @@ static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint len
IIgsSample::IIgsSample(uint8 *data, uint32 len, int16 resourceNr) : AgiSound() {
Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES);
+ _sample = nullptr;
+
// Check that the header was read ok and that it's of the correct type
if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
uint32 sampleStartPos = stream.pos();
diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp
index 74f20c1d22..8263ea12ac 100644
--- a/engines/agi/sprite.cpp
+++ b/engines/agi/sprite.cpp
@@ -106,6 +106,28 @@ void SpritesMgr::buildSpriteListAdd(uint16 givenOrderNr, ScreenObjEntry *screenO
spriteEntry.yPos = (screenObj->yPos) - (screenObj->ySize) + 1;
spriteEntry.xSize = screenObj->xSize;
spriteEntry.ySize = screenObj->ySize;
+
+ // Checking, if xPos/yPos/right/bottom are valid and do not go outside of playscreen (visual screen)
+ // Original AGI did not do this (but it then resulted in memory corruption)
+ if (spriteEntry.xPos < 0) {
+ warning("buildSpriteListAdd(): ignoring screen obj %d, b/c xPos (%d) < 0", screenObj->objectNr, spriteEntry.xPos);
+ return;
+ }
+ if (spriteEntry.yPos < 0) {
+ warning("buildSpriteListAdd(): ignoring screen obj %d, b/c yPos (%d) < 0", screenObj->objectNr, spriteEntry.yPos);
+ return;
+ }
+ int16 xRight = spriteEntry.xPos + spriteEntry.xSize;
+ if (xRight > SCRIPT_HEIGHT) {
+ warning("buildSpriteListAdd(): ignoring screen obj %d, b/c rightPos (%d) > %d", screenObj->objectNr, xRight, SCRIPT_WIDTH);
+ return;
+ }
+ int16 yBottom = spriteEntry.yPos + spriteEntry.ySize;
+ if (yBottom > SCRIPT_HEIGHT) {
+ warning("buildSpriteListAdd(): ignoring screen obj %d, b/c bottomPos (%d) > %d", screenObj->objectNr, yBottom, SCRIPT_HEIGHT);
+ return;
+ }
+
// warning("list-add: %d, %d, original yPos: %d, ySize: %d", spriteEntry.xPos, spriteEntry.yPos, screenObj->yPos, screenObj->ySize);
spriteEntry.backgroundBuffer = (uint8 *)malloc(spriteEntry.xSize * spriteEntry.ySize * 2); // for visual + priority data
assert(spriteEntry.backgroundBuffer);
@@ -332,7 +354,8 @@ void SpritesMgr::showSprite(ScreenObjEntry *screenObj) {
}
// render this block
- _gfx->render_Block(x, y, width, height);
+ int16 upperY = y - height + 1;
+ _gfx->render_Block(x, upperY, width, height);
}
void SpritesMgr::showSprites(SpriteList &spriteList) {
@@ -394,7 +417,7 @@ void SpritesMgr::showObject(int16 viewNr) {
screenObj.yPos_prev = SCRIPT_HEIGHT - 1;
screenObj.yPos = screenObj.yPos_prev;
screenObj.priority = 15;
- screenObj.flags |= fFixedPriority;
+ screenObj.flags = fFixedPriority; // Original AGI did "| fFixedPriority" on uninitialized memory
screenObj.objectNr = 255; // ???
backgroundBuffer = (uint8 *)malloc(screenObj.xSize * screenObj.ySize * 2); // for visual + priority data
diff --git a/engines/agi/systemui.cpp b/engines/agi/systemui.cpp
index 2dd6629103..aeb1ded4a2 100644
--- a/engines/agi/systemui.cpp
+++ b/engines/agi/systemui.cpp
@@ -38,10 +38,14 @@ SystemUI::SystemUI(AgiEngine *vm, GfxMgr *gfx, TextMgr *text) {
_askForVerificationMouseLockedButtonNr = -1;
_askForVerificationMouseActiveButtonNr = -1;
+ clearSavedGameSlots();
+
_textStatusScore = "Score:%v3 of %v7";
_textStatusSoundOn = "Sound:on";
_textStatusSoundOff = "Sound:off";
+ _textEnterCommand = "Enter input\n\n";
+
_textPause = " Game paused.\nPress Enter to continue.";
_textPauseButton = nullptr;
@@ -212,6 +216,47 @@ const char *SystemUI::getInventoryTextReturnToGame() {
return _textInventoryReturnToGame;
}
+bool SystemUI::askForCommand(Common::String &commandText) {
+ // Let user enter the command (this was originally only available for Hercules rendering, we allow it everywhere)
+ bool previousEditState = _text->inputGetEditStatus();
+ byte previousEditCursor = _text->inputGetCursorChar();
+
+ _text->drawMessageBox(_textEnterCommand, 0, 36, true);
+
+ _text->inputEditOn();
+
+ _text->charPos_Push();
+ _text->charAttrib_Push();
+
+ _text->charPos_SetInsideWindow(2, 0);
+ _text->charAttrib_Set(15, 0);
+ _text->clearBlockInsideWindow(2, 0, 36, 0); // input line is supposed to be black
+ _text->inputSetCursorChar('_');
+
+ _text->stringSet(commandText.c_str()); // Set current command text (may be a command recall)
+
+ _vm->cycleInnerLoopActive(CYCLE_INNERLOOP_GETSTRING);
+ _text->stringEdit(35); // only allow up to 35 characters
+
+ _text->charAttrib_Pop();
+ _text->charPos_Pop();
+ _text->inputSetCursorChar(previousEditCursor);
+ if (!previousEditState) {
+ _text->inputEditOff();
+ }
+
+ _text->closeWindow();
+
+ if (!_text->stringWasEntered()) {
+ // User cancelled? exit now
+ return false;
+ }
+
+ commandText.clear();
+ commandText += (char *)_text->_inputString;
+ return true;
+}
+
int16 SystemUI::figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription) {
int16 matchedGameSlotId = -1;
int16 freshGameSlotId = -1;
@@ -327,7 +372,7 @@ int16 SystemUI::askForRestoreGameSlot() {
int16 restoreGameSlotNr = -1;
// Fill saved game slot cache
- readSavedGameSlots(true, true); // filter empty/corrupt slots, but including auto-save slot
+ readSavedGameSlots(true, true); // filter empty/corrupt slots, but include auto-save slot
if (_savedGameArray.size() == 0) {
// no saved games
@@ -526,12 +571,12 @@ void SystemUI::readSavedGameSlots(bool filterNonexistant, bool withAutoSaveSlot)
SystemUISavedGameEntry savedGameEntry;
Common::String saveDescription;
uint32 saveDate = 0;
- uint16 saveTime = 0;
+ uint32 saveTime = 0;
bool saveIsValid = false;
int16 mostRecentSlotNr = -1;
uint32 mostRecentSlotSaveDate = 0;
- uint16 mostRecentSlotSaveTime = 0;
+ uint32 mostRecentSlotSaveTime = 0;
clearSavedGameSlots();
@@ -638,6 +683,9 @@ void SystemUI::readSavedGameSlots(bool filterNonexistant, bool withAutoSaveSlot)
void SystemUI::figureOutAutomaticSavedGameSlot(const char *automaticSaveDescription, int16 &matchedGameSlotId, int16 &freshGameSlotId) {
bool foundFresh = false;
+ matchedGameSlotId = -1;
+ freshGameSlotId = -1;
+
for (uint16 slotNr = 0; slotNr < _savedGameArray.size(); slotNr++) {
SystemUISavedGameEntry *savedGameEntry = &_savedGameArray[slotNr];
@@ -653,7 +701,7 @@ void SystemUI::figureOutAutomaticSavedGameSlot(const char *automaticSaveDescript
// no new slot found yet
if (!savedGameEntry->exists) {
// and current slot doesn't exist
- if (slotNr) {
+ if (savedGameEntry->slotId) {
// and slot is not the auto-save slot -> remember this slot
freshGameSlotId = savedGameEntry->slotId;
foundFresh = true;
@@ -746,21 +794,23 @@ bool SystemUI::askForVerification(const char *verifyText, const char *button1Tex
// Buttons enabled, calculate button coordinates
int16 msgBoxX = 0, msgBoxY = 0, msgBoxLowerY = 0;
int16 msgBoxWidth = 0, msgBoxHeight = 0;
+ int16 fontHeight = _gfx->getDisplayFontHeight();
+ int16 fontWidth = _gfx->getDisplayFontWidth();
_text->getMessageBoxInnerDisplayDimensions(msgBoxX, msgBoxY, msgBoxWidth, msgBoxHeight);
- // Adjust Y coordinate to lower edge
+ // Calculate lower Y
msgBoxLowerY = msgBoxY + (msgBoxHeight - 1);
buttonEntry.active = false;
if (button1Text) {
buttonEntry.text = button1Text;
- buttonEntry.textWidth = strlen(button1Text) * FONT_DISPLAY_WIDTH;
+ buttonEntry.textWidth = strlen(button1Text) * _gfx->getDisplayFontWidth();
buttonEntry.isDefault = true;
_buttonArray.push_back(buttonEntry);
}
if (button2Text) {
buttonEntry.text = button2Text;
- buttonEntry.textWidth = strlen(button2Text) * FONT_DISPLAY_WIDTH;
+ buttonEntry.textWidth = strlen(button2Text) * _gfx->getDisplayFontWidth();
buttonEntry.isDefault = false;
_buttonArray.push_back(buttonEntry);
}
@@ -768,37 +818,30 @@ bool SystemUI::askForVerification(const char *verifyText, const char *button1Tex
// Render-Mode specific calculations
switch (_vm->_renderMode) {
case Common::kRenderApple2GS:
- _buttonArray[0].rect = Common::Rect(14 + _buttonArray[0].textWidth, FONT_DISPLAY_HEIGHT + 6);
- _buttonArray[0].rect.moveTo(msgBoxX + 2, msgBoxLowerY - (8 + FONT_DISPLAY_HEIGHT + 2));
-
+ _buttonArray[0].rect = createRect(msgBoxX, +2, msgBoxLowerY - fontHeight, -(8 + 2), _buttonArray[0].textWidth, +14, fontHeight, +6);
+
if (_buttonArray.size() > 1) {
- int16 adjustedX = msgBoxX + msgBoxWidth - 10;
- _buttonArray[1].rect = Common::Rect(14 + _buttonArray[1].textWidth, FONT_DISPLAY_HEIGHT + 6);
- adjustedX -= _buttonArray[1].rect.width();
- _buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - (8 + FONT_DISPLAY_HEIGHT + 2));
+ int16 adjustedX = msgBoxX + msgBoxWidth - _buttonArray[1].textWidth; // - 10;
+ _buttonArray[1].rect = createRect(adjustedX, -(14 + 10), _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, +14, fontHeight, +6);
}
break;
- case Common::kRenderAmiga:
- _buttonArray[0].rect = Common::Rect(4 + _buttonArray[0].textWidth + 4, 2 + FONT_DISPLAY_HEIGHT + 2);
- _buttonArray[0].rect.moveTo(msgBoxX, msgBoxLowerY - _buttonArray[0].rect.height());
+ case Common::kRenderAmiga: {
+ _buttonArray[0].rect = createRect(msgBoxX, 0, msgBoxLowerY - fontHeight, -(2 + 2), _buttonArray[0].textWidth, +(4 + 4), fontHeight, +(2 + 2));
if (_buttonArray.size() > 1) {
- int16 adjustedX = msgBoxX + msgBoxWidth;
- _buttonArray[1].rect = Common::Rect(4 + _buttonArray[1].textWidth + 4, 2 + FONT_DISPLAY_HEIGHT + 2);
- adjustedX -= _buttonArray[1].rect.width();
- _buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - _buttonArray[1].rect.height());
+ int16 adjustedX = msgBoxX + msgBoxWidth - _buttonArray[1].textWidth;
+ _buttonArray[1].rect = createRect(adjustedX, -(4 + 4), _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, +(4 + 4), fontHeight, +(2 + 2));
}
break;
+ }
case Common::kRenderAtariST:
- _buttonArray[0].rect = Common::Rect(_buttonArray[0].textWidth, FONT_DISPLAY_HEIGHT);
- _buttonArray[0].rect.moveTo(msgBoxX + (5 * FONT_DISPLAY_WIDTH), msgBoxLowerY - FONT_DISPLAY_HEIGHT);
+ _buttonArray[0].rect = createRect(msgBoxX + (5 * fontWidth), 0, msgBoxLowerY - fontHeight, 0, _buttonArray[0].textWidth, 0, fontHeight, 0);
+
if (_buttonArray.size() > 1) {
- int16 adjustedX = msgBoxX + msgBoxWidth - (5 * FONT_DISPLAY_WIDTH);
- _buttonArray[1].rect = Common::Rect(_buttonArray[1].textWidth, FONT_DISPLAY_HEIGHT);
- adjustedX -= _buttonArray[1].rect.width();
- _buttonArray[1].rect.moveTo(adjustedX, msgBoxLowerY - _buttonArray[1].rect.height());
+ int16 adjustedX = msgBoxX + msgBoxWidth - (5 * fontWidth + _buttonArray[1].textWidth);
+ _buttonArray[1].rect = createRect(adjustedX, 0, _buttonArray[0].rect.top, 0, _buttonArray[1].textWidth, 0, fontHeight, 0);
}
break;
@@ -946,6 +989,25 @@ void SystemUI::askForVerificationKeyPress(uint16 newKey) {
}
}
+Common::Rect SystemUI::createRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight) {
+ switch (_gfx->getUpscaledHires()) {
+ case DISPLAY_UPSCALED_DISABLED:
+ break;
+ case DISPLAY_UPSCALED_640x400:
+ adjX *= 2; adjY *= 2;
+ adjWidth *= 2; adjHeight *= 2;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ x += adjX; y += adjY;
+ width += adjWidth; height += adjHeight;
+ Common::Rect newRect(width, height);
+ newRect.moveTo(x, y);
+ return newRect;
+}
+
#define SYSTEMUI_BUTTONEDGE_APPLEIIGS_WIDTH 8
#define SYSTEMUI_BUTTONEDGE_APPLEIIGS_HEIGHT 5
@@ -993,20 +1055,20 @@ void SystemUI::drawButtonAppleIIgs(SystemUIButtonEntry *button) {
}
// draw base box for it
- _gfx->drawDisplayRect(button->rect.left, button->rect.bottom - 1, button->rect.width(), button->rect.height(), backgroundColor, false);
+ _gfx->drawDisplayRect(button->rect.left, button->rect.top, button->rect.width(), button->rect.height(), backgroundColor, false);
// draw inner lines
- _gfx->drawDisplayRect(button->rect.left + 1, button->rect.top - 1, button->rect.width() - 2, 1, 0, false); // upper horizontal
- _gfx->drawDisplayRect(button->rect.left - 2, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // left vertical
- _gfx->drawDisplayRect(button->rect.right, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // right vertical
- _gfx->drawDisplayRect(button->rect.left + 1, button->rect.bottom, button->rect.width() - 2, 1, 0, false); // lower horizontal
+ _gfx->drawDisplayRect(button->rect.left, +1, button->rect.top, -1, button->rect.width(), -2, 0, 1, 0, false); // lower horizontal
+ _gfx->drawDisplayRect(button->rect.left, -2, button->rect.top, +1, 0, 2, button->rect.height(), -2, 0, false); // left vertical
+ _gfx->drawDisplayRect(button->rect.right, 0, button->rect.top, +1, 0, 2, button->rect.height(), -2, 0, false); // right vertical
+ _gfx->drawDisplayRect(button->rect.left, +1, button->rect.bottom, 0, button->rect.width(), -2, 0, 1, 0, false); // upper horizontal
if (button->isDefault) {
// draw outer lines
- _gfx->drawDisplayRect(button->rect.left, button->rect.top - 3, button->rect.width(), 1, 0, false); // upper horizontal
- _gfx->drawDisplayRect(button->rect.left - 5, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // left vertical
- _gfx->drawDisplayRect(button->rect.right + 3, button->rect.bottom - 2, 2, button->rect.height() - 2, 0, false); // right vertical
- _gfx->drawDisplayRect(button->rect.left, button->rect.bottom + 2, button->rect.width(), 1, 0, false); // lower horizontal
+ _gfx->drawDisplayRect(button->rect.left, 0, button->rect.top, -3, button->rect.width(), 0, 0, 1, 0, false); // upper horizontal
+ _gfx->drawDisplayRect(button->rect.left, -5, button->rect.top, +2, 0, 2, button->rect.height(), -2, 0, false); // left vertical
+ _gfx->drawDisplayRect(button->rect.right, +3, button->rect.top, +2, 0, 2, button->rect.height(), -2, 0, false); // right vertical
+ _gfx->drawDisplayRect(button->rect.left, 0, button->rect.bottom, +2, button->rect.width(), 0, 0, 1, 0, false); // lower horizontal
if (button->active)
edgeBitmap = buttonEdgeAppleIIgsDefaultActive;
@@ -1021,18 +1083,18 @@ void SystemUI::drawButtonAppleIIgs(SystemUIButtonEntry *button) {
}
// draw edge graphics
- drawButtonAppleIIgsEdgePixels(button->rect.left - 5, button->rect.top - 3, edgeBitmap, false, false);
- drawButtonAppleIIgsEdgePixels(button->rect.right + 4, button->rect.top - 3, edgeBitmap, true, false);
- drawButtonAppleIIgsEdgePixels(button->rect.left - 5, button->rect.bottom + 2, edgeBitmap, false, true);
- drawButtonAppleIIgsEdgePixels(button->rect.right + 4, button->rect.bottom + 2, edgeBitmap, true, true);
+ drawButtonAppleIIgsEdgePixels(button->rect.left, -5, button->rect.top, -3, edgeBitmap, false, false);
+ drawButtonAppleIIgsEdgePixels(button->rect.right, +4, button->rect.top, -3, edgeBitmap, true, false);
+ drawButtonAppleIIgsEdgePixels(button->rect.left, -5, button->rect.bottom, +2, edgeBitmap, false, true);
+ drawButtonAppleIIgsEdgePixels(button->rect.right, +4, button->rect.bottom, +2, edgeBitmap, true, true);
// Button text
- _gfx->drawStringOnDisplay(button->rect.left + 7, button->rect.top + 3, button->text, foregroundColor, backgroundColor);
+ _gfx->drawStringOnDisplay(button->rect.left, +7, button->rect.top, +3, button->text, foregroundColor, backgroundColor);
- _gfx->copyDisplayRectToScreen(button->rect.left - 5, button->rect.top - 3, button->rect.width() + 10, button->rect.height() + 6);
+ _gfx->copyDisplayRectToScreen(button->rect.left, -5, button->rect.top, -3, button->rect.width(), +10, button->rect.height(), +6);
}
-void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap, bool mirrored, bool upsideDown) {
+void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 adjX, int16 y, int16 adjY, byte *edgeBitmap, bool mirrored, bool upsideDown) {
int8 directionY = upsideDown ? -1 : +1;
int8 directionX = mirrored ? -1 : +1;
int8 curY = 0;
@@ -1050,9 +1112,9 @@ void SystemUI::drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap,
while (widthLeft) {
if (curBitmapByte & curBitmapBit) {
- _gfx->putPixelOnDisplay(x + curX, y + curY, 0);
+ _gfx->putPixelOnDisplay(x, adjX + curX, y, adjY + curY, 0);
} else {
- _gfx->putPixelOnDisplay(x + curX, y + curY, 15);
+ _gfx->putPixelOnDisplay(x, adjX + curX, y, adjY + curY, 15);
}
curBitmapBit = curBitmapBit >> 1;
@@ -1087,12 +1149,11 @@ void SystemUI::drawButtonAmiga(SystemUIButtonEntry *button) {
}
// draw base box for it
- _gfx->drawDisplayRect(button->rect.left, button->rect.bottom - 1, button->rect.width(), button->rect.height(), backgroundColor, false);
+ _gfx->drawDisplayRect(button->rect.left, button->rect.top, button->rect.width(), button->rect.height(), backgroundColor, false);
// Button text
- _gfx->drawStringOnDisplay(button->rect.left + 4, button->rect.top + 2, button->text, foregroundColor, backgroundColor);
+ _gfx->drawStringOnDisplay(button->rect.left, +4, button->rect.top, +2, button->text, foregroundColor, backgroundColor);
- // draw base box for it
_gfx->copyDisplayRectToScreen(button->rect.left, button->rect.top, button->rect.width(), button->rect.height());
}
diff --git a/engines/agi/systemui.h b/engines/agi/systemui.h
index ceb78935eb..283de8794c 100644
--- a/engines/agi/systemui.h
+++ b/engines/agi/systemui.h
@@ -77,6 +77,8 @@ public:
const char *getInventoryTextSelectItems();
const char *getInventoryTextReturnToGame();
+ bool askForCommand(Common::String &commandText);
+
int16 figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription);
int16 figureOutAutomaticRestoreGameSlot(const char *automaticSaveDescription);
@@ -107,9 +109,12 @@ private:
private:
SystemUIButtonArray _buttonArray;
+ Common::Rect createRect(int16 x, int16 adjX, int16 y, int16 adjY, int16 width, int16 adjWidth, int16 height, int16 adjHeight);
+ //void moveRect(int16 x, int16 adjX, int16 y, int16 adjY);
+
void drawButton(SystemUIButtonEntry *button);
void drawButtonAppleIIgs(SystemUIButtonEntry *buttonEntry);
- void drawButtonAppleIIgsEdgePixels(int16 x, int16 y, byte *edgeBitmap, bool mirrored, bool upsideDown);
+ void drawButtonAppleIIgsEdgePixels(int16 x, int16 adjX, int16 y, int16 adjY, byte *edgeBitmap, bool mirrored, bool upsideDown);
void drawButtonAmiga(SystemUIButtonEntry *buttonEntry);
void drawButtonAtariST(SystemUIButtonEntry *buttonEntry);
@@ -127,6 +132,8 @@ private:
const char *_textStatusSoundOn;
const char *_textStatusSoundOff;
+ const char *_textEnterCommand;
+
const char *_textPause;
const char *_textPauseButton;
const char *_textRestart;
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 965de69335..0cacce2421 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/config-manager.h"
#include "agi/agi.h"
#include "agi/sprite.h" // for commit_both()
#include "agi/graphics.h"
@@ -66,6 +67,7 @@ TextMgr::TextMgr(AgiEngine *vm, Words *words, GfxMgr *gfx) {
_inputStringRow = 0;
_inputStringColumn = 0;
+ _inputStringEntered = false;
_inputStringMaxLen = 0;
_inputStringCursorPos = 0;
_inputString[0] = 0;
@@ -73,6 +75,12 @@ TextMgr::TextMgr(AgiEngine *vm, Words *words, GfxMgr *gfx) {
configureScreen(2);
_messageBoxCancelled = false;
+
+ _optionCommandPromptWindow = false;
+
+ if (ConfMan.getBool("commandpromptwindow")) {
+ _optionCommandPromptWindow = true;
+ }
}
TextMgr::~TextMgr() {
@@ -87,7 +95,7 @@ void TextMgr::configureScreen(uint16 row_Min) {
_window_Row_Max = row_Min + 21;
// forward data to GfxMgr as well
- _gfx->setRenderStartOffset(row_Min * FONT_DISPLAY_HEIGHT);
+ _gfx->setRenderStartOffset(row_Min * FONT_VISUAL_HEIGHT);
}
uint16 TextMgr::getWindowRowMin() {
return _window_Row_Min;
@@ -169,7 +177,7 @@ void TextMgr::charAttrib_Set(byte foreground, byte background) {
if (background) {
_textAttrib.combinedForeground = 3;
_textAttrib.combinedBackground = 8; // enable invert of colors
- } else if (foreground > 14) {
+ } else {
if (foreground > 14) {
_textAttrib.combinedForeground = 3;
} else {
@@ -178,6 +186,16 @@ void TextMgr::charAttrib_Set(byte foreground, byte background) {
_textAttrib.combinedBackground = 0;
}
break;
+ case Common::kRenderHercA:
+ case Common::kRenderHercG:
+ if (background) {
+ _textAttrib.combinedForeground = 0;
+ _textAttrib.combinedBackground = 1;
+ } else {
+ _textAttrib.combinedForeground = 1;
+ _textAttrib.combinedBackground = 0;
+ }
+ break;
default:
// EGA-handling:
if (background) {
@@ -465,7 +483,8 @@ void TextMgr::drawMessageBox(const char *textPtr, int16 forcedHeight, int16 want
_messageState.backgroundSize_Width = (_messageState.textSize_Width * FONT_VISUAL_WIDTH) + 10;
_messageState.backgroundSize_Height = (_messageState.textSize_Height * FONT_VISUAL_HEIGHT) + 10;
_messageState.backgroundPos_x = (_messageState.textPos.column * FONT_VISUAL_WIDTH) - 5;
- _messageState.backgroundPos_y = (_messageState.textPos_Edge.row - _window_Row_Min + 1) * FONT_VISUAL_HEIGHT + 4;
+ _messageState.backgroundPos_y = (startingRow * FONT_VISUAL_HEIGHT) - 5;
+ // original AGI used lowerY here, calculated using (_messageState.textPos_Edge.row - _window_Row_Min + 1) * FONT_VISUAL_HEIGHT + 4;
// Hardcoded colors: white background and red lines
_gfx->drawBox(_messageState.backgroundPos_x, _messageState.backgroundPos_y, _messageState.backgroundSize_Width, _messageState.backgroundSize_Height, 15, 4);
@@ -486,10 +505,11 @@ void TextMgr::getMessageBoxInnerDisplayDimensions(int16 &x, int16 &y, int16 &wid
if (!_messageState.window_Active)
return;
- y = _messageState.textPos.row * FONT_DISPLAY_HEIGHT;
- x = _messageState.textPos.column * FONT_DISPLAY_WIDTH;
- width = _messageState.textSize_Width * FONT_DISPLAY_WIDTH;
- height = _messageState.textSize_Height * FONT_DISPLAY_HEIGHT;
+ y = _messageState.textPos.row;
+ x = _messageState.textPos.column;
+ width = _messageState.textSize_Width;
+ height = _messageState.textSize_Height;
+ _gfx->translateFontRectToDisplayScreen(x, y, width, height);
}
bool TextMgr::isMouseWithinMessageBox() {
@@ -498,10 +518,10 @@ bool TextMgr::isMouseWithinMessageBox() {
int16 mouseX = _vm->_mouse.pos.x;
if (_messageState.window_Active) {
- _vm->adjustPosToGameScreen(mouseX, mouseY);
+ _gfx->translateDisplayPosToGameScreen(mouseX, mouseY);
- if ((mouseX >= _messageState.backgroundPos_x) && (mouseX <= (_messageState.backgroundPos_x + _messageState.backgroundSize_Width))) {
- if ((mouseY >= _messageState.backgroundPos_y - _messageState.backgroundSize_Height) && (mouseY <= (_messageState.backgroundPos_y))) {
+ if ((mouseX >= _messageState.backgroundPos_x) && (mouseX < (_messageState.backgroundPos_x + _messageState.backgroundSize_Width))) {
+ if ((mouseY >= _messageState.backgroundPos_y) && (mouseY < (_messageState.backgroundPos_y + _messageState.backgroundSize_Height))) {
return true;
}
}
@@ -580,12 +600,12 @@ void TextMgr::clearBlock(int16 row_Upper, int16 column_Upper, int16 row_Lower, i
charPos_Clip(row_Upper, column_Upper);
charPos_Clip(row_Lower, column_Lower);
- int16 x = column_Upper * FONT_DISPLAY_WIDTH;
- int16 y = row_Upper * FONT_DISPLAY_HEIGHT;
- int16 width = (column_Lower + 1 - column_Upper) * FONT_DISPLAY_WIDTH;
- int16 height = (row_Lower + 1 - row_Upper) * FONT_DISPLAY_HEIGHT;
+ int16 x = column_Upper;
+ int16 y = row_Upper;
+ int16 width = (column_Lower + 1 - column_Upper);
+ int16 height = (row_Lower + 1 - row_Upper);
+ _gfx->translateFontRectToDisplayScreen(x, y, width, height);
- y = y + height - 1; // drawDisplayRect wants lower Y-coordinate
_gfx->drawDisplayRect(x, y, width, height, color);
}
@@ -658,6 +678,30 @@ void TextMgr::promptKeyPress(uint16 newKey) {
int16 maxChars = 0;
int16 scriptsInputLen = _vm->getVar(VM_VAR_MAX_INPUT_CHARACTERS);
+ bool acceptableInput = false;
+
+ // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.)
+ // In text-mode this sort of worked at least with the DOS interpreter
+ // but as soon as invalid characters were used in graphics mode they weren't properly shown
+ switch (_vm->getLanguage()) {
+ case Common::RU_RUS:
+ if (newKey >= 0x20)
+ acceptableInput = true;
+ break;
+ default:
+ if ((newKey >= 0x20) && (newKey <= 0x7f))
+ acceptableInput = true;
+ break;
+ }
+
+ if (_optionCommandPromptWindow) {
+ // Forward to command prompt window, using last command
+ if (acceptableInput) {
+ promptCommandWindow(false, newKey);
+ }
+ return;
+ }
+
if (_messageState.dialogue_Open) {
maxChars = TEXT_STRING_MAX_SIZE - 4;
} else {
@@ -702,22 +746,6 @@ void TextMgr::promptKeyPress(uint16 newKey) {
}
default:
if (maxChars > _promptCursorPos) {
- bool acceptableInput = false;
-
- // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.)
- // In text-mode this sort of worked at least with the DOS interpreter
- // but as soon as invalid characters were used in graphics mode they weren't properly shown
- switch (_vm->getLanguage()) {
- case Common::RU_RUS:
- if (newKey >= 0x20)
- acceptableInput = true;
- break;
- default:
- if ((newKey >= 0x20) && (newKey <= 0x7f))
- acceptableInput = true;
- break;
- }
-
if (acceptableInput) {
_prompt[_promptCursorPos] = newKey;
_promptCursorPos++;
@@ -734,6 +762,11 @@ void TextMgr::promptKeyPress(uint16 newKey) {
}
void TextMgr::promptCancelLine() {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
+
while (_promptCursorPos) {
promptKeyPress(0x08); // Backspace until prompt is empty
}
@@ -742,6 +775,12 @@ void TextMgr::promptCancelLine() {
void TextMgr::promptEchoLine() {
int16 previousLen = strlen((char *)_promptPrevious);
+ if (_optionCommandPromptWindow) {
+ // Forward to command prompt window, using last command
+ promptCommandWindow(true, 0);
+ return;
+ }
+
if (_promptCursorPos < previousLen) {
inputEditOn();
@@ -758,6 +797,11 @@ void TextMgr::promptRedraw() {
char *textPtr = nullptr;
if (_promptEnabled) {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
+
inputEditOn();
clearLine(_promptRow, _textAttrib.background);
charPos_Set(_promptRow, 0);
@@ -775,6 +819,10 @@ void TextMgr::promptRedraw() {
// for AGI1
void TextMgr::promptClear() {
+ if (_optionCommandPromptWindow) {
+ // Abort, in case command prompt window is active
+ return;
+ }
clearLine(_promptRow, _textAttrib.background);
}
@@ -784,6 +832,35 @@ void TextMgr::promptRememberForAutoComplete(bool entered) {
#endif
}
+void TextMgr::promptCommandWindow(bool recallLastCommand, uint16 newKey) {
+ Common::String commandText;
+
+ if (recallLastCommand) {
+ commandText += Common::String((char *)_promptPrevious);
+ }
+ if (newKey) {
+ if (newKey != ' ') {
+ // Only add char, when it's not a space.
+ // Original AGI did not filter space, but it makes no sense to start with a space.
+ // Space would get filtered anyway during dictionary parsing.
+ commandText += newKey;
+ }
+ }
+
+ if (_systemUI->askForCommand(commandText)) {
+ if (commandText.size()) {
+ // Something actually was entered?
+ strncpy((char *)&_prompt, commandText.c_str(), sizeof(_prompt));
+ promptRememberForAutoComplete(true);
+ memcpy(&_promptPrevious, &_prompt, sizeof(_prompt));
+ // parse text
+ _vm->_words->parseUsingDictionary((char *)&_prompt);
+
+ _prompt[0] = 0;
+ }
+ }
+}
+
bool TextMgr::stringWasEntered() {
return _inputStringEntered;
}
@@ -941,8 +1018,18 @@ char *TextMgr::stringWordWrap(const char *originalText, int16 maxWidth, int16 *c
//memset(resultWrappedBuffer, 0, sizeof(resultWrappedBuffer)); for debugging
+ // Good testcases:
+ // King's Quest 1 intro: the scrolling text is filled up with spaces, so that old lines are erased
+ // Apple IIgs restart system UI: spaces used to make the window larger
+ // Gold Rush Stagecoach path room 60: " Lake Michigan!", with max length 9 -> should get split into " Lake" / "Michigan!"
+
while (originalText[curReadPos]) {
// Try to find out length of next word
+
+ // If first character is a space, skip it, so that we process at least this space
+ if (originalText[curReadPos] == ' ')
+ curReadPos++;
+
while (originalText[curReadPos]) {
if (originalText[curReadPos] == ' ')
break;
@@ -957,6 +1044,15 @@ char *TextMgr::stringWordWrap(const char *originalText, int16 maxWidth, int16 *c
if (wordLen >= lineWidthLeft) {
// Not enough space left
+
+ // If first character right after the new line is a space, skip over it
+ if (wordLen) {
+ if (originalText[wordStartPos] == ' ') {
+ wordStartPos++;
+ wordLen--;
+ }
+ }
+
if (wordLen > maxWidth) {
// Word way too long, split it in half
curReadPos = curReadPos - (wordLen - maxWidth);
@@ -973,14 +1069,6 @@ char *TextMgr::stringWordWrap(const char *originalText, int16 maxWidth, int16 *c
// Reached absolute maximum? -> exit now
if (boxHeight >= HEIGHT_MAX)
break;
-
- // If first character right after the new line is a space, skip over it
- if (wordLen) {
- if (originalText[wordStartPos] == ' ') {
- wordStartPos++;
- wordLen--;
- }
- }
}
// Copy current word over
@@ -1005,10 +1093,6 @@ char *TextMgr::stringWordWrap(const char *originalText, int16 maxWidth, int16 *c
}
wordStartPos = curReadPos;
-
- // Last word ended with a space, skip this space for reading the next word
- if (wordEndChar == ' ')
- curReadPos++;
}
resultWrappedBuffer[curWritePos] = 0;
diff --git a/engines/agi/text.h b/engines/agi/text.h
index 72d012b917..f0aeab7762 100644
--- a/engines/agi/text.h
+++ b/engines/agi/text.h
@@ -55,7 +55,7 @@ struct MessageState_Struct {
uint16 printed_Height;
int16 backgroundPos_x;
- int16 backgroundPos_y;
+ int16 backgroundPos_y; // original AGI used lowerY here, we use upperY so that upscaling is easier
int16 backgroundSize_Width;
int16 backgroundSize_Height;
};
@@ -163,6 +163,8 @@ public:
bool _inputEditEnabled;
byte _inputCursorChar;
+ bool _optionCommandPromptWindow;
+
bool _promptEnabled;
int16 _promptRow;
int16 _promptCursorPos;
@@ -189,6 +191,8 @@ public:
void promptClear(); // for AGI1
void promptRememberForAutoComplete(bool entered = false); // for auto-completion
+ void promptCommandWindow(bool recallLastCommand, uint16 newKey);
+
int16 _inputStringRow;
int16 _inputStringColumn;
bool _inputStringEntered;
diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp
index ac3e60ee6d..a13e40e60d 100644
--- a/engines/agi/view.cpp
+++ b/engines/agi/view.cpp
@@ -111,7 +111,6 @@ int AgiEngine::decodeView(byte *resourceData, uint16 resourceSize, int16 viewNr)
byte *celCompressedData = nullptr;
uint16 celCompressedSize = 0;
-// byte *rawBitmap = nullptr;
debugC(5, kDebugLevelResources, "decode_view(%d)", viewNr);
@@ -431,14 +430,28 @@ void AgiEngine::unloadView(int16 viewNr) {
* @param viewNr number of AGI view resource
*/
void AgiEngine::setView(ScreenObjEntry *screenObj, int16 viewNr) {
- screenObj->viewData = &_game.views[viewNr];
+ if (!(_game.dirView[viewNr].flags & RES_LOADED)) {
+ // View resource currently not loaded, this is probably a game bug
+ // Load the resource now to fix the issue, and give out a warning
+ // This happens in at least Larry 1 for Apple IIgs right after getting beaten up by taxi driver
+ // Original interpreter bombs out in this situation saying "view not loaded, Press ESC to quit"
+ warning("setView() called on screen object %d to use view %d, but view not loaded", screenObj->objectNr, viewNr);
+ warning("probably game script bug, trying to load view into memory");
+ if (agiLoadResource(RESOURCETYPE_VIEW, viewNr) != errOK) {
+ // loading failed, we better error() out now
+ error("setView() called to set view %d for screen object %d, which is not loaded atm and loading failed", viewNr, screenObj->objectNr);
+ return;
+ };
+ }
+
+ screenObj->viewResource = &_game.views[viewNr];
screenObj->currentViewNr = viewNr;
- screenObj->loopCount = screenObj->viewData->loopCount;
+ screenObj->loopCount = screenObj->viewResource->loopCount;
screenObj->viewReplaced = true;
if (getVersion() < 0x2000) {
- screenObj->stepSize = screenObj->viewData->headerStepSize;
- screenObj->cycleTime = screenObj->viewData->headerCycleTime;
+ screenObj->stepSize = screenObj->viewResource->headerStepSize;
+ screenObj->cycleTime = screenObj->viewResource->headerCycleTime;
screenObj->cycleTimeCount = 0;
}
if (screenObj->currentLoopNr >= screenObj->loopCount) {
@@ -454,7 +467,11 @@ void AgiEngine::setView(ScreenObjEntry *screenObj, int16 viewNr) {
* @param loopNr number of loop
*/
void AgiEngine::setLoop(ScreenObjEntry *screenObj, int16 loopNr) {
- assert(screenObj->viewData != NULL);
+ if (!(_game.dirView[screenObj->currentViewNr].flags & RES_LOADED)) {
+ error("setLoop() called on screen object %d, which has no loaded view resource assigned to it", screenObj->objectNr);
+ return;
+ }
+ assert(screenObj->viewResource);
if (screenObj->loopCount == 0) {
warning("setLoop() called on screen object %d, which has no loops (view %d)", screenObj->objectNr, screenObj->currentViewNr);
@@ -465,7 +482,11 @@ void AgiEngine::setLoop(ScreenObjEntry *screenObj, int16 loopNr) {
// requested loop not existant
// instead of error()ing out, we instead clip it
// At least required for possibly Manhunter 1 according to previous comment when leaving the arcade machine
- // TODO: check MH1
+ // TODO: Check MH1
+ // TODO: This causes an issue in KQ1, when bowing to the king in room 53
+ // Ego will face away from the king, because the scripts set the loop first and then the view
+ // Loop is corrected by us, because at that time it's invalid. Was already present in 1.7.0
+ // We should probably script-patch it out.
int16 requestedLoopNr = loopNr;
loopNr = screenObj->loopCount - 1;
@@ -493,7 +514,16 @@ void AgiEngine::setLoop(ScreenObjEntry *screenObj, int16 loopNr) {
* @param celNr number of cel
*/
void AgiEngine::setCel(ScreenObjEntry *screenObj, int16 celNr) {
- assert(screenObj->viewData != NULL);
+ if (!(_game.dirView[screenObj->currentViewNr].flags & RES_LOADED)) {
+ error("setCel() called on screen object %d, which has no loaded view resource assigned to it", screenObj->objectNr);
+ return;
+ }
+ assert(screenObj->viewResource);
+
+ if (screenObj->loopCount == 0) {
+ warning("setLoop() called on screen object %d, which has no loops (view %d)", screenObj->objectNr, screenObj->currentViewNr);
+ return;
+ }
AgiViewLoop *curViewLoop = &_game.views[screenObj->currentViewNr].loop[screenObj->currentLoopNr];
diff --git a/engines/agi/view.h b/engines/agi/view.h
index 04021260a3..e59916da78 100644
--- a/engines/agi/view.h
+++ b/engines/agi/view.h
@@ -47,10 +47,6 @@ struct AgiView {
byte *description;
int16 loopCount;
AgiViewLoop *loop;
-
- //struct ViewLoop *loop;
- //bool agi256_2;
- //byte *resourceData;
};
enum MotionType {
@@ -98,7 +94,7 @@ struct ScreenObjEntry {
int16 yPos;
uint8 currentViewNr;
bool viewReplaced;
- struct AgiView *viewData;
+ struct AgiView *viewResource;
uint8 currentLoopNr;
uint8 loopCount;
struct AgiViewLoop *loopData;
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 32fa4cbff4..7072f003c2 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -293,7 +293,7 @@ int16 Words::findWordInDictionary(const Common::String &userInputLowcased, uint1
return wordId;
}
-void Words::parseUsingDictionary(char *rawUserInput) {
+void Words::parseUsingDictionary(const char *rawUserInput) {
Common::String userInput;
Common::String userInputLowcased;
const char *userInputPtr = nullptr;
diff --git a/engines/agi/words.h b/engines/agi/words.h
index c7bf4829c3..96dafae275 100644
--- a/engines/agi/words.h
+++ b/engines/agi/words.h
@@ -57,7 +57,7 @@ public:
void unloadDictionary();
void clearEgoWords();
- void parseUsingDictionary(char *rawUserInput);
+ void parseUsingDictionary(const char *rawUserInput);
private:
void cleanUpInput(const char *userInput, Common::String &cleanInput);
diff --git a/engines/agos/configure.engine b/engines/agos/configure.engine
index 3ae1fb16f2..cd7fcf9d78 100644
--- a/engines/agos/configure.engine
+++ b/engines/agos/configure.engine
@@ -1,4 +1,4 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine agos "AGOS" yes "agos2" "AGOS 1 games"
-add_engine agos2 "AGOS 2 games" yes
+add_engine agos2 "AGOS 2 games" yes "" "" "highres"
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 94446159b9..2c89522089 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -94,13 +94,13 @@ using namespace AGOS;
class AgosMetaEngine : public AdvancedMetaEngine {
public:
AgosMetaEngine() : AdvancedMetaEngine(AGOS::gameDescriptions, sizeof(AGOS::AGOSGameDescription), agosGames) {
- _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
+ _guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
- virtual GameDescriptor findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+ virtual GameDescriptor findGame(const char *gameId) const {
+ return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
virtual const char *getName() const {
@@ -186,7 +186,6 @@ SaveStateList AgosMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -203,6 +202,8 @@ SaveStateList AgosMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 762f60bd91..13b5bf761c 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -217,7 +217,7 @@ static void convertVolume(int &vol) {
}
static void convertPan(int &pan) {
- // DirectSound was orginally used, which specifies volume
+ // DirectSound was originally used, which specifies volume
// and panning differently than ScummVM does, using a logarithmic scale
// rather than a linear one.
//
diff --git a/engines/avalanche/POTFILES b/engines/avalanche/POTFILES
new file mode 100644
index 0000000000..5b0bb910ed
--- /dev/null
+++ b/engines/avalanche/POTFILES
@@ -0,0 +1 @@
+engines/avalanche/parser.cpp
diff --git a/engines/avalanche/configure.engine b/engines/avalanche/configure.engine
index 28d6a558db..9b913ff053 100644
--- a/engines/avalanche/configure.engine
+++ b/engines/avalanche/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 avalanche "Lord Avalot d'Argent" no
+add_engine avalanche "Lord Avalot d'Argent" no "" "" "highres"
diff --git a/engines/avalanche/detection.cpp b/engines/avalanche/detection.cpp
index 484d148161..e35c5d2cac 100644
--- a/engines/avalanche/detection.cpp
+++ b/engines/avalanche/detection.cpp
@@ -40,7 +40,7 @@ uint32 AvalancheEngine::getFeatures() const {
}
const char *AvalancheEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
static const PlainGameDescriptor avalancheGames[] = {
@@ -110,7 +110,6 @@ SaveStateList AvalancheMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
@@ -152,6 +151,8 @@ SaveStateList AvalancheMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp
index 220186ca5e..7c6d254099 100644
--- a/engines/avalanche/parser.cpp
+++ b/engines/avalanche/parser.cpp
@@ -30,6 +30,7 @@
#include "avalanche/nim.h"
#include "gui/saveload.h"
+#include "common/translation.h"
namespace Avalanche {
@@ -1883,7 +1884,7 @@ void Parser::doThat() {
break;
case kVerbCodeLoad: {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
int16 savegameId = dialog->runModalWithCurrentTarget();
delete dialog;
@@ -1895,7 +1896,7 @@ void Parser::doThat() {
}
break;
case kVerbCodeSave: {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
int16 savegameId = dialog->runModalWithCurrentTarget();
Common::String savegameDescription = dialog->getResultString();
delete dialog;
diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index d40d5e482f..6ae663479d 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -137,6 +137,21 @@ BbvsEngine::~BbvsEngine() {
}
void BbvsEngine::newGame() {
+ memset(_easterEggInput, 0, sizeof(_easterEggInput));
+ _gameTicks = 0;
+ _playVideoNumber = 0;
+ memset(_inventoryItemStatus, 0, sizeof(_inventoryItemStatus));
+ memset(_gameVars, 0, sizeof(_gameVars));
+ memset(_sceneVisited, 0, sizeof(_sceneVisited));
+
+ _mouseX = 160;
+ _mouseY = 120;
+ _mouseButtons = 0;
+
+ _currVerbNum = kVerbLook;
+ _currTalkObjectIndex = -1;
+ _currSceneNum = 0;
+
_currInventoryItem = -1;
_newSceneNum = 32;
}
@@ -162,24 +177,10 @@ Common::Error BbvsEngine::run() {
_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));
-
- _mouseX = 160;
- _mouseY = 120;
- _mouseButtons = 0;
+ newGame();
- _currVerbNum = kVerbLook;
- _currInventoryItem = -1;
- _currTalkObjectIndex = -1;
- _currSceneNum = 0;
+ _bootSaveSlot = -1;
_newSceneNum = 31;
if (ConfMan.hasKey("save_slot"))
diff --git a/engines/bbvs/detection.cpp b/engines/bbvs/detection.cpp
index eb894e9f13..7c0045ee73 100644
--- a/engines/bbvs/detection.cpp
+++ b/engines/bbvs/detection.cpp
@@ -43,7 +43,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("vspr0001.vnm", "7ffe9b9e7ca322db1d48e86f5130578e", 1166628),
Common::EN_ANY,
Common::kPlatformWindows,
- ADGF_NO_FLAGS | ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO0()
},
{
@@ -52,7 +52,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("vspr0001.vnm", "91c76b1048f93208cd7b1a05ebccb408", 1176976),
Common::RU_RUS,
Common::kPlatformWindows,
- GF_GUILANGSWITCH | ADGF_TESTING,
+ GF_GUILANGSWITCH | ADGF_NO_FLAGS,
GUIO0()
},
@@ -69,7 +69,7 @@ static const char * const directoryGlobs[] = {
class BbvsMetaEngine : public AdvancedMetaEngine {
public:
BbvsMetaEngine() : AdvancedMetaEngine(Bbvs::gameDescriptions, sizeof(ADGameDescription), bbvsGames) {
- _singleid = "bbvs";
+ _singleId = "bbvs";
_maxScanDepth = 3;
_directoryGlobs = directoryGlobs;
}
@@ -116,7 +116,6 @@ SaveStateList BbvsMetaEngine::listSaves(const char *target) const {
pattern += ".###";
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- 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
@@ -131,6 +130,8 @@ SaveStateList BbvsMetaEngine::listSaves(const char *target) const {
}
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/bbvs/dialogs.cpp b/engines/bbvs/dialogs.cpp
index ef7f3c9320..c8470f8eef 100644
--- a/engines/bbvs/dialogs.cpp
+++ b/engines/bbvs/dialogs.cpp
@@ -102,7 +102,7 @@ void MainMenu::reflowLayout() {
_w = 2 * buttonWidth + buttonPadding;
_h = 3 * buttonHeight + 3 * buttonPadding;
_x = (screenW - _w) / 2;
- _y = screenH - _h;
+ _y = screenH - _h - 2;
int x = 0, y = 0;
diff --git a/engines/cge/POTFILES b/engines/cge/POTFILES
index 55430683c3..f8aef4932d 100644
--- a/engines/cge/POTFILES
+++ b/engines/cge/POTFILES
@@ -1,2 +1,3 @@
engines/cge/detection.cpp
+engines/cge/events.cpp
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 47c5f56b6e..52168dc934 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -115,7 +115,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class CGEMetaEngine : public AdvancedMetaEngine {
public:
CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(ADGameDescription), CGEGames, optionsList) {
- _singleid = "soltys";
+ _singleId = "soltys";
}
virtual const char *getName() const {
@@ -199,7 +199,6 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
@@ -235,6 +234,8 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/cge/events.cpp b/engines/cge/events.cpp
index 24b3a270cf..c2f8982592 100644
--- a/engines/cge/events.cpp
+++ b/engines/cge/events.cpp
@@ -30,6 +30,7 @@
#include "gui/message.h"
#include "common/config-manager.h"
#include "common/events.h"
+#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "cge/events.h"
#include "cge/events.h"
@@ -70,7 +71,7 @@ bool Keyboard::getKey(Common::Event &event) {
return false;
case Common::KEYCODE_F5:
if (_vm->canSaveGameStateCurrently()) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
int16 savegameId = dialog->runModalWithCurrentTarget();
Common::String savegameDescription = dialog->getResultString();
delete dialog;
@@ -81,7 +82,7 @@ bool Keyboard::getKey(Common::Event &event) {
return false;
case Common::KEYCODE_F7:
if (_vm->canLoadGameStateCurrently()) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
int16 savegameId = dialog->runModalWithCurrentTarget();
delete dialog;
diff --git a/engines/cge2/POTFILES b/engines/cge2/POTFILES
index 1e904763ec..3bff3258fd 100644
--- a/engines/cge2/POTFILES
+++ b/engines/cge2/POTFILES
@@ -1 +1,2 @@
engines/cge2/detection.cpp
+engines/cge2/events.cpp
diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp
index a1867b0dfe..01119bb1fd 100644
--- a/engines/cge2/detection.cpp
+++ b/engines/cge2/detection.cpp
@@ -111,7 +111,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class CGE2MetaEngine : public AdvancedMetaEngine {
public:
CGE2MetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), CGE2Games, optionsList) {
- _singleid = "sfinx";
+ _singleId = "sfinx";
}
virtual const char *getName() const {
@@ -199,7 +199,6 @@ SaveStateList CGE2MetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
@@ -235,6 +234,8 @@ SaveStateList CGE2MetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/cge2/events.cpp b/engines/cge2/events.cpp
index 85743c8011..96cecc8e23 100644
--- a/engines/cge2/events.cpp
+++ b/engines/cge2/events.cpp
@@ -30,6 +30,7 @@
#include "gui/message.h"
#include "common/config-manager.h"
#include "common/events.h"
+#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "cge2/events.h"
#include "cge2/text.h"
@@ -63,7 +64,7 @@ bool Keyboard::getKey(Common::Event &event) {
return false;
case Common::KEYCODE_F5:
if (_vm->canSaveGameStateCurrently()) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
int16 savegameId = dialog->runModalWithCurrentTarget();
Common::String savegameDescription = dialog->getResultString();
delete dialog;
@@ -74,7 +75,7 @@ bool Keyboard::getKey(Common::Event &event) {
return false;
case Common::KEYCODE_F7:
if (_vm->canLoadGameStateCurrently()) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
int16 savegameId = dialog->runModalWithCurrentTarget();
delete dialog;
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
index eb111c3255..54f5c00d93 100644
--- a/engines/cge2/vga13h.cpp
+++ b/engines/cge2/vga13h.cpp
@@ -141,7 +141,7 @@ Sprite::Sprite(CGE2Engine *vm)
memset(_actionCtrl, 0, sizeof(_actionCtrl));
memset(_file, 0, sizeof(_file));
memset(&_flags, 0, sizeof(_flags));
- _flags._frnt = 1;
+ _flags._frnt = true;
}
Sprite::Sprite(CGE2Engine *vm, BitmapPtr shpP, int cnt)
@@ -152,7 +152,7 @@ Sprite::Sprite(CGE2Engine *vm, BitmapPtr shpP, int cnt)
memset(_actionCtrl, 0, sizeof(_actionCtrl));
memset(_file, 0, sizeof(_file));
memset(&_flags, 0, sizeof(_flags));
- _flags._frnt = 1;
+ _flags._frnt = true;
setShapeList(shpP, cnt);
}
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index c6099447d8..6ecf07fe15 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -535,7 +535,7 @@ int loadSpl(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- g_cine->_animDataTable[entry].load(dataPtr + 0x16, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize - 0x16, 1, foundFileIdx, 0, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
return entry + 1;
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index dac7add16b..ec01e8734d 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -80,12 +80,12 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class CineMetaEngine : public AdvancedMetaEngine {
public:
CineMetaEngine() : AdvancedMetaEngine(Cine::gameDescriptions, sizeof(Cine::CINEGameDescription), cineGames, optionsList) {
- _singleid = "cine";
- _guioptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD);
+ _singleId = "cine";
+ _guiOptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD);
}
- virtual GameDescriptor findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+ virtual GameDescriptor findGame(const char *gameId) const {
+ return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
virtual const char *getName() const {
@@ -137,7 +137,6 @@ SaveStateList CineMetaEngine::listSaves(const char *target) const {
Common::String pattern = target;
pattern += ".#";
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end());
Common::StringArray::const_iterator file;
Common::String filename = target;
@@ -169,6 +168,8 @@ SaveStateList CineMetaEngine::listSaves(const char *target) const {
delete in;
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index 1f4f286694..dfd3a1f4bc 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -691,6 +691,11 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor
}
if (strlen(bgName)) {
+ if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD)) {
+ char buffer[20];
+ removeExtention(buffer, bgName);
+ g_sound->setBgMusic(atoi(buffer + 1));
+ }
loadBg(bgName);
}
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 6ad38f4433..86eb709d5a 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -1858,7 +1858,9 @@ int FWScript::o1_playSample() {
if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
return 0;
}
- g_sound->stopMusic();
+ // The DOS CD version of Future Wars uses CD audio for music
+ if (!(g_cine->getGameType() == Cine::GType_FW && (g_cine->getFeatures() & GF_CD)))
+ g_sound->stopMusic();
if (size == 0xFFFF) {
g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0);
} else {
diff --git a/engines/composer/configure.engine b/engines/composer/configure.engine
index 71a79acb5d..17120a3a3d 100644
--- a/engines/composer/configure.engine
+++ b/engines/composer/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 composer "Magic Composer" yes
+add_engine composer "Magic Composer" yes "" "" "highres"
diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp
index 036c1e88d8..a3ab18ae54 100644
--- a/engines/composer/detection.cpp
+++ b/engines/composer/detection.cpp
@@ -38,7 +38,7 @@ int ComposerEngine::getGameType() const {
}
const char *ComposerEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
uint32 ComposerEngine::getFeatures() const {
@@ -81,12 +81,12 @@ static const ComposerGameDescription gameDescriptions[] = {
GType_ComposerV1
},
- // Magic Tales: Baba Yaga and the Magic Geese Mac - from bug #3466402
+ // Magic Tales: Baba Yaga and the Magic Geese Mac - from bug #3466402, #7025
{
{
"babayaga",
"",
- AD_ENTRY1("Baba Yaga", "ae3a4445f42fe10253da7ee4ea0d37"),
+ AD_ENTRY1s("Baba Yaga", "ae3a4445f42fe10253da7ee4ea0d37d6", 44321),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
@@ -386,7 +386,7 @@ static const char *directoryGlobs[] = {
class ComposerMetaEngine : public AdvancedMetaEngine {
public:
ComposerMetaEngine() : AdvancedMetaEngine(Composer::gameDescriptions, sizeof(Composer::ComposerGameDescription), composerGames) {
- _singleid = "composer";
+ _singleId = "composer";
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index 4d0ed2bf91..6f5d236173 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -35,7 +35,7 @@ struct CRUISEGameDescription {
};
const char *CruiseEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
Common::Language CruiseEngine::getLanguage() const {
@@ -196,8 +196,8 @@ static const CRUISEGameDescription gameDescriptions[] = {
class CruiseMetaEngine : public AdvancedMetaEngine {
public:
CruiseMetaEngine() : AdvancedMetaEngine(Cruise::gameDescriptions, sizeof(Cruise::CRUISEGameDescription), cruiseGames) {
- _singleid = "cruise";
- _guioptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
+ _singleId = "cruise";
+ _guiOptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
}
virtual const char *getName() const {
@@ -231,7 +231,6 @@ SaveStateList CruiseMetaEngine::listSaves(const char *target) const {
Common::String pattern("cruise.s##");
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -250,6 +249,8 @@ SaveStateList CruiseMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index a32dae3216..65427bd8cd 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -84,7 +84,7 @@ const ADGameDescription gameDescriptions[] = {
class DraciMetaEngine : public AdvancedMetaEngine {
public:
DraciMetaEngine() : AdvancedMetaEngine(Draci::gameDescriptions, sizeof(ADGameDescription), draciGames) {
- _singleid = "draci";
+ _singleId = "draci";
}
virtual const char *getName() const {
@@ -120,7 +120,6 @@ SaveStateList DraciMetaEngine::listSaves(const char *target) const {
Common::String pattern("draci.s##");
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -143,6 +142,8 @@ SaveStateList DraciMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index fbf58faaa1..ffec393a0a 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -310,8 +310,8 @@ SaveStateDescriptor loadMetaData(Common::ReadStream *s, int slot, bool setPlayTi
class DrasculaMetaEngine : public AdvancedMetaEngine {
public:
DrasculaMetaEngine() : AdvancedMetaEngine(Drascula::gameDescriptions, sizeof(Drascula::DrasculaGameDescription), drasculaGames) {
- _singleid = "drascula";
- _guioptions = GUIO1(GUIO_NOMIDI);
+ _singleId = "drascula";
+ _guiOptions = GUIO1(GUIO_NOMIDI);
}
virtual const char *getName() const {
@@ -355,7 +355,6 @@ SaveStateList DrasculaMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
int slotNum = 0;
@@ -378,6 +377,8 @@ SaveStateList DrasculaMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/dreamweb/detection.cpp b/engines/dreamweb/detection.cpp
index 4fc624c2f3..764171bcb0 100644
--- a/engines/dreamweb/detection.cpp
+++ b/engines/dreamweb/detection.cpp
@@ -70,8 +70,8 @@ public:
AdvancedMetaEngine(DreamWeb::gameDescriptions,
sizeof(DreamWeb::DreamWebGameDescription), dreamWebGames,
gameGuiOptions) {
- _singleid = "dreamweb";
- _guioptions = GUIO1(GUIO_NOMIDI);
+ _singleId = "dreamweb";
+ _guiOptions = GUIO1(GUIO_NOMIDI);
}
virtual const char *getName() const {
@@ -128,7 +128,6 @@ bool DreamWebMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
SaveStateList DreamWebMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray files = saveFileMan->listSavefiles("DREAMWEB.D##");
- Common::sort(files.begin(), files.end());
SaveStateList saveList;
for (uint i = 0; i < files.size(); ++i) {
@@ -146,6 +145,8 @@ SaveStateList DreamWebMetaEngine::listSaves(const char *target) const {
saveList.push_back(sd);
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 475cc77064..d3b9b113cf 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -292,7 +292,7 @@ void splashScreen() {
Common::Event event;
while (time0 + 600 > g_system->getMillis()) {
g_system->updateScreen();
- g_system->getEventManager()->pollEvent(event);
+ (void)g_system->getEventManager()->pollEvent(event);
g_system->delayMillis(10);
}
g_system->hideOverlay();
diff --git a/engines/fullpipe/configure.engine b/engines/fullpipe/configure.engine
index a9042449db..611d0188dc 100644
--- a/engines/fullpipe/configure.engine
+++ b/engines/fullpipe/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 fullpipe "Full Pipe" no "" "" "16bit"
+add_engine fullpipe "Full Pipe" no "" "" "16bit highres"
diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp
index ccd55935e6..6f92f19f24 100644
--- a/engines/fullpipe/detection.cpp
+++ b/engines/fullpipe/detection.cpp
@@ -32,7 +32,7 @@
namespace Fullpipe {
const char *FullpipeEngine::getGameId() const {
- return _gameDescription->gameid;
+ return _gameDescription->gameId;
}
}
@@ -76,7 +76,7 @@ static const ADGameDescription gameDescriptions[] = {
class FullpipeMetaEngine : public AdvancedMetaEngine {
public:
FullpipeMetaEngine() : AdvancedMetaEngine(Fullpipe::gameDescriptions, sizeof(ADGameDescription), fullpipeGames) {
- _singleid = "fullpipe";
+ _singleId = "fullpipe";
}
virtual const char *getName() const {
@@ -111,7 +111,6 @@ SaveStateList FullpipeMetaEngine::listSaves(const char *target) const {
Common::String pattern("fullpipe.s##");
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -130,6 +129,8 @@ SaveStateList FullpipeMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/game.cpp b/engines/game.cpp
index 85ad6fe2e8..7ff51a99cc 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -26,8 +26,8 @@
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) {
const PlainGameDescriptor *g = list;
- while (g->gameid) {
- if (0 == scumm_stricmp(gameid, g->gameid))
+ while (g->gameId) {
+ if (0 == scumm_stricmp(gameid, g->gameId))
return g;
g++;
}
@@ -40,7 +40,7 @@ GameDescriptor::GameDescriptor() {
}
GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions) {
- setVal("gameid", pgd.gameid);
+ setVal("gameid", pgd.gameId);
setVal("description", pgd.description);
if (!guioptions.empty())
diff --git a/engines/game.h b/engines/game.h
index a9bec8f9e0..e01e5c6885 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -36,7 +36,7 @@
* consisting of PlainGameDescriptors.
*/
struct PlainGameDescriptor {
- const char *gameid;
+ const char *gameId;
const char *description;
};
@@ -108,7 +108,7 @@ public:
GameList() {}
GameList(const GameList &list) : Common::Array<GameDescriptor>(list) {}
GameList(const PlainGameDescriptor *g) {
- while (g->gameid) {
+ while (g->gameId) {
push_back(GameDescriptor(*g));
g++;
}
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index 3b26f63c39..b0aa78f416 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -33,7 +33,7 @@ class GobMetaEngine : public AdvancedMetaEngine {
public:
GobMetaEngine();
- virtual GameDescriptor findGame(const char *gameid) const;
+ virtual GameDescriptor findGame(const char *gameId) const;
virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
@@ -55,12 +55,12 @@ private:
GobMetaEngine::GobMetaEngine() :
AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
- _singleid = "gob";
- _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
+ _singleId = "gob";
+ _guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
}
-GameDescriptor GobMetaEngine::findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+GameDescriptor GobMetaEngine::findGame(const char *gameId) const {
+ return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp
index d6e9841e0a..9298f159a4 100644
--- a/engines/gob/script.cpp
+++ b/engines/gob/script.cpp
@@ -215,7 +215,7 @@ char *Script::readString(int32 length) {
}
byte Script::peekByte(int32 offset) {
- byte v;
+ byte v = 0;
peek(&v, 1, offset);
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index 1e024d5a50..2a9a716058 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -283,7 +283,12 @@ void AdLib::initOPL() {
_voiceOn [i] = 0;
}
- _opl->reset();
+ /* NOTE: We used to completely reset the OPL here, via _opl->reset(). However,
+ * with the OPL timer change in 73e8ac2a, reset() must not be called while
+ * the callback is still active. With the Gob AdLib rewrite in 03ef6689,
+ * this reset shouldn't be necessary anymore either, since this function
+ * here cleans everything properly anyway. If suddenly a certain piece of
+ * music in a Gob game sounds weird, we need to re-examine that. */
initOperatorVolumes();
resetFreqs();
diff --git a/engines/groovie/configure.engine b/engines/groovie/configure.engine
index 212a49bec8..f283731a58 100644
--- a/engines/groovie/configure.engine
+++ b/engines/groovie/configure.engine
@@ -1,4 +1,4 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine groovie "Groovie" yes "groovie2" "7th Guest"
+add_engine groovie "Groovie" yes "groovie2" "7th Guest" "highres"
add_engine groovie2 "Groovie 2 games" no "" "" "jpeg 16bit"
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index a249b66858..b12e264a57 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -322,7 +322,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class GroovieMetaEngine : public AdvancedMetaEngine {
public:
GroovieMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(GroovieGameDescription), groovieGames, optionsList) {
- _singleid = "groovie";
+ _singleId = "groovie";
// Use kADFlagUseExtraAsHint in order to distinguish the 11th hour from
// its "Making of" as well as the Clandestiny Trailer; they all share
@@ -333,7 +333,7 @@ public:
// to the detection entries. In the latter case, this TODO should be
// replaced with an according explanation.
_flags = kADFlagUseExtraAsHint;
- _guioptions = GUIO3(GUIO_NOSUBTITLES, GUIO_NOSFX, GUIO_NOASPECT);
+ _guiOptions = GUIO3(GUIO_NOSUBTITLES, GUIO_NOSFX, GUIO_NOASPECT);
// Need MIDI directory to detect 11H Mac Installed
_maxScanDepth = 2;
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index b42cf09245..2021cef6e8 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -69,7 +69,7 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
// Initialize the custom debug levels
DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback");
- DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resouce management");
+ DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resource management");
DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts");
DebugMan.addDebugChannel(kDebugUnknown, "Unknown", "Report values of unknown data in files");
DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Show the hotspots");
diff --git a/engines/hopkins/configure.engine b/engines/hopkins/configure.engine
index c38ecd4cd2..cd9f50a5f9 100644
--- a/engines/hopkins/configure.engine
+++ b/engines/hopkins/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 hopkins "Hopkins FBI" yes "" "" "16bit"
+add_engine hopkins "Hopkins FBI" yes "" "" "16bit highres"
diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp
index 670efb8898..cc1e84f5f8 100644
--- a/engines/hopkins/detection.cpp
+++ b/engines/hopkins/detection.cpp
@@ -153,7 +153,6 @@ SaveStateList HopkinsMetaEngine::listSaves(const char *target) const {
Common::String pattern = Common::String::format("%s.0##", target);
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
Hopkins::hopkinsSavegameHeader header;
@@ -178,6 +177,8 @@ SaveStateList HopkinsMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/hugo/POTFILES b/engines/hugo/POTFILES
new file mode 100644
index 0000000000..ff61e12ca5
--- /dev/null
+++ b/engines/hugo/POTFILES
@@ -0,0 +1 @@
+engines/hugo/file.cpp
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index a005e649d4..4e4746c002 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -41,7 +41,7 @@ uint32 HugoEngine::getFeatures() const {
}
const char *HugoEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
@@ -180,7 +180,6 @@ SaveStateList HugoMetaEngine::listSaves(const char *target) const {
pattern += "-##.SAV";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
char slot[3];
@@ -217,6 +216,8 @@ SaveStateList HugoMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index e2633977a8..7a3538ea63 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -32,6 +32,7 @@
#include "common/savefile.h"
#include "common/textconsole.h"
#include "common/config-manager.h"
+#include "common/translation.h"
#include "graphics/surface.h"
#include "graphics/thumbnail.h"
@@ -294,7 +295,7 @@ bool FileManager::saveGame(const int16 slot, const Common::String &descrip) {
Common::String savegameDescription;
if (slot == -1) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
savegameId = dialog->runModalWithCurrentTarget();
savegameDescription = dialog->getResultString();
delete dialog;
@@ -396,7 +397,7 @@ bool FileManager::restoreGame(const int16 slot) {
int16 savegameId;
if (slot == -1) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
savegameId = dialog->runModalWithCurrentTarget();
delete dialog;
} else {
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index 4a90722a35..6683f973ca 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -542,7 +542,7 @@ bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
debugPrintf("Failure.\n");
}
} else {
- debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n");
+ debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the original game executable.)\n\n");
}
return true;
@@ -562,7 +562,7 @@ bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
return true;
}
- debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n");
+ debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the original game executable.\n A save slot between 0 and 5 must be specified.)\n\n");
return true;
}
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index a4786ef583..989a45b420 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -246,7 +246,6 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -269,6 +268,8 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 2ee0262ef2..773d491423 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -1546,7 +1546,7 @@ const KYRAGameDescription adGameDescs[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO7(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_EOB_HPGRAPHS)
},
EOB_FLAGS
@@ -1562,7 +1562,7 @@ const KYRAGameDescription adGameDescs[] = {
},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO7(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_EOB_HPGRAPHS)
},
EOB_FLAGS
@@ -1576,10 +1576,10 @@ const KYRAGameDescription adGameDescs[] = {
{ "EOBDATA3.PAK", 0, "3ed915ab5b94d60dbfe1b55379889c51", -1 },
{ 0, 0, 0, 0 }
},
- Common::IT_ITA,
- Common::kPlatformDOS,
- ADGF_TESTING,
- GUIO7(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_EOB_HPGRAPHS)
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO7(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_EOB_HPGRAPHS)
},
EOB_FLAGS
},
@@ -1594,7 +1594,7 @@ const KYRAGameDescription adGameDescs[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GAMEOPTION_EOB_HPGRAPHS)
},
EOB2_FLAGS
@@ -1610,7 +1610,7 @@ const KYRAGameDescription adGameDescs[] = {
},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GAMEOPTION_EOB_HPGRAPHS)
},
EOB2_FLAGS
diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp
index cfdf762bba..5ff0b6a109 100644
--- a/engines/kyra/gui_lol.cpp
+++ b/engines/kyra/gui_lol.cpp
@@ -2219,7 +2219,7 @@ int GUI_LoL::runMenu(Menu &menu) {
int fW = (d->w << 3) - wW;
int fC = 0;
- // LoL doesnt't have default higlighted items. No item should be
+ // LoL doesn't have default higlighted items. No item should be
// highlighted when entering a new menu.
// Instead, the respevtive struct entry is used to determine whether
// a menu has scroll buttons or slider bars.
diff --git a/engines/kyra/gui_v1.cpp b/engines/kyra/gui_v1.cpp
index a75c14b071..92891f71b2 100644
--- a/engines/kyra/gui_v1.cpp
+++ b/engines/kyra/gui_v1.cpp
@@ -200,7 +200,7 @@ void GUI_v1::processHighlights(Menu &menu) {
int mouseY = p.y;
if (_vm->game() == GI_LOL && menu.highlightedItem != 255) {
- // LoL doesnt't have default highlighted items.
+ // LoL doesn't have default highlighted items.
// We use a highlightedItem value of 255 for this.
// With LoL no highlighting should take place unless the
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 3c3aff6ea9..6c0d529f96 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -37,7 +37,7 @@ namespace Kyra {
Sound::Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer)
: _vm(vm), _mixer(mixer), _soundChannels(), _musicEnabled(1),
- _sfxEnabled(true) {
+ _sfxEnabled(true) {
}
Sound::~Sound() {
@@ -165,7 +165,7 @@ bool Sound::allVoiceChannelsPlaying() const {
#pragma mark -
MixedSoundDriver::MixedSoundDriver(KyraEngine_v1 *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx)
- : Sound(vm, mixer), _music(music), _sfx(sfx) {
+ : Sound(vm, mixer), _music(music), _sfx(sfx) {
}
MixedSoundDriver::~MixedSoundDriver() {
@@ -289,16 +289,16 @@ void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) {
//}
if (_flags.platform == Common::kPlatformDOS || _flags.platform == Common::kPlatformMacintosh) {
- assert(command*2+1 < _trackMapSize);
- if (_curMusicTheme != _trackMap[command*2]) {
- if (_trackMap[command*2] != -1 && _trackMap[command*2] != -2)
- snd_playTheme(_trackMap[command*2], -1);
+ assert(command * 2 + 1 < _trackMapSize);
+ if (_curMusicTheme != _trackMap[command * 2]) {
+ if (_trackMap[command * 2] != -1 && _trackMap[command * 2] != -2)
+ snd_playTheme(_trackMap[command * 2], -1);
}
if (command != 1) {
if (_lastMusicCommand != command) {
_sound->haltTrack();
- _sound->playTrack(_trackMap[command*2+1]);
+ _sound->playTrack(_trackMap[command * 2 + 1]);
}
} else {
_sound->beginFadeOut();
@@ -307,8 +307,8 @@ void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) {
if (command == -1) {
_sound->haltTrack();
} else {
- assert(command*2+1 < _trackMapSize);
- if (_trackMap[command*2] != -2 && command != _lastMusicCommand) {
+ assert(command * 2 + 1 < _trackMapSize);
+ if (_trackMap[command * 2] != -2 && command != _lastMusicCommand) {
_sound->haltTrack();
_sound->playTrack(command);
}
diff --git a/engines/lab/configure.engine b/engines/lab/configure.engine
index 18091b1b84..3be9545aa6 100644
--- a/engines/lab/configure.engine
+++ b/engines/lab/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 lab "Labyrinth of Time" no
+add_engine lab "Labyrinth of Time" yes
diff --git a/engines/lab/detection.cpp b/engines/lab/detection.cpp
index d01dff2843..1fd3ca8944 100644
--- a/engines/lab/detection.cpp
+++ b/engines/lab/detection.cpp
@@ -48,7 +48,7 @@ static const ADGameDescription labDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO0()
},
{
@@ -61,7 +61,7 @@ static const ADGameDescription labDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- Lab::GF_LOWRES | ADGF_TESTING,
+ Lab::GF_LOWRES | ADGF_NO_FLAGS,
GUIO0()
},
{
@@ -75,7 +75,7 @@ static const ADGameDescription labDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformWindows,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO0()
},
{
@@ -115,7 +115,7 @@ uint32 LabEngine::getFeatures() const {
class LabMetaEngine : public AdvancedMetaEngine {
public:
LabMetaEngine() : AdvancedMetaEngine(labDescriptions, sizeof(ADGameDescription), lab_setting) {
- _singleid = "lab";
+ _singleId = "lab";
_maxScanDepth = 4;
_directoryGlobs = directoryGlobs;
@@ -169,7 +169,6 @@ SaveStateList LabMetaEngine::listSaves(const char *target) const {
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
SaveStateList saveList;
@@ -187,6 +186,8 @@ SaveStateList LabMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -196,26 +197,7 @@ int LabMetaEngine::getMaximumSaveSlot() const {
void LabMetaEngine::removeSaveState(const char *target, int slot) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::String filename = Common::String::format("%s.%03u", target, slot);
-
- saveFileMan->removeSavefile(filename.c_str());
-
- Common::StringArray filenames;
- Common::String pattern = target;
- pattern += ".###";
- filenames = saveFileMan->listSavefiles(pattern.c_str());
- 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 = Common::String::format("%s.%03u", target, ++slot);
- }
- }
+ saveFileMan->removeSavefile(Common::String::format("%s.%03u", target, slot));
}
SaveStateDescriptor LabMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
diff --git a/engines/lab/lab.cpp b/engines/lab/lab.cpp
index 0a4cf4ec50..9b0ebfc4e5 100644
--- a/engines/lab/lab.cpp
+++ b/engines/lab/lab.cpp
@@ -214,12 +214,6 @@ void LabEngine::updateEvents() {
Common::Error LabEngine::loadGameState(int slot) {
bool result = loadGame(slot);
- _curFileName = " ";
- _closeDataPtr = nullptr;
- _mainDisplay = true;
- _followingCrumbs = false;
- _event->simulateEvent();
- _graphics->_longWinInFront = false;
return (result) ? Common::kNoError : Common::kUserCanceled;
}
@@ -229,11 +223,11 @@ Common::Error LabEngine::saveGameState(int slot, const Common::String &desc) {
}
bool LabEngine::canLoadGameStateCurrently() {
- return !_anim->isPlaying() && !_introPlaying;
+ return !_introPlaying;
}
bool LabEngine::canSaveGameStateCurrently() {
- return !_anim->isPlaying() && !_introPlaying;
+ return !_introPlaying;
}
} // End of namespace Lab
diff --git a/engines/lab/processroom.cpp b/engines/lab/processroom.cpp
index 44c8d65d7c..5093e8ef85 100644
--- a/engines/lab/processroom.cpp
+++ b/engines/lab/processroom.cpp
@@ -238,6 +238,8 @@ void LabEngine::doActions(const ActionList &actionList) {
ActionList::const_iterator action;
for (action = actionList.begin(); action != actionList.end(); ++action) {
updateEvents();
+ if (_quitLab || shouldQuit())
+ return;
switch (action->_actionType) {
case kActionPlaySound:
@@ -381,6 +383,8 @@ void LabEngine::doActions(const ActionList &actionList) {
while (_system->getMillis() < targetMillis) {
updateEvents();
+ if (_quitLab || shouldQuit())
+ return;
_anim->diffNextFrame();
}
}
@@ -409,6 +413,8 @@ void LabEngine::doActions(const ActionList &actionList) {
case kActionWaitSound: // used in scene 44 (heart of the labyrinth / ending)
while (_music->isSoundEffectActive()) {
updateEvents();
+ if (_quitLab || shouldQuit())
+ return;
_anim->diffNextFrame();
waitTOF();
}
diff --git a/engines/lab/savegame.cpp b/engines/lab/savegame.cpp
index 16c4044839..656595e3e5 100644
--- a/engines/lab/savegame.cpp
+++ b/engines/lab/savegame.cpp
@@ -157,6 +157,11 @@ bool LabEngine::saveGame(int slot, const Common::String desc) {
file->finalize();
delete file;
+ _mainDisplay = true;
+ _alternate = false;
+ _event->simulateEvent();
+ _graphics->screenUpdate();
+
return true;
}
@@ -202,6 +207,17 @@ bool LabEngine::loadGame(int slot) {
delete file;
+ _curFileName = " ";
+ _closeDataPtr = nullptr;
+ _followingCrumbs = false;
+ _graphics->_longWinInFront = false;
+ _event->initMouse();
+
+ _mainDisplay = true;
+ _alternate = false;
+ _event->simulateEvent();
+ _graphics->screenUpdate();
+
return true;
}
@@ -238,11 +254,6 @@ bool LabEngine::saveRestoreGame() {
delete dialog;
}
- _alternate = false;
- _mainDisplay = true;
- _event->initMouse();
- _graphics->screenUpdate();
-
return isOK;
}
diff --git a/engines/lastexpress/configure.engine b/engines/lastexpress/configure.engine
index 807b1a088b..66bac55dea 100644
--- a/engines/lastexpress/configure.engine
+++ b/engines/lastexpress/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 lastexpress "The Last Express" no "" "" "16bit"
+add_engine lastexpress "The Last Express" no "" "" "16bit highres"
diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp
index d790582104..52224e4ea5 100644
--- a/engines/lastexpress/detection.cpp
+++ b/engines/lastexpress/detection.cpp
@@ -199,8 +199,8 @@ static const ADGameDescription gameDescriptions[] = {
class LastExpressMetaEngine : public AdvancedMetaEngine {
public:
LastExpressMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), lastExpressGames) {
- _singleid = "lastexpress";
- _guioptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOSFX);
+ _singleId = "lastexpress";
+ _guiOptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOSFX);
}
const char *getName() const {
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index 902e8afd65..690a358bc3 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -193,12 +193,12 @@ class LureMetaEngine : public AdvancedMetaEngine {
public:
LureMetaEngine() : AdvancedMetaEngine(Lure::gameDescriptions, sizeof(Lure::LureGameDescription), lureGames) {
_md5Bytes = 1024;
- _singleid = "lure";
+ _singleId = "lure";
// Use kADFlagUseExtraAsHint to distinguish between EGA and VGA versions
// of italian Lure when their datafiles sit in the same directory.
_flags = kADFlagUseExtraAsHint;
- _guioptions = GUIO1(GUIO_NOSPEECH);
+ _guiOptions = GUIO1(GUIO_NOSPEECH);
}
virtual const char *getName() const {
@@ -245,7 +245,6 @@ SaveStateList LureMetaEngine::listSaves(const char *target) const {
Common::String pattern = "lure.###";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -262,6 +261,8 @@ SaveStateList LureMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index 7adc3e1f98..636c2d147c 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -521,7 +521,7 @@ static MadeGameDescription g_fallbackDesc = {
class MadeMetaEngine : public AdvancedMetaEngine {
public:
MadeMetaEngine() : AdvancedMetaEngine(Made::gameDescriptions, sizeof(Made::MadeGameDescription), madeGames) {
- _singleid = "made";
+ _singleId = "made";
}
virtual const char *getName() const {
diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
index 740c19abad..b9731b1d31 100644
--- a/engines/mads/debugger.cpp
+++ b/engines/mads/debugger.cpp
@@ -158,7 +158,7 @@ bool Debugger::Cmd_ShowCodes(int argc, const char **argv) {
Scene &scene = _vm->_game->_scene;
// Copy the depth/walk surface to the background and flag for screen refresh
- scene._depthSurface.copyTo(&scene._backgroundSurface);
+ scene._depthSurface.blitFrom(scene._backgroundSurface);
scene._spriteSlots.fullRefresh();
// Draw the locations of scene nodes onto the background
diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp
index 0357bd4bcc..b3ba60b6d0 100644
--- a/engines/mads/detection.cpp
+++ b/engines/mads/detection.cpp
@@ -192,7 +192,6 @@ SaveStateList MADSMetaEngine::listSaves(const char *target) const {
MADS::MADSSavegameHeader header;
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
@@ -213,6 +212,8 @@ SaveStateList MADSMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
index d9a1e53964..fa656a90c1 100644
--- a/engines/mads/dialogs.cpp
+++ b/engines/mads/dialogs.cpp
@@ -54,21 +54,19 @@ Dialog::~Dialog() {
void Dialog::save() {
_savedSurface = new MSurface(_width, _height);
- _vm->_screen.copyTo(_savedSurface,
+ _savedSurface->blitFrom(*_vm->_screen,
Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height),
Common::Point());
- _vm->_screen.copyRectToScreen(getBounds());
+// _vm->_screen->copyRectToScreen(getBounds());
}
void Dialog::restore() {
if (_savedSurface) {
- _savedSurface->copyTo(&_vm->_screen, _position);
+ _vm->_screen->blitFrom(*_savedSurface, _position);
delete _savedSurface;
_savedSurface = nullptr;
- _vm->_screen.copyRectToScreen(getBounds());
-
Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3],
&_vm->_palette->_mainPalette[248 * 3]);
_vm->_palette->setPalette(&_vm->_palette->_mainPalette[248 * 3], 248, 8);
@@ -87,16 +85,16 @@ void Dialog::draw() {
// Draw the dialog
// Fill entire content of dialog
Common::Rect bounds = getBounds();
- _vm->_screen.fillRect(bounds, TEXTDIALOG_BACKGROUND);
+ _vm->_screen->fillRect(bounds, TEXTDIALOG_BACKGROUND);
// Draw the outer edge lines
- _vm->_screen.hLine(_position.x + 1, _position.y + _height - 2,
+ _vm->_screen->hLine(_position.x + 1, _position.y + _height - 2,
_position.x + _width - 2, TEXTDIALOG_EDGE);
- _vm->_screen.hLine(_position.x, _position.y + _height - 1,
+ _vm->_screen->hLine(_position.x, _position.y + _height - 1,
_position.x + _width - 1, TEXTDIALOG_EDGE);
- _vm->_screen.vLine(_position.x + _width - 2, _position.y + 2,
+ _vm->_screen->vLine(_position.x + _width - 2, _position.y + 2,
_position.y + _height - 2, TEXTDIALOG_EDGE);
- _vm->_screen.vLine(_position.x + _width - 1, _position.y + 1,
+ _vm->_screen->vLine(_position.x + _width - 1, _position.y + 1,
_position.y + _height - 1, TEXTDIALOG_EDGE);
// Draw the gravelly dialog content
@@ -125,8 +123,9 @@ void Dialog::calculateBounds() {
void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte color2) {
uint16 currSeed = seed ? seed : 0xB78E;
+ Graphics::Surface dest = _vm->_screen->getSubArea(r);
for (int yp = 0; yp < r.height(); ++yp) {
- byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp);
+ byte *destP = (byte *)dest.getBasePtr(0, yp);
for (int xp = 0; xp < r.width(); ++xp) {
uint16 seedAdjust = currSeed;
@@ -326,7 +325,7 @@ void TextDialog::draw() {
for (int lineNum = 0; lineNum <= _numLines; ++lineNum) {
if (_lineXp[lineNum] == -1) {
// Draw a line across the entire dialog
- _vm->_screen.hLine(_position.x + 2,
+ _vm->_screen->hLine(_position.x + 2,
lineYp + (_font->getHeight() + 1) / 2,
_position.x + _width - 4, TEXTDIALOG_BLACK);
} else {
@@ -336,21 +335,19 @@ void TextDialog::draw() {
if (_lineXp[lineNum] & 0x40)
++yp;
- _font->writeString(&_vm->_screen, _lines[lineNum],
+ _font->writeString(_vm->_screen, _lines[lineNum],
Common::Point(xp, yp), 1);
if (_lineXp[lineNum] & 0x80) {
// Draw an underline under the text
int lineWidth = _font->getWidth(_lines[lineNum], 1);
- _vm->_screen.hLine(xp, yp + _font->getHeight(), xp + lineWidth,
+ _vm->_screen->hLine(xp, yp + _font->getHeight(), xp + lineWidth,
TEXTDIALOG_BLACK);
}
}
lineYp += _font->getHeight() + 1;
}
-
- _vm->_screen.copyRectToScreen(getBounds());
}
void TextDialog::calculateBounds() {
@@ -360,10 +357,10 @@ void TextDialog::calculateBounds() {
if (_position.y == -1)
_position.y = 100 - (_height / 2);
- if ((_position.x + _width) > _vm->_screen.getWidth())
- _position.x = _vm->_screen.getWidth() - (_position.x + _width);
- if ((_position.y + _height) > _vm->_screen.getHeight())
- _position.y = _vm->_screen.getHeight() - (_position.y + _height);
+ if ((_position.x + _width) > _vm->_screen->w)
+ _position.x = _vm->_screen->w - (_position.x + _width);
+ if ((_position.y + _height) > _vm->_screen->h)
+ _position.y = _vm->_screen->h - (_position.y + _height);
}
void TextDialog::drawWithInput() {
@@ -452,7 +449,7 @@ FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
}
FullScreenDialog::~FullScreenDialog() {
- _vm->_screen.resetClipBounds();
+ _vm->_screen->resetClipBounds();
_vm->_game->_scene.restrictScene();
}
@@ -491,16 +488,13 @@ void FullScreenDialog::display() {
game._trigger = 0;
// Clear the screen and draw the upper and lower horizontal lines
- _vm->_screen.empty();
+ _vm->_screen->clear();
_vm->_palette->setLowRange();
- _vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
- _vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
- _vm->_screen.resetClipBounds();
- _vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+ _vm->_screen->hLine(0, 20, MADS_SCREEN_WIDTH, 2);
+ _vm->_screen->hLine(0, 179, MADS_SCREEN_WIDTH, 2);
// Restrict the screen to the area between the two lines
- _vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
- DIALOG_TOP + MADS_SCENE_HEIGHT));
+ _vm->_screen->setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH, DIALOG_TOP + MADS_SCENE_HEIGHT));
_vm->_game->_scene.restrictScene();
if (_screenId > 0)
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
index 938931e80d..a18d03d143 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.cpp
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
@@ -218,7 +218,7 @@ void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, int variant) {
}
void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
- byte *destP = depthSurface.getData();
+ byte *destP = (byte *)depthSurface.getPixels();
byte *walkMap = new byte[stream->size()];
stream->read(walkMap, stream->size());
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 7463704c4b..de83260b0f 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -98,7 +98,7 @@ void EventsManager::changeCursor() {
// Check for hotspot indication pixels along the right-hand and bottom
// row. Put together, these give the cursor's hotspot x,y
int hotspotX = 0, hotspotY = 0;
- byte *cursorData = cursor->getData();
+ const byte *cursorData = (const byte *)cursor->getPixels();
for (int idx = 0; idx < cursor->w; ++idx) {
if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex)
hotspotX = idx;
@@ -110,7 +110,7 @@ void EventsManager::changeCursor() {
// Reduce the cursor data to remove the last column from each row, since
// the cursor routines don't have a pitch option
byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)];
- byte *srcP = cursorData;
+ const byte *srcP = cursorData;
byte *destP = destCursor;
for (int idx = 0; idx < (cursor->h - 1); ++idx) {
@@ -217,7 +217,7 @@ bool EventsManager::checkForNextFrameCounter() {
_vm->_debugger->onFrame();
// Display the frame
- _vm->_screen.updateScreen();
+ _vm->_screen->update();
// Signal the ScummVM debugger
_vm->_debugger->onFrame();
diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp
index 3e6d23fe6f..3828c3df8e 100644
--- a/engines/mads/font.cpp
+++ b/engines/mads/font.cpp
@@ -167,16 +167,13 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
return x;
int bottom = y + height - 1;
- if (bottom > surface->getHeight() - 1) {
- height -= MIN(height, bottom - (surface->getHeight() - 1));
+ if (bottom > surface->h - 1) {
+ height -= MIN(height, bottom - (surface->h - 1));
}
if (height <= 0)
return x;
- byte *destPtr = surface->getBasePtr(x, y);
- uint8 *oldDestPtr = destPtr;
-
int xPos = x;
const char *text = msg.c_str();
@@ -185,10 +182,11 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
int charWidth = _charWidths[(byte)theChar];
if (charWidth > 0) {
-
if (xPos + charWidth > xEnd)
return xPos;
+ Graphics::Surface dest = surface->getSubArea(
+ Common::Rect(xPos, y, xPos + charWidth, y + height));
uint8 *charData = &_charData[_charOffs[(byte)theChar]];
int bpp = getBpp(charWidth);
@@ -196,6 +194,8 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
charData += bpp * skipY;
for (int i = 0; i < height; i++) {
+ byte *destPtr = (byte *)dest.getBasePtr(0, i);
+
for (int j = 0; j < bpp; j++) {
if (*charData & 0xc0)
*destPtr = _fontColors[(*charData & 0xc0) >> 6];
@@ -211,22 +211,13 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
destPtr++;
charData++;
}
-
- destPtr += surface->getWidth() - bpp * 4;
-
}
-
- destPtr = oldDestPtr + charWidth + spaceWidth;
- oldDestPtr = destPtr;
-
}
xPos += charWidth + spaceWidth;
-
}
return xPos;
-
}
int Font::getWidth(const Common::String &msg, int spaceWidth) {
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 8ebea2a3b2..0a6741ba7a 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -498,7 +498,7 @@ void Game::loadGame(int slotNumber) {
_scene._currentSceneId = -2;
_sectionNumber = _scene._nextSceneId / 100;
_scene._frameStartTime = _vm->_events->getFrameCounter();
- _vm->_screen._shakeCountdown = -1;
+ _vm->_screen->_shakeCountdown = -1;
// Default the selected inventory item to the first one, if the player has any
_scene._userInterface._selectedInvIndex = _objects._inventoryList.size() > 0 ? 0 : -1;
@@ -600,7 +600,8 @@ void Game::createThumbnail() {
uint8 thumbPalette[PALETTE_SIZE];
_vm->_palette->grabPalette(thumbPalette, 0, PALETTE_COUNT);
_saveThumb = new Graphics::Surface();
- ::createThumbnail(_saveThumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette);
+ ::createThumbnail(_saveThumb, (const byte *)_vm->_screen->getPixels(),
+ MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette);
}
void Game::syncTimers(SyncType slaveType, int slaveId, SyncType masterType, int masterId) {
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index 963a35c24c..29bcd10094 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -94,22 +94,15 @@ void MADSEngine::initialize() {
_palette = new Palette(this);
Font::init(this);
_font = new Font();
- _screen.init();
+ _screen = new Screen();
_sound = new SoundManager(this, _mixer);
_audio = new AudioPlayer(_mixer, getGameID());
_game = Game::init(this);
-
- switch (getGameID()) {
- case GType_RexNebular:
- _gameConv = nullptr;
- break;
- default:
- _gameConv = new GameConversations(this);
- }
+ _gameConv = new GameConversations(this);
loadOptions();
- _screen.empty();
+ _screen->clear();
}
void MADSEngine::loadOptions() {
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index eb808de32f..52f71f7c79 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -100,7 +100,7 @@ public:
GameConversations * _gameConv;
Palette *_palette;
Resources *_resources;
- ScreenSurface _screen;
+ Screen *_screen;
SoundManager *_sound;
AudioPlayer *_audio;
bool _easyMouse;
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
index 10d5a2179a..9050ca6081 100644
--- a/engines/mads/menu_views.cpp
+++ b/engines/mads/menu_views.cpp
@@ -253,7 +253,7 @@ void TextView::processCommand() {
SceneInfo *sceneInfo = SceneInfo::init(_vm);
sceneInfo->_width = MADS_SCREEN_WIDTH;
sceneInfo->_height = MADS_SCENE_HEIGHT;
- _spareScreens[spareIndex].setSize(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ _spareScreens[spareIndex].create(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
_spareScreens[spareIndex]);
@@ -346,9 +346,11 @@ void TextView::doFrame() {
// If a screen transition is in progress and it's time for another column, handle it
if (_spareScreen) {
- byte *srcP = _spareScreen->getBasePtr(_translationX, 0);
- byte *bgP = scene._backgroundSurface.getBasePtr(_translationX, 0);
- byte *screenP = (byte *)_vm->_screen.getBasePtr(_translationX, 0);
+ const byte *srcP = (const byte *)_spareScreen->getBasePtr(_translationX, 0);
+ byte *bgP = (byte *)scene._backgroundSurface.getBasePtr(_translationX, 0);
+
+ Graphics::Surface dest = _vm->_screen->getSubArea(Common::Rect(_translationX, 0, _translationX + 1, 0));
+ byte *screenP = (byte *)dest.getBasePtr(0, 0);
for (int y = 0; y < MADS_SCENE_HEIGHT; ++y, srcP += MADS_SCREEN_WIDTH,
bgP += MADS_SCREEN_WIDTH, screenP += MADS_SCREEN_WIDTH) {
@@ -356,10 +358,6 @@ void TextView::doFrame() {
*screenP = *srcP;
}
- // Flag the column of the screen is modified
- _vm->_screen.copyRectToScreen(Common::Rect(_translationX, 0,
- _translationX + 1, MADS_SCENE_HEIGHT));
-
// Keep moving the column to copy to the right
if (++_translationX == MADS_SCREEN_WIDTH) {
// Surface transition is complete
@@ -571,6 +569,7 @@ void AnimationView::doFrame() {
void AnimationView::loadNextResource() {
Scene &scene = _vm->_game->_scene;
Palette &palette = *_vm->_palette;
+ Screen &screen = *_vm->_screen;
ResourceEntry &resEntry = _resources[_resourceIndex];
Common::Array<PaletteCycle> paletteCycles;
@@ -587,12 +586,15 @@ void AnimationView::loadNextResource() {
// Handle the bars at the top/bottom
if (resEntry._showWhiteBars) {
// For animations the screen has been clipped to the middle 156 rows.
- // So although it's slightly messy, bypass our screen class entirely,
- // and draw the horizontal lines directly on the physiacl screen surface
- Graphics::Surface *s = g_system->lockScreen();
- s->hLine(0, 20, MADS_SCREEN_WIDTH, 253);
- s->hLine(0, 179, MADS_SCREEN_WIDTH, 253);
- g_system->unlockScreen();
+ // So although it's slightly messy, temporarily reset clip bounds
+ // so we can redraw the white lines
+ Common::Rect clipBounds = screen.getClipBounds();
+ screen.resetClipBounds();
+
+ screen.hLine(0, 20, MADS_SCREEN_WIDTH, 253);
+ screen.hLine(0, 179, MADS_SCREEN_WIDTH, 253);
+
+ screen.setClipBounds(clipBounds);
}
// Load the new animation
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index f768624278..40c69c0f08 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -32,37 +32,6 @@ namespace MADS {
MADSEngine *MSurface::_vm = nullptr;
-MSurface::MSurface() {
- pixels = nullptr;
- _freeFlag = false;
-}
-
-MSurface::MSurface(int width, int height) {
- pixels = nullptr;
- _freeFlag = false;
- setSize(width, height);
-}
-
-MSurface::~MSurface() {
- if (_freeFlag)
- Graphics::Surface::free();
-}
-
-void MSurface::setSize(int width, int height) {
- if (_freeFlag)
- Graphics::Surface::free();
- Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- _freeFlag = true;
-}
-
-void MSurface::setPixels(byte *pData, int horizSize, int vertSize) {
- _freeFlag = false;
- pixels = pData;
- w = pitch = horizSize;
- h = vertSize;
- format.bytesPerPixel = 1;
-}
-
int MSurface::scaleValue(int value, int scale, int err) {
int scaled = 0;
while (value--) {
@@ -76,7 +45,6 @@ int MSurface::scaleValue(int value, int scale, int err) {
}
void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect) {
-
enum {
kStatusSkip,
kStatusScale,
@@ -116,8 +84,8 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
return;
int heightAmt = scaledHeight;
- byte *src = info.sprite->getData();
- byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY);
+ const byte *src = (const byte *)info.sprite->getPixels();
+ byte *dst = (byte *)getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY);
int status = kStatusSkip;
byte *scaledLineBuf = new byte[scaledWidth];
@@ -138,7 +106,7 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
byte *lineDst = scaledLineBuf;
int curErrX = errX;
int width = scaledWidth;
- byte *tempSrc = src;
+ const byte *tempSrc = src;
int startX = clipX;
while (width > 0) {
byte pixel = *tempSrc++;
@@ -201,63 +169,136 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
}
delete[] scaledLineBuf;
-
}
-void MSurface::empty() {
- Common::fill(getBasePtr(0, 0), getBasePtr(0, h), 0);
+void MSurface::scrollX(int xAmount) {
+ if (xAmount == 0)
+ return;
+
+ byte buffer[80];
+ int direction = (xAmount > 0) ? -1 : 1;
+ int xSize = ABS(xAmount);
+ assert(xSize <= 80);
+
+ byte *srcP = (byte *)getBasePtr(0, 0);
+
+ for (int y = 0; y < this->h; ++y, srcP += pitch) {
+ if (direction < 0) {
+ // Copy area to be overwritten
+ Common::copy(srcP, srcP + xSize, &buffer[0]);
+ // Shift the remainder of the line over the given area
+ Common::copy(srcP + xSize, srcP + this->w, srcP);
+ // Move buffered area to the end of the line
+ Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
+ } else {
+ // Copy area to be overwritten
+ Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
+ // Shift the remainder of the line over the given area
+ Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
+ // Move buffered area to the start of the line
+ Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
+ }
+ }
+
+ markAllDirty();
}
-void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds,
- const Common::Point &destPos, int transparentColor) {
- // Validation of the rectangle and position
- int destX = destPos.x, destY = destPos.y;
- if ((destX >= w) || (destY >= h))
+void MSurface::scrollY(int yAmount) {
+ if (yAmount == 0)
return;
- Common::Rect copyRect = srcBounds;
- if (destX < 0) {
- copyRect.left += -destX;
- destX = 0;
- } else if (destX + copyRect.width() > w) {
- copyRect.right -= destX + copyRect.width() - w;
- }
- if (destY < 0) {
- copyRect.top += -destY;
- destY = 0;
- } else if (destY + copyRect.height() > h) {
- copyRect.bottom -= destY + copyRect.height() - h;
+ int direction = (yAmount > 0) ? 1 : -1;
+ int ySize = ABS(yAmount);
+ assert(ySize < (this->h / 2));
+ assert(this->w == pitch);
+
+ int blockSize = ySize * this->w;
+ byte *tempData = new byte[blockSize];
+ byte *pixelsP = (byte *)getBasePtr(0, 0);
+
+ if (direction > 0) {
+ // Buffer the lines to be overwritten
+ byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
+ Common::copy(srcP, srcP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
+ pixelsP + (pitch * this->h));
+ // Transfer the buffered lines top the top of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP);
+ } else {
+ // Buffer the lines to be overwritten
+ Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
+ // Transfer the buffered lines to the bottom of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
}
- if (!copyRect.isValidRect())
- return;
+ markAllDirty();
+ delete[] tempData;
+}
- // Copy the specified area
+void MSurface::translate(Common::Array<RGB6> &palette) {
+ for (int y = 0; y < this->h; ++y) {
+ byte *pDest = (byte *)getBasePtr(0, y);
+
+ for (int x = 0; x < this->w; ++x, ++pDest) {
+ if (*pDest < 255) // scene 752 has some palette indices of 255
+ *pDest = palette[*pDest]._palIndex;
+ }
+ }
- byte *data = src->getData();
- byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
- byte *destPtr = (byte *)pixels + (destY * getWidth()) + destX;
+ markAllDirty();
+}
- for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
- if (transparentColor == -1) {
- // No transparency, so copy line over
- Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr);
- } else {
- // Copy each byte one at a time checking for the transparency color
- for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr)
- if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr];
+void MSurface::translate(byte map[PALETTE_COUNT]) {
+ for (int y = 0; y < this->h; ++y) {
+ byte *pDest = (byte *)getBasePtr(0, y);
+
+ for (int x = 0; x < this->w; ++x, ++pDest) {
+ *pDest = map[*pDest];
}
+ }
+
+ markAllDirty();
+}
+
+MSurface *MSurface::flipHorizontal() const {
+ MSurface *dest = new MSurface(this->w, this->h);
+
+ for (int y = 0; y < this->h; ++y) {
+ const byte *srcP = getBasePtr(this->w - 1, y);
+ byte *destP = dest->getBasePtr(0, y);
- srcPtr += src->getWidth();
- destPtr += getWidth();
+ for (int x = 0; x < this->w; ++x)
+ *destP++ = *srcP--;
+ }
+
+ return dest;
+}
+
+void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
+ const Common::Point &destPos, const Common::Rect &srcRect) {
+ // Loop through the lines
+ for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
+ const byte *srcP = (const byte *)srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
+ byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yCtr);
+
+ // Copy the line over
+ for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
+ *destP = paletteMap[*srcP];
+ }
}
+
+ addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + srcRect.width(),
+ destPos.y + srcRect.height()));
}
-void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
+void MSurface::copyFrom(MSurface &src, const Common::Point &destPos, int depth,
DepthSurface *depthSurface, int scale, bool flipped, int transparentColor) {
int destX = destPos.x, destY = destPos.y;
- int frameWidth = src->getWidth();
- int frameHeight = src->getHeight();
+ int frameWidth = src.w;
+ int frameHeight = src.h;
int direction = flipped ? -1 : 1;
int highestDim = MAX(frameWidth, frameHeight);
@@ -271,7 +312,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
distCtr += scale;
if (distCtr < 100) {
lineDist[distIndex] = false;
- } else {
+ }
+ else {
lineDist[distIndex] = true;
distCtr -= 100;
@@ -290,18 +332,20 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
// Special case for quicker drawing of non-scaled images
if (scale == 100 || scale == -1) {
// Copy the specified area
- Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight());
+ Common::Rect copyRect(0, 0, src.w, src.h);
if (destX < 0) {
copyRect.left += -destX;
destX = 0;
- } else if (destX + copyRect.width() > w) {
+ }
+ else if (destX + copyRect.width() > w) {
copyRect.right -= destX + copyRect.width() - w;
}
if (destY < 0) {
copyRect.top += -destY;
destY = 0;
- } else if (destY + copyRect.height() > h) {
+ }
+ else if (destY + copyRect.height() > h) {
copyRect.bottom -= destY + copyRect.height() - h;
}
@@ -311,9 +355,9 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
if (flipped)
copyRect.moveTo(0, copyRect.top);
- byte *data = src->getData();
- byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
- byte *destPtr = (byte *)pixels + (destY * pitch) + destX;
+ byte *data = src.getPixels();
+ byte *srcPtr = data + (src.w * copyRect.top + copyRect.left);
+ byte *destPtr = (byte *)getPixels() + (destY * pitch) + destX;
if (flipped)
srcPtr += copyRect.width() - 1;
@@ -329,18 +373,18 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
destPtr[xCtr] = *srcP;
}
- srcPtr += src->getWidth();
- destPtr += getWidth();
+ srcPtr += src.w;
+ destPtr += this->w;
}
return;
}
// Start of draw logic for scaled sprites
- const byte *srcPixelsP = src->getData();
+ const byte *srcPixelsP = src.getPixels();
- int destRight = this->getWidth() - 1;
- int destBottom = this->getHeight() - 1;
+ int destRight = this->w - 1;
+ int destBottom = this->h - 1;
// Check x bounding area
int spriteLeft = 0;
@@ -387,7 +431,7 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
spriteLeft = spriteLeft * direction;
// Loop through the lines of the sprite
- for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) {
+ for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src.pitch) {
if (!lineDist[yp])
// Not a display line, so skip it
continue;
@@ -411,8 +455,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
continue;
// Get depth of current output pixel in depth surface
- Common::Point pt((destP - (byte *)this->pixels) % this->pitch,
- (destP - (byte *)this->pixels) / this->pitch);
+ Common::Point pt((destP - (byte *)getPixels()) % this->pitch,
+ (destP - (byte *)getPixels()) / this->pitch);
int pixelDepth = (depthSurface == nullptr) ? 15 : depthSurface->getDepth(pt);
if ((*srcP != transparentColor) && (depth <= pixelDepth))
@@ -424,119 +468,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
// Move to the next destination line
destPixelsP += this->pitch;
}
-}
-
-void MSurface::scrollX(int xAmount) {
- if (xAmount == 0)
- return;
-
- byte buffer[80];
- int direction = (xAmount > 0) ? -1 : 1;
- int xSize = ABS(xAmount);
- assert(xSize <= 80);
-
- byte *srcP = getBasePtr(0, 0);
-
- for (int y = 0; y < this->h; ++y, srcP += pitch) {
- if (direction < 0) {
- // Copy area to be overwritten
- Common::copy(srcP, srcP + xSize, &buffer[0]);
- // Shift the remainder of the line over the given area
- Common::copy(srcP + xSize, srcP + this->w, srcP);
- // Move buffered area to the end of the line
- Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
- } else {
- // Copy area to be overwritten
- Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
- // Shift the remainder of the line over the given area
- Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
- // Move buffered area to the start of the line
- Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
- }
- }
-}
-
-void MSurface::scrollY(int yAmount) {
- if (yAmount == 0)
- return;
-
- int direction = (yAmount > 0) ? 1 : -1;
- int ySize = ABS(yAmount);
- assert(ySize < (this->h / 2));
- assert(this->w == pitch);
-
- int blockSize = ySize * this->w;
- byte *tempData = new byte[blockSize];
- byte *pixelsP = getBasePtr(0, 0);
-
- if (direction > 0) {
- // Buffer the lines to be overwritten
- byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
- Common::copy(srcP, srcP + (pitch * ySize), tempData);
- // Vertically shift all the lines
- Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
- pixelsP + (pitch * this->h));
- // Transfer the buffered lines top the top of the screen
- Common::copy(tempData, tempData + blockSize, pixelsP);
- } else {
- // Buffer the lines to be overwritten
- Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
- // Vertically shift all the lines
- Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
- // Transfer the buffered lines to the bottom of the screen
- Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
- }
-
- delete[] tempData;
-}
-
-void MSurface::translate(Common::Array<RGB6> &palette) {
- for (int y = 0; y < this->h; ++y) {
- byte *pDest = getBasePtr(0, y);
-
- for (int x = 0; x < this->w; ++x, ++pDest) {
- if (*pDest < 255) // scene 752 has some palette indices of 255
- *pDest = palette[*pDest]._palIndex;
- }
- }
-}
-
-void MSurface::translate(byte map[PALETTE_COUNT]) {
- for (int y = 0; y < this->h; ++y) {
- byte *pDest = getBasePtr(0, y);
-
- for (int x = 0; x < this->w; ++x, ++pDest) {
- *pDest = map[*pDest];
- }
- }
-}
-
-MSurface *MSurface::flipHorizontal() const {
- MSurface *dest = new MSurface(this->w, this->h);
-
- for (int y = 0; y < this->h; ++y) {
- const byte *srcP = getBasePtr(this->w - 1, y);
- byte *destP = dest->getBasePtr(0, y);
-
- for (int x = 0; x < this->w; ++x)
- *destP++ = *srcP--;
- }
-
- return dest;
-}
-
-void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
- const Common::Point &destPos, const Common::Rect &srcRect) {
- // Loop through the lines
- for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
- const byte *srcP = srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
- byte *destP = getBasePtr(destPos.x, destPos.y + yCtr);
- // Copy the line over
- for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
- *destP = paletteMap[*srcP];
- }
- }
+ addDirtyRect(Common::Rect(destX, destY, destX + frameWidth, destY + frameHeight));
}
/*------------------------------------------------------------------------*/
@@ -544,26 +477,26 @@ void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
int DepthSurface::getDepth(const Common::Point &pt) {
if (_depthStyle == 2) {
int bits = (3 - (pt.x % 4)) * 2;
- byte v = *getBasePtr(pt.x >> 2, pt.y);
+ byte v = *(const byte *)getBasePtr(pt.x >> 2, pt.y);
return v >> bits;
} else {
if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
return 0;
- return *getBasePtr(pt.x, pt.y) & 0xF;
+ return *(const byte *)getBasePtr(pt.x, pt.y) & 0xF;
}
}
int DepthSurface::getDepthHighBit(const Common::Point &pt) {
if (_depthStyle == 2) {
int bits = (3 - (pt.x % 4)) * 2;
- byte v = *getBasePtr(pt.x >> 2, pt.y);
+ byte v = *(const byte *)getBasePtr(pt.x >> 2, pt.y);
return (v >> bits) & 2;
} else {
if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
return 0;
- return *getBasePtr(pt.x, pt.y) & 0x80;
+ return *(const byte *)getBasePtr(pt.x, pt.y) & 0x80;
}
}
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 80891afb83..e92770900d 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -25,7 +25,7 @@
#include "common/scummsys.h"
#include "common/rect.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
#include "mads/palette.h"
namespace MADS {
@@ -50,22 +50,21 @@ struct SpriteInfo {
/*
* MADS graphics surface
*/
-class MSurface : public Graphics::Surface {
+class MSurface : virtual public Graphics::ManagedSurface {
+private:
+ /**
+ * Helper method for calculating new dimensions when scaling a sprite
+ */
+ int scaleValue(int value, int scale, int err);
protected:
static MADSEngine *_vm;
- bool _freeFlag;
public:
/**
- * Sets the engine refrence used all surfaces
+ * Sets the engine reference used all surfaces
*/
static void setVm(MADSEngine *vm) { _vm = vm; }
/**
- * Helper method for calculating new dimensions when scaling a sprite
- */
- static int scaleValue(int value, int scale, int err);
-
- /**
* Base method for descendents to load their contents
*/
virtual void load(const Common::String &resName) {}
@@ -73,126 +72,50 @@ public:
/**
* Basic constructor
*/
- MSurface();
+ MSurface() : Graphics::ManagedSurface() {}
/**
* Constructor for a surface with fixed dimensions
*/
- MSurface(int width, int height);
+ MSurface(int width, int height) : Graphics::ManagedSurface(width, height) {}
/**
* Destructor
*/
- virtual ~MSurface();
-
- /**
- * Reinitializes a surface to have a given set of dimensions
- */
- void setSize(int width, int height);
-
- /**
- * Sets the pixels the surface is associated with
- * @remarks The surface will not free the data block
- */
- void setPixels(byte *pData, int horizSize, int vertSize);
-
- /**
- * Draws an arbitrary line on the screen using a specified color
- * @param startPos Starting position
- * @param endPos Ending position
- * @param color Color to use
- */
- void line(const Common::Point &startPos, const Common::Point &endPos, byte color);
-
- /**
- * Draws a sprite
- * @param pt Position to draw sprite at
- * @param info General sprite details
- * @param clipRect Clipping rectangle to constrain sprite drawing within
- */
- void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect);
-
- /**
- * Returns the width of the surface
- */
- int getWidth() const { return w; }
-
- /**
- * Returns the height of the surface
- */
- int getHeight() const { return h; }
+ virtual ~MSurface() {}
/**
- * Returns the size of the surface as a Rect
+ * Return a rect containing the bounds of the surface
*/
- Common::Rect getBounds() const {
- return Common::Rect(0, 0, w, h);
- }
+ Common::Rect getBounds() { return Common::Rect(0, 0, this->w, this->h); }
/**
- * Returns a pointer to the surface data
+ * Return the pixels for the surface
*/
- byte *getData() { return (byte *)Graphics::Surface::getPixels(); }
+ inline byte *getPixels() { return (byte *)Graphics::ManagedSurface::getPixels(); }
/**
- * Returns a pointer to a given position within the surface
+ * Return the pixels for the surface
*/
- byte *getBasePtr(int x, int y) { return (byte *)Graphics::Surface::getBasePtr(x, y); }
+ inline const void *getPixels() const { return (const byte *)Graphics::ManagedSurface::getPixels(); }
/**
- * Returns a pointer to a given position within the surface
- */
- const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::Surface::getBasePtr(x, y); }
-
- /**
- * Clears the surface
- */
- void empty();
-
- /**
- * Copys a sub-section of another surface into the current one.
- * @param src Source surface
- * @param srcBounds Area of source surface to copy
- * @param destPos Destination position to draw in current surface
- * @param transparentColor Transparency palette index
- */
- void copyFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos,
- int transparentColor = -1);
-
- /**
- * Copys a sub-section of another surface into the current one.
- * @param src Source surface
- * @param destPos Destination position to draw in current surface
- * @param depth Depth of sprite
- * @param depthSurface Depth surface to use with sprite depth
- * @param scale Scale for image
- * @param flipped Flag for whether image is to be flipped
- * @param transparentColor Transparency palette index
- */
- void copyFrom(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface,
- int scale, bool flipped, int transparentColor = -1);
-
- /**
- * Copies the surface to a given destination surface
+ * Return a pointer to a given position on the surface
*/
- void copyTo(MSurface *dest, int transparentColor = -1) {
- dest->copyFrom(this, Common::Rect(w, h), Common::Point(), transparentColor);
- }
+ byte *getBasePtr(int x, int y) { return (byte *)Graphics::ManagedSurface::getBasePtr(x, y); }
/**
- * Copies the surface to a given destination surface
+ * Return a pointer to a given position on the surface
*/
- void copyTo(MSurface *dest, const Common::Point &pt, int transparentColor = -1) {
- dest->copyFrom(this, Common::Rect(w, h), pt, transparentColor);
- }
+ inline const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::ManagedSurface::getBasePtr(x, y); }
/**
- * Copies the surface to a given destination surface
+ * Draws a sprite
+ * @param pt Position to draw sprite at
+ * @param info General sprite details
+ * @param clipRect Clipping rectangle to constrain sprite drawing within
*/
- void copyTo(MSurface *dest, const Common::Rect &srcBounds, const Common::Point &destPos,
- int transparentColor = -1) {
- dest->copyFrom(this, srcBounds, destPos, transparentColor);
- }
+ void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect);
/**
* Scroll the screen horizontally by a given amount
@@ -227,6 +150,19 @@ public:
*/
void copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
const Common::Point &destPos, const Common::Rect &srcRect);
+
+ /**
+ * Copys a sub-section of another surface into the current one.
+ * @param src Source surface
+ * @param destPos Destination position to draw in current surface
+ * @param depth Depth of sprite
+ * @param depthSurface Depth surface to use with sprite depth
+ * @param scale Scale for image
+ * @param flipped Flag for whether image is to be flipped
+ * @param transparentColor Transparency palette index
+ */
+ void copyFrom(MSurface &src, const Common::Point &destPos, int depth, DepthSurface *depthSurface,
+ int scale, bool flipped, int transparentColor = -1);
};
class DepthSurface : public MSurface {
@@ -239,7 +175,7 @@ public:
/**
* Constructor
*/
- DepthSurface() : _depthStyle(0) {}
+ DepthSurface() : MSurface(), _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 58e60fe323..2af80f517e 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -438,11 +438,10 @@ void CopyProtectionDialog::show() {
Common::KeyState curKey;
const Common::Rect inputArea(110, 165, 210, 175);
MSurface *origInput = new MSurface(inputArea.width(), inputArea.height());
- _vm->_screen.frameRect(inputArea, TEXTDIALOG_BLACK);
- _vm->_screen.copyTo(origInput, inputArea, Common::Point(0, 0));
- _font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE);
- _vm->_screen.copyRectToScreen(inputArea);
- _vm->_screen.updateScreen();
+ _vm->_screen->frameRect(inputArea, TEXTDIALOG_BLACK);
+ origInput->blitFrom(*_vm->_screen, inputArea, Common::Point(0, 0));
+ _font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE);
+ _vm->_screen->update();
bool firstTime = true;
@@ -470,11 +469,10 @@ void CopyProtectionDialog::show() {
_textInput = _hogEntry._word[0];
}
- _vm->_screen.copyFrom(origInput, Common::Rect(0, 0, inputArea.width(), inputArea.height()), Common::Point(inputArea.left, inputArea.top));
- _font->writeString(&_vm->_screen, _textInput,
+ _vm->_screen->blitFrom(*origInput, Common::Point(inputArea.left, inputArea.top));
+ _font->writeString(_vm->_screen, _textInput,
Common::Point(inputArea.left + 2, inputArea.top + 1), 1);
- _vm->_screen.copyRectToScreen(inputArea);
- _vm->_screen.updateScreen();
+ _vm->_screen->update();
}
origInput->free();
@@ -537,7 +535,7 @@ void PictureDialog::save() {
// Save the entire screen
_savedSurface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
- _vm->_screen.copyTo(_savedSurface);
+ _savedSurface->blitFrom(*_vm->_screen);
// Save palette information
Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE], &_palette[0]);
@@ -568,7 +566,7 @@ void PictureDialog::save() {
// Remap the greyed out screen to use the small greyscale range
// at the top end of the palette
- _vm->_screen.translate(map);
+ _vm->_screen->translate(map);
// Load the inventory picture
Common::String setName = Common::String::format("*OB%.3d.SS", _objectId);
@@ -578,13 +576,12 @@ void PictureDialog::save() {
// Get the inventory frame, and adjust the dialog position to allow for it
MSprite *frame = asset->getFrame(0);
_position.y = frame->h + 12;
- if ((_position.y + _height) > _vm->_screen.getHeight())
- _position.y -= (_position.y + _height) - _vm->_screen.getHeight();
+ if ((_position.y + _height) > _vm->_screen->h)
+ _position.y -= (_position.y + _height) - _vm->_screen->h;
// Draw the inventory picture
- frame->copyTo(&_vm->_screen, Common::Point(160 - frame->w / 2, 6),
+ _vm->_screen->transBlitFrom(*frame, Common::Point(160 - frame->w / 2, 6),
frame->getTransparencyIndex());
- _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
// Adjust the dialog colors to use
TEXTDIALOG_CONTENT1 -= 10;
@@ -598,13 +595,11 @@ void PictureDialog::save() {
void PictureDialog::restore() {
if (_savedSurface) {
- _savedSurface->copyTo(&_vm->_screen);
+ _vm->_screen->blitFrom(*_savedSurface);
_savedSurface->free();
delete _savedSurface;
_savedSurface = nullptr;
- _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
-
// Restore palette information
Palette &palette = *_vm->_palette;
Common::copy(&_palette[0], &_palette[PALETTE_SIZE], &palette._mainPalette[0]);
@@ -691,7 +686,6 @@ void GameDialog::display() {
}
GameDialog::~GameDialog() {
- _vm->_screen.resetClipBounds();
_vm->_game->_scene._currentSceneId = RETURNING_FROM_DIALOG;
}
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index 9c0acf1a47..1db5eaea00 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -827,49 +827,51 @@ void GameNebular::step() {
if (_player._visible && _player._stepEnabled && !_player._moving &&
(_player._facing == _player._turnToFacing)) {
if (_scene._frameStartTime >= (uint32)_globals[kWalkerTiming]) {
- int randomVal = _vm->getRandomNumber(29999);
- if (_globals[kSexOfRex] == REX_MALE) {
- switch (_player._facing) {
- case FACING_SOUTHWEST:
- case FACING_SOUTHEAST:
- case FACING_NORTHWEST:
- case FACING_NORTHEAST:
- if (randomVal < 200) {
- _player.addWalker(-1, 0);
- _player.addWalker(1, 0);
- }
- break;
-
- case FACING_WEST:
- case FACING_EAST:
- if (randomVal < 500) {
- for (int count = 0; count < 10; ++count) {
+ if (_player._stopWalkers.empty()) {
+ int randomVal = _vm->getRandomNumber(29999);
+ if (_globals[kSexOfRex] == REX_MALE) {
+ switch (_player._facing) {
+ case FACING_SOUTHWEST:
+ case FACING_SOUTHEAST:
+ case FACING_NORTHWEST:
+ case FACING_NORTHEAST:
+ if (randomVal < 200) {
+ _player.addWalker(-1, 0);
_player.addWalker(1, 0);
}
- }
- break;
-
- case FACING_SOUTH:
- if (randomVal < 500) {
- for (int count = 0; count < 10; ++count) {
- _player.addWalker((randomVal < 250) ? 1 : 2, 0);
+ break;
+
+ case FACING_WEST:
+ case FACING_EAST:
+ if (randomVal < 500) {
+ for (int count = 0; count < 10; ++count) {
+ _player.addWalker(1, 0);
+ }
}
- } else if (randomVal < 750) {
- for (int count = 0; count < 5; ++count) {
- _player.addWalker(1, 0);
+ break;
+
+ case FACING_SOUTH:
+ if (randomVal < 500) {
+ for (int count = 0; count < 10; ++count) {
+ _player.addWalker((randomVal < 250) ? 1 : 2, 0);
+ }
+ } else if (randomVal < 750) {
+ for (int count = 0; count < 5; ++count) {
+ _player.addWalker(1, 0);
+ }
+
+ _player.addWalker(0, 0);
+ _player.addWalker(0, 0);
+
+ for (int count = 0; count < 5; ++count) {
+ _player.addWalker(2, 0);
+ }
}
+ break;
- _player.addWalker(0, 0);
- _player.addWalker(0, 0);
-
- for (int count = 0; count < 5; ++count) {
- _player.addWalker(2, 0);
- }
+ default:
+ break;
}
- break;
-
- default:
- break;
}
}
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 0520294b29..cd81efe0f0 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -384,8 +384,8 @@ void AdvertView::show() {
// Load the advert background onto the screen
SceneInfo *sceneInfo = SceneInfo::init(_vm);
sceneInfo->load(screenId, 0, Common::String(), 0, _vm->_game->_scene._depthSurface,
- _vm->_screen);
- _vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
+ *_vm->_screen);
+ _vm->_screen->markAllDirty();
_vm->_palette->setFullPalette(_vm->_palette->_mainPalette);
delete sceneInfo;
diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp
index da419a70a2..40228b4b7d 100644
--- a/engines/mads/nebular/nebular_scenes.cpp
+++ b/engines/mads/nebular/nebular_scenes.cpp
@@ -323,8 +323,8 @@ void SceneInfoNebular::loadCodes(MSurface &depthSurface, int variant) {
}
void SceneInfoNebular::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
- byte *destP = depthSurface.getData();
- byte *endP = depthSurface.getBasePtr(0, depthSurface.h);
+ byte *destP = (byte *)depthSurface.getPixels();
+ byte *endP = (byte *)depthSurface.getBasePtr(0, depthSurface.h);
byte runLength = stream->readByte();
while (destP < endP && runLength > 0) {
diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp
index 0fb13a706c..7323ee893d 100644
--- a/engines/mads/nebular/nebular_scenes3.cpp
+++ b/engines/mads/nebular/nebular_scenes3.cpp
@@ -2818,7 +2818,7 @@ void Scene318::step() {
if (_internCounter >= 3600) {
_vm->_sound->command(59);
- _vm->_screen._shakeCountdown = 20;
+ _vm->_screen->_shakeCountdown = 20;
_internWalkingFl = true;
}
}
@@ -3288,22 +3288,22 @@ void Scene319::step() {
if (_animMode == 2) {
if (_animFrame == 13)
- _vm->_screen._shakeCountdown = 40;
+ _vm->_screen->_shakeCountdown = 40;
if (_animFrame == 16)
- _vm->_screen._shakeCountdown = 1;
+ _vm->_screen->_shakeCountdown = 1;
}
if (_animMode == 3) {
if (_animFrame == 11)
- _vm->_screen._shakeCountdown = 60;
+ _vm->_screen->_shakeCountdown = 60;
if (_animFrame == 18)
- _vm->_screen._shakeCountdown = 1;
+ _vm->_screen->_shakeCountdown = 1;
}
if ((_animMode == 4) && (_animFrame == 16))
- _vm->_screen._shakeCountdown = 80;
+ _vm->_screen->_shakeCountdown = 80;
if ((nextFrame >= 0) && (nextFrame != _scene->_animation[0]->getCurrentFrame())) {
_scene->_animation[0]->setCurrentFrame(nextFrame);
@@ -3326,7 +3326,7 @@ void Scene319::step() {
_animFrame = _scene->_animation[0]->getCurrentFrame();
_slacheTalkingFl = true;
- _vm->_screen._shakeCountdown = 1;
+ _vm->_screen->_shakeCountdown = 1;
for (int i = 0; i <= 1; i++) {
int oldIdx = _globals._sequenceIndexes[i];
@@ -3350,7 +3350,7 @@ void Scene319::step() {
_vm->_palette->setColorValues(0, 0, 0);
_vm->_palette->fadeOut(_vm->_palette->_mainPalette, nullptr, 18, 228,
248, 0, 1, 16);
- _vm->_screen._shakeCountdown = 1;
+ _vm->_screen->_shakeCountdown = 1;
_scene->_reloadSceneFlag = true;
break;
@@ -3731,7 +3731,7 @@ void Scene320::step() {
case 417:
case 457:
- _vm->_screen._shakeCountdown = 40;
+ _vm->_screen->_shakeCountdown = 40;
_vm->_sound->command(59);
break;
diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp
index 3778a59eb3..ea3574b0d1 100644
--- a/engines/mads/nebular/nebular_scenes5.cpp
+++ b/engines/mads/nebular/nebular_scenes5.cpp
@@ -1603,7 +1603,7 @@ void Scene508::enter() {
_globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2);
_scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8);
_globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2);
- int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
+ int idx = _scene->_dynamicHotspots.add(NOUN_SPINACH_PATCH_DOLL, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0));
_scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST);
_scene->_hotspots.activate(NOUN_HOLE, false);
_scene->_hotspots.activate(NOUN_LASER_BEAM, false);
diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp
index f7a7153fbe..7ef627ceeb 100644
--- a/engines/mads/phantom/phantom_scenes.cpp
+++ b/engines/mads/phantom/phantom_scenes.cpp
@@ -191,7 +191,7 @@ void SceneInfoPhantom::loadCodes(MSurface &depthSurface, int variant) {
}
void SceneInfoPhantom::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
- byte *destP = depthSurface.getData();
+ byte *destP = (byte *)depthSurface.getPixels();
byte *walkMap = new byte[stream->size()];
stream->read(walkMap, stream->size());
diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp
index ee0ca98cd3..46d9e0ebd3 100644
--- a/engines/mads/rails.cpp
+++ b/engines/mads/rails.cpp
@@ -149,7 +149,7 @@ int Rails::scanPath(const Common::Point &srcPos, const Common::Point &destPos) {
++xDiff;
++yDiff;
- const byte *srcP = _depthSurface->getBasePtr(srcPos.x, srcPos.y);
+ const byte *srcP = (const byte *)_depthSurface->getBasePtr(srcPos.x, srcPos.y);
int index = xAmount;
// Outer loop
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index 83ab1151a9..66f56f9407 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -89,8 +89,7 @@ Scene::~Scene() {
}
void Scene::restrictScene() {
- _sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
- _vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
+ _sceneSurface.create(*_vm->_screen, Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT));
}
void Scene::clearVocab() {
@@ -517,7 +516,7 @@ void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
if (_posAdjust != Common::Point(0, 0))
warning("Adjust used %d %d", _posAdjust.x, _posAdjust.y);
// Copy background for the dirty areas to the screen
- _dirtyAreas.copy(&_backgroundSurface, &_vm->_screen, _posAdjust);
+ _dirtyAreas.copy(&_backgroundSurface, _vm->_screen, _posAdjust);
// Handle dirty areas for foreground objects
_spriteSlots.setDirtyAreas();
@@ -528,11 +527,11 @@ void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
_spriteSlots.drawSprites(&_sceneSurface);
// Draw text elements onto the view
- _textDisplay.draw(&_vm->_screen);
+ _textDisplay.draw(_vm->_screen);
if (transitionType) {
// Fading in the screen
- _vm->_screen.transition(transitionType, surfaceFlag);
+ _vm->_screen->transition(transitionType, surfaceFlag);
_vm->_sound->startQueuedCommands();
} else {
// Copy dirty areas to the screen
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index 7b0e64c1fe..5323178ec7 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -242,13 +242,13 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
int height = _height;
if (!bgSurface.getPixels() || (bgSurface.w != width) || (bgSurface.h != height)) {
- bgSurface.setSize(width, height);
+ bgSurface.create(width, height);
}
if (_depthStyle == 2)
width >>= 2;
if (!depthSurface.getPixels()) {
- depthSurface.setSize(width, height);
+ depthSurface.create(width, height);
}
loadCodes(depthSurface, variant);
@@ -288,7 +288,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
assert(asset && _depthStyle != 2);
MSprite *spr = asset->getFrame(si._frameNumber);
- bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,
+ bgSurface.copyFrom(*spr, si._position, si._depth, &depthSurface,
si._scale, false, spr->getTransparencyIndex());
}
@@ -455,7 +455,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
newHeight = tileCount * tileHeight;
if (bgSurface.w != newWidth || bgSurface.h != newHeight)
- bgSurface.setSize(newWidth, newHeight);
+ bgSurface.create(newWidth, newHeight);
// --------------------------------------------------------------------------------
@@ -477,7 +477,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
//debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize);
- newTile->empty();
+ newTile->clear();
byte *compressedTileData = new byte[compressedTileDataSize];
@@ -503,7 +503,8 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
TileSetIterator tile = tileSet.begin();
for (int i = 0; i < tileIndex; i++)
++tile;
- ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight));
+
+ bgSurface.blitFrom(*(*tile).get(), Common::Point(x * tileWidth, y * tileHeight));
((*tile).get())->free();
}
}
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 90fbbe7e2a..05f9de61e2 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -69,7 +69,6 @@ void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
_active = true;
}
-
void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) {
int width, height;
Scene &scene = _vm->_game->_scene;
@@ -215,12 +214,13 @@ void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common:
Common::Point destPos(srcBounds.left, srcBounds.top);
if ((*this)[i]._active && bounds.isValidRect()) {
- srcSurface->copyTo(destSurface, bounds, destPos);
+ destSurface->blitFrom(*srcSurface, bounds, destPos);
}
}
}
void DirtyAreas::copyToScreen() {
+/*
for (uint i = 0; i < size(); ++i) {
const Common::Rect &bounds = (*this)[i]._bounds;
@@ -229,9 +229,10 @@ void DirtyAreas::copyToScreen() {
continue;
if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) {
- _vm->_screen.copyRectToScreen(bounds);
+ _vm->_screen->copyRectToScreen(bounds);
}
}
+ */
}
void DirtyAreas::reset() {
@@ -554,38 +555,17 @@ void ScreenObjects::synchronize(Common::Serializer &s) {
/*------------------------------------------------------------------------*/
-ScreenSurface::ScreenSurface() {
+Screen::Screen(): Graphics::Screen(), MSurface() {
+ // Create the screen surface separately on another surface, since the screen
+ // surface will be subject to change as the clipping area is altered
+ _rawSurface.create(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
+ resetClipBounds();
+
_shakeCountdown = -1;
_random = 0x4D2;
- _surfacePixels = nullptr;
-}
-
-void ScreenSurface::init() {
- // Set the size for the screen
- setSize(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
-
- // Store a copy of the raw pixels pointer for the screen, since the surface
- // itself may be later changed to only a subset of the screen
- _surfacePixels = (byte *)getPixels();
- _freeFlag = false;
-}
-
-ScreenSurface::~ScreenSurface() {
- ::free(_surfacePixels);
}
-void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) {
- const byte *buf = getBasePtr(bounds.left, bounds.top);
-
- Common::Rect destBounds = bounds;
- destBounds.translate(_clipBounds.left, _clipBounds.top);
-
- if (bounds.width() != 0 && bounds.height() != 0)
- g_system->copyRectToScreen(buf, this->pitch, destBounds.left, destBounds.top,
- destBounds.width(), destBounds.height());
-}
-
-void ScreenSurface::updateScreen() {
+void Screen::update() {
if (_shakeCountdown >= 0) {
_random = _random * 5 + 1;
int offset = (_random >> 8) & 3;
@@ -596,27 +576,42 @@ void ScreenSurface::updateScreen() {
// offset width shown at the very right. The offset changes to give
// an effect of shaking the screen
offset *= 4;
- const byte *buf = getBasePtr(offset, 0);
- g_system->copyRectToScreen(buf, this->pitch, 0, 0,
- this->pitch - offset, this->h);
+ const byte *buf = (const byte *)getBasePtr(offset, 0);
+ g_system->copyRectToScreen(buf, this->pitch, 0, 0, this->pitch - offset, this->h);
if (offset > 0)
- g_system->copyRectToScreen(this->pixels, this->pitch,
+ g_system->copyRectToScreen(getPixels(), this->pitch,
this->pitch - offset, 0, offset, this->h);
+ return;
}
- g_system->updateScreen();
+ // Reset any clip bounds if active whilst the screen is updated
+ Common::Rect clipBounds = getClipBounds();
+ resetClipBounds();
+
+ // Update the screen
+ Graphics::Screen::update();
+
+ // Revert back to whatever clipping is active
+ setClipBounds(clipBounds);
}
-void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
+void Screen::transition(ScreenTransition transitionType, bool surfaceFlag) {
Palette &pal = *_vm->_palette;
Scene &scene = _vm->_game->_scene;
byte palData[PALETTE_SIZE];
+ // The original loads the new scene to the screen surface for some of the
+ // transition types like fade out/in, so we need to clear the dirty rects so
+ // it doesn't prematurely get blitted to the physical screen before fade out
+ Common::Rect clipBounds = getClipBounds();
+ clearDirtyRects();
+
switch (transitionType) {
case kTransitionFadeIn:
- case kTransitionFadeOutIn:
+ case kTransitionFadeOutIn: {
Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0);
Common::fill(&pal._colorFlags[0], &pal._colorFlags[3], false);
+ resetClipBounds();
if (transitionType == kTransitionFadeOutIn) {
// Fade out
@@ -628,9 +623,11 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
Common::fill(&palData[0], &palData[PALETTE_SIZE], 0);
pal.setFullPalette(palData);
- copyRectToScreen(getBounds());
+ markAllDirty();
+ update();
pal.fadeIn(palData, pal._mainPalette, 0, 256, 0, 1, 1, 16);
break;
+ }
case kTransitionBoxInBottomLeft:
case kTransitionBoxInBottomRight:
@@ -666,19 +663,13 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
// Quick transitions
break;
}
-}
-void ScreenSurface::setClipBounds(const Common::Rect &r) {
- _clipBounds = r;
- setPixels(_surfacePixels + pitch * r.top + r.left, r.width(), r.height());
- this->pitch = MADS_SCREEN_WIDTH;
+ // Reset clipping
+ markAllDirty();
+ setClipBounds(clipBounds);
}
-void ScreenSurface::resetClipBounds() {
- setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
-}
-
-void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entrySide,
+void Screen::panTransition(MSurface &newScreen, byte *palData, int entrySide,
const Common::Point &srcPos, const Common::Point &destPos,
ThroughBlack throughBlack, bool setPalette, int numTicks) {
EventsManager &events = *_vm->_events;
@@ -735,8 +726,6 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS
srcPos.x + xAt + 1, srcPos.y + size.y));
}
- copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y));
-
// Slight delay
events.pollEvents();
g_system->delayMillis(1);
@@ -747,16 +736,18 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS
}
if (throughBlack == THROUGH_BLACK2) {
+ /*
Common::Rect r(srcPos.x, srcPos.y, srcPos.x + size.x, srcPos.y + size.y);
copyRectToSurface(newScreen, destPos.x, destPos.y, r);
copyRectToScreen(r);
+ */
}
}
/**
* Translates the current screen from the old palette to the new palette
*/
-void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap) {
+void Screen::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap) {
Palette &palette = *_vm->_palette;
byte oldPalette[PALETTE_SIZE];
byte oldMap[PALETTE_COUNT];
@@ -775,7 +766,7 @@ void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteM
destP += 2 * RGB_SIZE;
}
- Common::Rect oldClip = _clipBounds;
+ Common::Rect oldClip = getClipBounds();
resetClipBounds();
copyRectTranslate(*this, oldMap, Common::Point(0, 0),
@@ -790,7 +781,7 @@ void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteM
* Palettes consist of 128 RGB entries for the foreground and background
* respectively, with the two interleaved together. So the start
*/
-void ScreenSurface::swapPalette(const byte *palData, byte swapTable[PALETTE_COUNT],
+void Screen::swapPalette(const byte *palData, byte swapTable[PALETTE_COUNT],
bool foreground) {
int start = foreground ? 1 : 0;
const byte *dynamicList = &palData[start * RGB_SIZE];
@@ -815,5 +806,12 @@ void ScreenSurface::swapPalette(const byte *palData, byte swapTable[PALETTE_COUN
}
}
+void Screen::setClipBounds(const Common::Rect &r) {
+ create(_rawSurface, r);
+}
+
+void Screen::resetClipBounds() {
+ setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+}
} // End of namespace MADS
diff --git a/engines/mads/screen.h b/engines/mads/screen.h
index d910e88633..626080580e 100644
--- a/engines/mads/screen.h
+++ b/engines/mads/screen.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/array.h"
+#include "graphics/screen.h"
#include "mads/msurface.h"
#include "mads/action.h"
@@ -207,11 +208,10 @@ public:
void synchronize(Common::Serializer &s);
};
-class ScreenSurface : public MSurface {
+class Screen : virtual public Graphics::Screen, virtual public MSurface {
private:
uint16 _random;
- byte *_surfacePixels;
- Common::Rect _clipBounds;
+ MSurface _rawSurface;
void panTransition(MSurface &newScreen, byte *palData, int entrySide,
const Common::Point &srcPos, const Common::Point &destPos,
@@ -226,36 +226,40 @@ public:
/**
* Constructor
*/
- ScreenSurface();
+ Screen();
/**
* Destructor
*/
- ~ScreenSurface();
+ virtual ~Screen() {}
/**
- * Initialize the surface
+ * Updates the physical screen with contents of the internal surface
*/
- void init();
+ virtual void update();
/**
- * Copys an area of the screen surface to the ScmmVM physical screen buffer
- * @param bounds Area of screen surface to copy
+ * Transition to a new screen with a given effect
*/
- void copyRectToScreen(const Common::Rect &bounds);
+ void transition(ScreenTransition transitionType, bool surfaceFlag);
/**
- * Updates the screen with the contents of the surface
+ * Set the screen drawing area to a sub-section of the real screen
*/
- void updateScreen();
-
- void transition(ScreenTransition transitionType, bool surfaceFlag);
-
void setClipBounds(const Common::Rect &r);
+ /**
+ * Reset back to drawing on the entirety of the screen
+ */
void resetClipBounds();
- const Common::Rect &getClipBounds() { return _clipBounds; }
+ /**
+ * Return the current drawing/clip area
+ */
+ const Common::Rect getClipBounds() const {
+ const Common::Point pt = getOffsetFromOwner();
+ return Common::Rect(pt.x, pt.y, pt.x + this->w, pt.y + this->h);
+ }
};
} // End of namespace MADS
diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp
index 50b37de7ea..2afe089d4a 100644
--- a/engines/mads/sequence.cpp
+++ b/engines/mads/sequence.cpp
@@ -237,8 +237,8 @@ bool SequenceList::loadSprites(int seqIndex) {
if ((seqEntry._flags != 0) || (seqEntry._dynamicHotspotIndex >= 0)) {
SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex];
MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1);
- int width = frame->getWidth() * seqEntry._scale / 200;
- int height = frame->getHeight() * seqEntry._scale / 100;
+ int width = frame->w * seqEntry._scale / 200;
+ int height = frame->h * seqEntry._scale / 100;
Common::Point pt = spriteSlot._position;
// Handle sprite movement, if present
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index 0a1c0b710d..fc8ddf22d2 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -59,10 +59,10 @@ MSprite::MSprite() : MSurface() {
}
MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette,
- const Common::Rect &bounds)
- : MSurface(bounds.width(), bounds.height()),
- _offset(Common::Point(bounds.left, bounds.top)), _transparencyIndex(TRANSPARENT_COLOR_INDEX) {
+ const Common::Rect &bounds): MSurface(), _transparencyIndex(TRANSPARENT_COLOR_INDEX),
+ _offset(Common::Point(bounds.left, bounds.top)) {
// Load the sprite data
+ create(bounds.width(), bounds.height());
loadSprite(source, palette);
}
@@ -74,8 +74,8 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
byte *outp, *lineStart;
bool newLine = false;
- outp = getData();
- lineStart = getData();
+ outp = getPixels();
+ lineStart = getPixels();
int spriteSize = this->w * this->h;
byte transIndex = getTransparencyIndex();
Common::fill(outp, outp + spriteSize, transIndex);
@@ -84,7 +84,7 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
byte cmd1, cmd2, count, pixel;
if (newLine) {
- outp = lineStart + getWidth();
+ outp = lineStart + this->w;
lineStart = outp;
newLine = false;
}
@@ -126,7 +126,7 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
// Do a final iteration over the sprite to convert it's pixels to
// the final positions in the main palette
spriteSize = this->w * this->h;
- for (outp = getData(); spriteSize > 0; --spriteSize, ++outp) {
+ for (outp = getPixels(); spriteSize > 0; --spriteSize, ++outp) {
if (*outp != transIndex)
*outp = palette[*outp]._palIndex;
}
@@ -257,12 +257,12 @@ void SpriteSlots::drawBackground() {
}
if (spriteSlot._depth <= 1) {
- frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
+ scene._backgroundSurface.transBlitFrom(*frame, pt, frame->getTransparencyIndex());
} else if (scene._depthStyle == 0) {
- scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface,
+ scene._backgroundSurface.copyFrom(*frame, pt, spriteSlot._depth, &scene._depthSurface,
-1, false, frame->getTransparencyIndex());
} else {
- frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
+ scene._backgroundSurface.transBlitFrom(*frame, pt, frame->getTransparencyIndex());
}
}
}
@@ -319,7 +319,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
if ((slot._scale < 100) && (slot._scale != -1)) {
// Scaled drawing
- s->copyFrom(sprite, slot._position, slot._depth, &scene._depthSurface,
+ s->copyFrom(*sprite, slot._position, slot._depth, &scene._depthSurface,
slot._scale, flipped, sprite->getTransparencyIndex());
} else {
int xp, yp;
@@ -334,7 +334,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
if (slot._depth > 1) {
// Draw the frame with depth processing
- s->copyFrom(sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
+ s->copyFrom(*sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
-1, flipped, sprite->getTransparencyIndex());
} else {
MSurface *spr = sprite;
@@ -344,7 +344,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
}
// No depth, so simply draw the image
- spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex());
+ s->transBlitFrom(*spr, Common::Point(xp, yp), sprite->getTransparencyIndex());
// Free sprite if it was a flipped one
if (flipped) {
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
index e4b09ff54c..8f7cb0a24b 100644
--- a/engines/mads/user_interface.cpp
+++ b/engines/mads/user_interface.cpp
@@ -112,7 +112,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
} else {
// Copy area
- userInterface._surface.copyTo(&userInterface, dirtyArea._bounds,
+ userInterface.blitFrom(userInterface._surface, dirtyArea._bounds,
Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
}
}
@@ -155,7 +155,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
if (slot._segmentId == IMG_SPINNING_OBJECT) {
MSprite *sprite = asset->getFrame(frameNumber - 1);
- sprite->copyTo(&userInterface, slot._position,
+ userInterface.transBlitFrom(*sprite, slot._position,
sprite->getTransparencyIndex());
} else {
MSprite *sprite = asset->getFrame(frameNumber - 1);
@@ -185,7 +185,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
// Flag area of screen as needing update
Common::Rect r = dirtyArea._bounds;
r.translate(0, scene._interfaceY);
- _vm->_screen.copyRectToScreen(r);
+ //_vm->_screen->copyRectToScreen(r);
}
}
}
@@ -339,10 +339,10 @@ UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm),
Common::fill(&_categoryIndexes[0], &_categoryIndexes[7], 0);
// Map the user interface to the bottom of the game's screen surface
- byte *pData = _vm->_screen.getBasePtr(0, MADS_SCENE_HEIGHT);
- setPixels(pData, MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+ create(*_vm->_screen, Common::Rect(0, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
+ MADS_SCREEN_HEIGHT));
- _surface.setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+ _surface.create(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
}
void UserInterface::load(const Common::String &resName) {
@@ -367,7 +367,7 @@ void UserInterface::load(const Common::String &resName) {
// Read in the surface data
Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1);
- pixelsStream->read(_surface.getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
+ pixelsStream->read(_surface.getPixels(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
delete pixelsStream;
}
@@ -390,7 +390,7 @@ void UserInterface::setup(InputMode inputMode) {
resName += ".INT";
load(resName);
- _surface.copyTo(this);
+ blitFrom(_surface);
}
_vm->_game->_screenObjects._inputMode = inputMode;
@@ -455,9 +455,9 @@ void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
// Copy the specified area
- byte *data = src->getData();
- byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
- byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX;
+ byte *data = src->getPixels();
+ byte *srcPtr = data + (src->w * copyRect.top + copyRect.left);
+ byte *destPtr = (byte *)getPixels() + (destY * this->w) + destX;
for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
// Process each line of the area
@@ -468,8 +468,8 @@ void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
destPtr[xCtr] = srcPtr[xCtr];
}
- srcPtr += src->getWidth();
- destPtr += getWidth();
+ srcPtr += src->w;
+ destPtr += this->w;
}
}
@@ -593,7 +593,7 @@ void UserInterface::scrollbarChanged() {
_uiSlots.add(r);
_uiSlots.draw(false, false);
drawScroller();
- updateRect(r);
+// updateRect(r);
}
void UserInterface::writeVocab(ScrCategory category, int id) {
@@ -1012,7 +1012,7 @@ void UserInterface::selectObject(int invIndex) {
_uiSlots.add(bounds);
_uiSlots.draw(false, false);
drawItemVocabList();
- updateRect(bounds);
+ //updateRect(bounds);
}
}
@@ -1036,7 +1036,7 @@ void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx
_uiSlots.add(bounds);
_uiSlots.draw(false, false);
drawInventoryList();
- updateRect(bounds);
+ //updateRect(bounds);
_inventoryChanged = false;
if (invList.size() < 2) {
@@ -1052,25 +1052,19 @@ void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx
if (oldIndex >= 0) {
writeVocab(category, oldIndex);
- if (getBounds(category, oldIndex, bounds))
- updateRect(bounds);
+/* if (getBounds(category, oldIndex, bounds))
+ updateRect(bounds); */
}
if (newIndex >= 0) {
writeVocab(category, newIndex);
- if (getBounds(category, newIndex, bounds))
- updateRect(bounds);
+/* if (getBounds(category, newIndex, bounds))
+ updateRect(bounds); */
}
}
}
-void UserInterface::updateRect(const Common::Rect &bounds) {
- Common::Rect r = bounds;
- r.translate(0, MADS_SCENE_HEIGHT);
- _vm->_screen.copyRectToScreen(r);
-}
-
void UserInterface::scrollerChanged() {
warning("TODO: scrollerChanged");
}
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index 60cc1f736d..9232dc1bb1 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -190,8 +190,6 @@ private:
* Draw a UI textual element
*/
void writeVocab(ScrCategory category, int id);
-
- void updateRect(const Common::Rect &bounds);
public:
MSurface _surface;
UISlots _uiSlots;
diff --git a/engines/metaengine.h b/engines/metaengine.h
index 41f3ec4cba..e7bfebab71 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -96,6 +96,9 @@ public:
/**
* Return a list of all save states associated with the given target.
*
+ * The returned list is guaranteed to be sorted by slot numbers. That
+ * means smaller slot numbers are always stored before bigger slot numbers.
+ *
* The caller has to ensure that this (Meta)Engine is responsible
* for the specified target (by using findGame on it respectively
* on the associated gameid from the relevant ConfMan entry, if present).
diff --git a/engines/mohawk/configure.engine b/engines/mohawk/configure.engine
index 47402c4560..ccb9499ef0 100644
--- a/engines/mohawk/configure.engine
+++ b/engines/mohawk/configure.engine
@@ -1,6 +1,6 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books"
+add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books" "highres"
add_engine cstime "Where in Time is Carmen Sandiego?" no
add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit"
-add_engine myst "Myst" no
+add_engine myst "Myst" yes
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 9b5bae78be..fd79e53b07 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -63,6 +63,8 @@ MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes));
registerCmd("cache", WRAP_METHOD(MystConsole, Cmd_Cache));
registerCmd("resources", WRAP_METHOD(MystConsole, Cmd_Resources));
+ registerCmd("quickTest", WRAP_METHOD(MystConsole, Cmd_QuickTest));
+ registerVar("show_resource_rects", &_vm->_showResourceRects);
}
MystConsole::~MystConsole() {
@@ -119,7 +121,7 @@ static const uint16 default_start_card[12] = {
10000,
2000,
5038,
- 2, // TODO: Should be 1?
+ 1,
1,
6122,
4134,
@@ -329,6 +331,44 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) {
return true;
}
+bool MystConsole::Cmd_QuickTest(int argc, const char **argv) {
+ // Go through all the ages, all the views and click random stuff
+ for (uint i = 0; i < ARRAYSIZE(mystStackNames); i++) {
+ if (i == 2 || i == 5 || i == 9 || i == 10) continue;
+ debug("Loading stack %s", mystStackNames[i]);
+ _vm->changeToStack(i, default_start_card[i], 0, 0);
+
+ Common::Array<uint16> ids = _vm->getResourceIDList(ID_VIEW);
+ for (uint j = 0; j < ids.size(); j++) {
+ if (ids[j] == 4632) continue;
+
+ debug("Loading card %d", ids[j]);
+ _vm->changeToCard(ids[j], kTransitionCopy);
+
+ _vm->_video->updateMovies();
+ _vm->_scriptParser->runPersistentScripts();
+ _vm->_system->updateScreen();
+
+ int16 resIndex = _vm->_rnd->getRandomNumber(_vm->_resources.size()) - 1;
+ if (resIndex >= 0 && _vm->_resources[resIndex]->isEnabled()) {
+ _vm->_resources[resIndex]->handleMouseDown();
+ _vm->_resources[resIndex]->handleMouseUp();
+ }
+
+ _vm->_video->updateMovies();
+ _vm->_scriptParser->runPersistentScripts();
+ _vm->_system->updateScreen();
+
+ if (_vm->getCurStack() != i) {
+ // Clicking may have linked us to another age
+ _vm->changeToStack(i, default_start_card[i], 0, 0);
+ }
+ }
+ }
+
+ return true;
+}
+
#endif // ENABLE_MYST
#ifdef ENABLE_RIVEN
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index af01c0d1e0..dc40049a89 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -55,6 +55,7 @@ private:
bool Cmd_DisableInitOpcodes(int argc, const char **argv);
bool Cmd_Cache(int argc, const char **argv);
bool Cmd_Resources(int argc, const char **argv);
+ bool Cmd_QuickTest(int argc, const char **argv);
};
#endif
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 926c296257..a64d7ff7df 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -26,6 +26,7 @@
#include "common/savefile.h"
#include "common/system.h"
#include "common/textconsole.h"
+#include "common/translation.h"
#include "mohawk/livingbooks.h"
@@ -35,6 +36,7 @@
#ifdef ENABLE_MYST
#include "mohawk/myst.h"
+#include "mohawk/myst_state.h"
#endif
#ifdef ENABLE_RIVEN
@@ -52,7 +54,7 @@ struct MohawkGameDescription {
};
const char* MohawkEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
uint32 MohawkEngine::getFeatures() const {
@@ -159,10 +161,24 @@ static const char *directoryGlobs[] = {
0
};
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_PLAY_MYST_FLYBY,
+ {
+ _s("Play the Myst fly by movie"),
+ _s("The Myst fly by movie was not played by the original engine."),
+ "playmystflyby",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
class MohawkMetaEngine : public AdvancedMetaEngine {
public:
- MohawkMetaEngine() : AdvancedMetaEngine(Mohawk::gameDescriptions, sizeof(Mohawk::MohawkGameDescription), mohawkGames) {
- _singleid = "mohawk";
+ MohawkMetaEngine() : AdvancedMetaEngine(Mohawk::gameDescriptions, sizeof(Mohawk::MohawkGameDescription), mohawkGames, optionsList) {
+ _singleId = "mohawk";
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
@@ -184,13 +200,18 @@ public:
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const { return 999; }
virtual void removeSaveState(const char *target, int slot) const;
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
bool MohawkMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves)
|| (f == kSupportsLoadingDuringStartup)
- || (f == kSupportsDeleteSave);
+ || (f == kSupportsDeleteSave)
+ || (f == kSavesSupportMetaInfo)
+ || (f == kSavesSupportThumbnail)
+ || (f == kSavesSupportCreationDate)
+ || (f == kSavesSupportPlayTime);
}
SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
@@ -198,12 +219,15 @@ SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
SaveStateList saveList;
// Loading games is only supported in Myst/Riven currently.
+#ifdef ENABLE_MYST
if (strstr(target, "myst")) {
- filenames = g_system->getSavefileManager()->listSavefiles("*.mys");
+ filenames = Mohawk::MystGameState::generateSaveGameList();
for (uint32 i = 0; i < filenames.size(); i++)
saveList.push_back(SaveStateDescriptor(i, filenames[i]));
- } else if (strstr(target, "riven")) {
+ } else
+#endif
+ if (strstr(target, "riven")) {
filenames = g_system->getSavefileManager()->listSavefiles("*.rvn");
for (uint32 i = 0; i < filenames.size(); i++)
@@ -215,15 +239,35 @@ SaveStateList MohawkMetaEngine::listSaves(const char *target) const {
void MohawkMetaEngine::removeSaveState(const char *target, int slot) const {
// Removing saved games is only supported in Myst/Riven currently.
+#ifdef ENABLE_MYST
if (strstr(target, "myst")) {
- Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("*.mys");
- g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
- } else if (strstr(target, "riven")) {
+ Common::StringArray filenames = Mohawk::MystGameState::generateSaveGameList();
+ Mohawk::MystGameState::deleteSave(filenames[slot]);
+ } else
+#endif
+ if (strstr(target, "riven")) {
Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("*.rvn");
g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
}
}
+SaveStateDescriptor MohawkMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+#ifdef ENABLE_MYST
+ if (strstr(target, "myst")) {
+ Common::StringArray filenames = Mohawk::MystGameState::generateSaveGameList();
+
+ if (slot >= (int) filenames.size()) {
+ return SaveStateDescriptor();
+ }
+
+ return Mohawk::MystGameState::querySaveMetaInfos(filenames[slot]);
+ } else
+#endif
+ {
+ return SaveStateDescriptor();
+ }
+}
+
bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Mohawk::MohawkGameDescription *gd = (const Mohawk::MohawkGameDescription *)desc;
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index 97d2932d57..7941a0d51a 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -22,6 +22,13 @@
namespace Mohawk {
+#define GAMEOPTION_PLAY_MYST_FLYBY GUIO_GAMEOPTIONS1
+
+#define GUI_OPTIONS_MYST GUIO3(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOMIDI)
+#define GUI_OPTIONS_MYST_ME GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOMIDI, GAMEOPTION_PLAY_MYST_FLYBY)
+#define GUI_OPTIONS_MYST_DEMO GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD)
+#define GUI_OPTIONS_MYST_MAKING_OF GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD)
+
static const MohawkGameDescription gameDescriptions[] = {
// Myst
// English Windows 3.11
@@ -34,7 +41,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -52,7 +59,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO | ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_DEMO
},
GType_MYST,
GF_DEMO,
@@ -70,7 +77,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -88,7 +95,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -106,7 +113,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -124,7 +131,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::IT_ITA,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -142,7 +149,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::JA_JPN,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -160,7 +167,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -178,7 +185,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_MAKING_OF
},
GType_MAKINGOF,
0,
@@ -196,7 +203,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::JA_JPN,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_MAKING_OF
},
GType_MAKINGOF,
0,
@@ -214,7 +221,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_ME
},
GType_MYST,
GF_ME,
@@ -232,7 +239,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::DE_DEU,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_ME
},
GType_MYST,
GF_ME,
@@ -250,7 +257,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_ME
},
GType_MYST,
GF_ME,
@@ -268,7 +275,7 @@ static const MohawkGameDescription gameDescriptions[] = {
Common::PL_POL,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_ME
},
GType_MYST,
GF_ME,
@@ -2698,7 +2705,7 @@ static const MohawkGameDescription fallbackDescs[] = {
Common::UNK_LANG,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST
},
GType_MYST,
0,
@@ -2713,7 +2720,7 @@ static const MohawkGameDescription fallbackDescs[] = {
Common::UNK_LANG,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_MAKING_OF
},
GType_MAKINGOF,
0,
@@ -2728,7 +2735,7 @@ static const MohawkGameDescription fallbackDescs[] = {
Common::UNK_LANG,
Common::kPlatformWindows,
ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
+ GUI_OPTIONS_MYST_ME
},
GType_MYST,
GF_ME,
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index ffc455286f..6c6ae9e77f 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -24,6 +24,7 @@
#include "mohawk/dialogs.h"
#include "gui/gui-manager.h"
+#include "gui/saveload.h"
#include "gui/ThemeEngine.h"
#include "gui/widget.h"
#include "common/system.h"
@@ -82,35 +83,47 @@ enum {
kWaterCmd = 'WATR',
kDropCmd = 'DROP',
kMapCmd = 'SMAP',
- kMenuCmd = 'MENU'
+ kMenuCmd = 'MENU',
+ kSaveCmd = 'SAVE',
+ kLoadCmd = 'LOAD',
+ kQuitCmd = 'QUIT'
};
#ifdef ENABLE_MYST
-MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) {
+MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::Dialog(0, 0, 360, 200), _vm(vm) {
// I18N: Option for fast scene switching
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
- _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 220, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
+ _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 220, 15, _("~T~ransitions Enabled"), 0, kTransCmd);
// I18N: Drop book page
_dropPageButton = new GUI::ButtonWidget(this, 15, 60, 100, 25, _("~D~rop Page"), 0, kDropCmd);
// Myst ME only has maps
if (_vm->getFeatures() & GF_ME)
- _showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("~S~how Map"), 0, kMapCmd);
+ _showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Show ~M~ap"), 0, kMapCmd);
else
_showMapButton = 0;
// Myst demo only has a menu
if (_vm->getFeatures() & GF_DEMO)
- _returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("~M~ain Menu"), 0, kMenuCmd);
+ _returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Main Men~u~"), 0, kMenuCmd);
else
_returnToMenuButton = 0;
+ _loadButton = new GUI::ButtonWidget(this, 245, 25, 100, 25, _("~L~oad"), 0, kLoadCmd);
+ _saveButton = new GUI::ButtonWidget(this, 245, 60, 100, 25, _("~S~ave"), 0, kSaveCmd);
+ new GUI::ButtonWidget(this, 245, 95, 100, 25, _("~Q~uit"), 0, kQuitCmd);
+
new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd);
new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd);
+
+ _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
+ _saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
}
MystOptionsDialog::~MystOptionsDialog() {
+ delete _loadDialog;
+ delete _saveDialog;
}
void MystOptionsDialog::open() {
@@ -133,6 +146,44 @@ void MystOptionsDialog::open() {
_zipModeCheckbox->setState(_vm->_gameState->_globals.zipMode);
_transitionsCheckbox->setState(_vm->_gameState->_globals.transitions);
+
+ _loadButton->setEnabled(_vm->canLoadGameStateCurrently());
+ _saveButton->setEnabled(_vm->canSaveGameStateCurrently());
+}
+
+void MystOptionsDialog::save() {
+ int slot = _saveDialog->runModalWithCurrentTarget();
+
+ if (slot >= 0) {
+ Common::String result(_saveDialog->getResultString());
+ if (result.empty()) {
+ // If the user was lazy and entered no save name, come up with a default name.
+ result = _saveDialog->createDefaultSaveDescription(slot);
+ }
+
+ _vm->saveGameState(slot, result);
+ close();
+ }
+}
+
+void MystOptionsDialog::load() {
+ int slot = _loadDialog->runModalWithCurrentTarget();
+
+ if (slot >= 0) {
+ _vm->loadGameState(slot);
+ close();
+ }
+}
+
+void MystOptionsDialog::reflowLayout() {
+ const int screenW = g_system->getOverlayWidth();
+ const int screenH = g_system->getOverlayHeight();
+
+ // Center the dialog
+ _x = (screenW - getWidth()) / 2;
+ _y = (screenH - getHeight()) / 2;
+
+ Dialog::reflowLayout();
}
void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
@@ -144,18 +195,39 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
case kMapCmd:
_vm->_needsShowMap = true;
close();
- break;
+ break;
case kMenuCmd:
_vm->_needsShowDemoMenu = true;
close();
- break;
+ break;
+ case kLoadCmd:
+ load();
+ break;
+ case kSaveCmd:
+ save();
+ break;
+ case kQuitCmd: {
+ if (_vm->getGameType() != GType_MAKINGOF) {
+ _vm->_needsShowCredits = true;
+ } else {
+ Common::Event eventQ;
+ eventQ.type = Common::EVENT_QUIT;
+ g_system->getEventManager()->pushEvent(eventQ);
+ }
+ close();
+ }
+ break;
case GUI::kOKCmd:
_vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState();
_vm->_gameState->_globals.transitions = _transitionsCheckbox->getState();
- GUI::OptionsDialog::handleCommand(sender, cmd, data);
+ setResult(1);
+ close();
+ break;
+ case GUI::kCloseCmd:
+ close();
break;
default:
- GUI::OptionsDialog::handleCommand(sender, cmd, data);
+ GUI::Dialog::handleCommand(sender, cmd, data);
}
}
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index 7470cd3acd..bc25c72a43 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -32,6 +32,10 @@
#include "gui/widget.h"
#include "gui/widgets/list.h"
+namespace GUI {
+class SaveLoadChooser;
+}
+
namespace Mohawk {
class MohawkEngine;
@@ -70,20 +74,32 @@ public:
class MohawkEngine_Myst;
-class MystOptionsDialog : public GUI::OptionsDialog {
+class MystOptionsDialog : public GUI::Dialog {
public:
MystOptionsDialog(MohawkEngine_Myst *vm);
~MystOptionsDialog();
void open();
+ virtual void reflowLayout() override;
virtual void handleCommand(GUI::CommandSender*, uint32, uint32);
private:
MohawkEngine_Myst *_vm;
+
GUI::CheckboxWidget *_zipModeCheckbox;
GUI::CheckboxWidget *_transitionsCheckbox;
+
GUI::ButtonWidget *_dropPageButton;
GUI::ButtonWidget *_showMapButton;
GUI::ButtonWidget *_returnToMenuButton;
+
+ GUI::ButtonWidget *_loadButton;
+ GUI::ButtonWidget *_saveButton;
+
+ GUI::SaveLoadChooser *_loadDialog;
+ GUI::SaveLoadChooser *_saveDialog;
+
+ void save();
+ void load();
};
#endif
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index b6a6c27329..c16fab9131 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -66,38 +66,22 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
DebugMan.addDebugChannel(kDebugHelp, "Help", "Track Help File (HELP) Parsing");
DebugMan.addDebugChannel(kDebugCache, "Cache", "Track Resource Cache Accesses");
- // Engine tweaks
- // Disabling this makes engine behavior as per
- // original, including bugs, missing bits etc. :)
- _tweaksEnabled = true;
-
_currentCursor = 0;
_mainCursor = kDefaultMystCursor;
_showResourceRects = false;
_curCard = 0;
_needsUpdate = false;
+ _canSafelySaveLoad = false;
_curResource = -1;
- _hoverResource = 0;
- _dragResource = 0;
-
- _gfx = NULL;
- _console = NULL;
- _scriptParser = NULL;
- _gameState = NULL;
- _loadDialog = NULL;
- _optionsDialog = NULL;
-
- _cursorHintCount = 0;
- _cursorHints = NULL;
-
- _prevStack = NULL;
-
- _view.conditionalImageCount = 0;
- _view.conditionalImages = NULL;
- _view.soundList = NULL;
- _view.soundListVolume = NULL;
- _view.scriptResCount = 0;
- _view.scriptResources = NULL;
+ _hoverResource = nullptr;
+
+ _gfx = nullptr;
+ _console = nullptr;
+ _scriptParser = nullptr;
+ _gameState = nullptr;
+ _optionsDialog = nullptr;
+
+ _prevStack = nullptr;
}
MohawkEngine_Myst::~MohawkEngine_Myst() {
@@ -107,20 +91,12 @@ MohawkEngine_Myst::~MohawkEngine_Myst() {
delete _console;
delete _scriptParser;
delete _gameState;
- delete _loadDialog;
delete _optionsDialog;
delete _prevStack;
delete _rnd;
- delete[] _cursorHints;
-
- delete[] _view.conditionalImages;
- delete[] _view.scriptResources;
-
for (uint32 i = 0; i < _resources.size(); i++)
delete _resources[i];
-
- _resources.clear();
}
// Uses cached data objects in preference to disk access
@@ -138,7 +114,11 @@ Common::SeekableReadStream *MohawkEngine_Myst::getResource(uint32 tag, uint16 id
}
error("Could not find a \'%s\' resource with ID %04x", tag2str(tag), id);
- return NULL;
+ return nullptr;
+}
+
+Common::Array<uint16> MohawkEngine_Myst::getResourceIDList(uint32 type) const {
+ return _mhk[0]->getResourceIDList(type);
}
void MohawkEngine_Myst::cachePreload(uint32 tag, uint16 id) {
@@ -242,7 +222,6 @@ Common::Error MohawkEngine_Myst::run() {
_gfx = new MystGraphics(this);
_console = new MystConsole(this);
_gameState = new MystGameState(this, _saveFileMan);
- _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
_optionsDialog = new MystOptionsDialog(this);
_cursor = new MystCursorManager(this);
_rnd = new Common::RandomSource("myst");
@@ -251,9 +230,9 @@ Common::Error MohawkEngine_Myst::run() {
_cursor->showCursor();
// Load game from launcher/command line if requested
- if (ConfMan.hasKey("save_slot") && canLoadGameStateCurrently()) {
+ if (ConfMan.hasKey("save_slot") && hasGameSaveSupport()) {
uint32 gameToLoad = ConfMan.getInt("save_slot");
- Common::StringArray savedGamesList = _gameState->generateSaveGameList();
+ Common::StringArray savedGamesList = MystGameState::generateSaveGameList();
if (gameToLoad > savedGamesList.size())
error ("Could not find saved game");
_gameState->load(savedGamesList[gameToLoad]);
@@ -284,7 +263,7 @@ Common::Error MohawkEngine_Myst::run() {
_needsUpdate = _video->updateMovies();
_scriptParser->runPersistentScripts();
- while (_eventMan->pollEvent(event)) {
+ while (pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE: {
_needsUpdate = true;
@@ -324,17 +303,15 @@ Common::Error MohawkEngine_Myst::run() {
case Common::KEYCODE_SPACE:
pauseGame();
break;
- case Common::KEYCODE_F4:
- _showResourceRects = !_showResourceRects;
- if (_showResourceRects)
- drawResourceRects();
- break;
case Common::KEYCODE_F5:
_needsPageDrop = false;
_needsShowMap = false;
_needsShowDemoMenu = false;
+ _needsShowCredits = false;
+ _canSafelySaveLoad = true;
runDialog(*_optionsDialog);
+ _canSafelySaveLoad = false;
if (_needsPageDrop) {
dropPage();
@@ -350,6 +327,12 @@ Common::Error MohawkEngine_Myst::run() {
changeToStack(kDemoStack, 2002, 0, 0);
_needsShowDemoMenu = false;
}
+
+ if (_needsShowCredits) {
+ _cursor->hideCursor();
+ changeToStack(kCreditsStack, 10000, 0, 0);
+ _needsShowCredits = false;
+ }
break;
default:
break;
@@ -372,6 +355,15 @@ Common::Error MohawkEngine_Myst::run() {
return Common::kNoError;
}
+bool MohawkEngine_Myst::pollEvent(Common::Event &event) {
+ // Saving / Loading is allowed from the GMM only when the main event loop is running
+ _canSafelySaveLoad = true;
+ bool eventReturned = _eventMan->pollEvent(event);
+ _canSafelySaveLoad = false;
+
+ return eventReturned;
+}
+
bool MohawkEngine_Myst::skippableWait(uint32 duration) {
uint32 end = _system->getMillis() + duration;
bool skipped = false;
@@ -413,6 +405,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
// Fill screen with black and empty cursor
_cursor->setCursor(0);
+ _currentCursor = 0;
if (getFeatures() & GF_ME)
_system->fillScreen(_system->getScreenFormat().RGBToColor(0, 0, 0));
@@ -502,7 +495,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
if (getFeatures() & GF_ME) {
// Play Flyby Entry Movie on Masterpiece Edition.
- const char *flyby = 0;
+ const char *flyby = nullptr;
switch (_curStack) {
case kSeleniticStack:
@@ -512,8 +505,9 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
flyby = "stoneship flyby";
break;
// Myst Flyby Movie not used in Original Masterpiece Edition Engine
+ // We play it when first arriving on Myst, and if the user has chosen so.
case kMystStack:
- if (_tweaksEnabled)
+ if (ConfMan.getBool("playmystflyby") && card == 4134)
flyby = "myst flyby";
break;
case kMechanicalStack:
@@ -539,12 +533,12 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
uint16 MohawkEngine_Myst::getCardBackgroundId() {
uint16 imageToDraw = 0;
- if (_view.conditionalImageCount == 0)
+ if (_view.conditionalImages.size() == 0)
imageToDraw = _view.mainImage;
else {
- for (uint16 i = 0; i < _view.conditionalImageCount; i++) {
+ for (uint16 i = 0; i < _view.conditionalImages.size(); i++) {
uint16 varValue = _scriptParser->getVar(_view.conditionalImages[i].var);
- if (varValue < _view.conditionalImages[i].numStates)
+ if (varValue < _view.conditionalImages[i].values.size())
imageToDraw = _view.conditionalImages[i].values[varValue];
}
}
@@ -586,36 +580,7 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
drawCardBackground();
// Handle sound
- int16 soundAction = 0;
- uint16 soundActionVolume = 0;
-
- if (_view.sound == kMystSoundActionConditional) {
- uint16 soundVarValue = _scriptParser->getVar(_view.soundVar);
- if (soundVarValue >= _view.soundCount)
- warning("Conditional sound variable outside range");
- else {
- soundAction = _view.soundList[soundVarValue];
- soundActionVolume = _view.soundListVolume[soundVarValue];
- }
- } else {
- soundAction = _view.sound;
- soundActionVolume = _view.soundVolume;
- }
-
- if (soundAction == kMystSoundActionContinue)
- debug(2, "Continuing with current sound");
- else if (soundAction == kMystSoundActionChangeVolume) {
- debug(2, "Continuing with current sound, changing volume");
- _sound->changeBackgroundVolumeMyst(soundActionVolume);
- } else if (soundAction == kMystSoundActionStop) {
- debug(2, "Stopping sound");
- _sound->stopBackgroundMyst();
- } else if (soundAction > 0) {
- debug(2, "Playing new sound %d", soundAction);
- _sound->replaceBackgroundMyst(soundAction, soundActionVolume);
- } else {
- error("Unknown sound action %d", soundAction);
- }
+ applySoundBlock(_view.soundBlock);
if (_view.flags & kMystZipDestination)
_gameState->addZipDest(_curStack, card);
@@ -637,15 +602,16 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
// Make sure the screen is updated
if (transition != kNoTransition) {
- if (!_gameState->_globals.transitions)
- transition = kTransitionCopy;
-
- _gfx->runTransition(transition, Common::Rect(544, 333), 10, 0);
+ if (_gameState->_globals.transitions) {
+ _gfx->runTransition(transition, Common::Rect(544, 333), 10, 0);
+ } else {
+ _gfx->copyBackBufferToScreen(Common::Rect(544, 333));
+ _needsUpdate = true;
+ }
}
// Make sure we have the right cursor showing
- _dragResource = 0;
- _hoverResource = 0;
+ _hoverResource = nullptr;
_curResource = -1;
checkCurrentResource();
@@ -671,13 +637,13 @@ void MohawkEngine_Myst::checkCurrentResource() {
// Tell previous resource the mouse is no longer hovering it
if (_hoverResource && !_hoverResource->contains(mouse)) {
_hoverResource->handleMouseLeave();
- _hoverResource = 0;
+ _hoverResource = nullptr;
}
for (uint16 i = 0; i < _resources.size(); i++)
if (_resources[i]->contains(mouse)) {
- if (_hoverResource != _resources[i] && _resources[i]->type == kMystHoverArea) {
- _hoverResource = static_cast<MystResourceType13 *>(_resources[i]);
+ if (_hoverResource != _resources[i] && _resources[i]->type == kMystAreaHover) {
+ _hoverResource = static_cast<MystAreaHover *>(_resources[i]);
_hoverResource->handleMouseEnter();
}
@@ -694,17 +660,17 @@ void MohawkEngine_Myst::checkCurrentResource() {
checkCursorHints();
}
-MystResource *MohawkEngine_Myst::updateCurrentResource() {
+MystArea *MohawkEngine_Myst::updateCurrentResource() {
checkCurrentResource();
if (_curResource >= 0)
return _resources[_curResource];
else
- return 0;
+ return nullptr;
}
void MohawkEngine_Myst::loadCard() {
- debugC(kDebugView, "Loading Card View:");
+ debugC(kDebugView, "Loading Card View: %d", _curCard);
Common::SeekableReadStream *viewStream = getResource(ID_VIEW, _curCard);
@@ -713,21 +679,23 @@ void MohawkEngine_Myst::loadCard() {
debugC(kDebugView, "Flags: 0x%04X", _view.flags);
// The Image Block (Reminiscent of Riven PLST resources)
- _view.conditionalImageCount = viewStream->readUint16LE();
- debugC(kDebugView, "Conditional Image Count: %d", _view.conditionalImageCount);
- if (_view.conditionalImageCount != 0) {
- _view.conditionalImages = new MystCondition[_view.conditionalImageCount];
- for (uint16 i = 0; i < _view.conditionalImageCount; i++) {
+ uint16 conditionalImageCount = viewStream->readUint16LE();
+ debugC(kDebugView, "Conditional Image Count: %d", conditionalImageCount);
+ if (conditionalImageCount != 0) {
+ for (uint16 i = 0; i < conditionalImageCount; i++) {
+ MystCondition conditionalImage;
+
debugC(kDebugView, "\tImage %d:", i);
- _view.conditionalImages[i].var = viewStream->readUint16LE();
- debugC(kDebugView, "\t\tVar: %d", _view.conditionalImages[i].var);
- _view.conditionalImages[i].numStates = viewStream->readUint16LE();
- debugC(kDebugView, "\t\tNumber of States: %d", _view.conditionalImages[i].numStates);
- _view.conditionalImages[i].values = new uint16[_view.conditionalImages[i].numStates];
- for (uint16 j = 0; j < _view.conditionalImages[i].numStates; j++) {
- _view.conditionalImages[i].values[j] = viewStream->readUint16LE();
- debugC(kDebugView, "\t\tState %d -> Value %d", j, _view.conditionalImages[i].values[j]);
+ conditionalImage.var = viewStream->readUint16LE();
+ debugC(kDebugView, "\t\tVar: %d", conditionalImage.var);
+ uint16 numStates = viewStream->readUint16LE();
+ debugC(kDebugView, "\t\tNumber of States: %d", numStates);
+ for (uint16 j = 0; j < numStates; j++) {
+ conditionalImage.values.push_back(viewStream->readUint16LE());
+ debugC(kDebugView, "\t\tState %d -> Value %d", j, conditionalImage.values[j]);
}
+
+ _view.conditionalImages.push_back(conditionalImage);
}
_view.mainImage = 0;
} else {
@@ -736,87 +704,58 @@ void MohawkEngine_Myst::loadCard() {
}
// The Sound Block (Reminiscent of Riven SLST resources)
- _view.sound = viewStream->readSint16LE();
- debugCN(kDebugView, "Sound Control: %d = ", _view.sound);
- if (_view.sound > 0) {
- debugC(kDebugView, "Play new Sound, change volume");
- debugC(kDebugView, "\tSound: %d", _view.sound);
- _view.soundVolume = viewStream->readUint16LE();
- debugC(kDebugView, "\tVolume: %d", _view.soundVolume);
- } else if (_view.sound == kMystSoundActionContinue)
- debugC(kDebugView, "Continue current sound");
- else if (_view.sound == kMystSoundActionChangeVolume) {
- debugC(kDebugView, "Continue current sound, change volume");
- _view.soundVolume = viewStream->readUint16LE();
- debugC(kDebugView, "\tVolume: %d", _view.soundVolume);
- } else if (_view.sound == kMystSoundActionStop) {
- debugC(kDebugView, "Stop sound");
- } else if (_view.sound == kMystSoundActionConditional) {
- debugC(kDebugView, "Conditional sound list");
- _view.soundVar = viewStream->readUint16LE();
- debugC(kDebugView, "\tVar: %d", _view.soundVar);
- _view.soundCount = viewStream->readUint16LE();
- debugC(kDebugView, "\tCount: %d", _view.soundCount);
- _view.soundList = new int16[_view.soundCount];
- _view.soundListVolume = new uint16[_view.soundCount];
-
- for (uint16 i = 0; i < _view.soundCount; i++) {
- _view.soundList[i] = viewStream->readSint16LE();
- debugC(kDebugView, "\t\tCondition %d: Action %d", i, _view.soundList[i]);
- if (_view.soundList[i] == kMystSoundActionChangeVolume || _view.soundList[i] >= 0) {
- _view.soundListVolume[i] = viewStream->readUint16LE();
- debugC(kDebugView, "\t\tCondition %d: Volume %d", i, _view.soundListVolume[i]);
- }
- }
- } else {
- debugC(kDebugView, "Unknown");
- warning("Unknown sound control value in card");
- }
+ _view.soundBlock = readSoundBlock(viewStream);
// Resources that scripts can call upon
- _view.scriptResCount = viewStream->readUint16LE();
- debugC(kDebugView, "Script Resource Count: %d", _view.scriptResCount);
- if (_view.scriptResCount != 0) {
- _view.scriptResources = new MystView::ScriptResource[_view.scriptResCount];
- for (uint16 i = 0; i < _view.scriptResCount; i++) {
- debugC(kDebugView, "\tResource %d:", i);
- _view.scriptResources[i].type = viewStream->readUint16LE();
- debugC(kDebugView, "\t\t Type: %d", _view.scriptResources[i].type);
-
- switch (_view.scriptResources[i].type) {
- case 1:
- debugC(kDebugView, "\t\t\t\t= Image");
- break;
- case 2:
- debugC(kDebugView, "\t\t\t\t= Sound");
- break;
- case 3:
- debugC(kDebugView, "\t\t\t\t= Resource List");
- break;
- default:
- debugC(kDebugView, "\t\t\t\t= Unknown");
- break;
- }
+ uint16 scriptResCount = viewStream->readUint16LE();
+ debugC(kDebugView, "Script Resource Count: %d", scriptResCount);
+ for (uint16 i = 0; i < scriptResCount; i++) {
+ MystView::ScriptResource scriptResource;
+
+ debugC(kDebugView, "\tResource %d:", i);
+ scriptResource.type = (MystView::ScriptResourceType) viewStream->readUint16LE();
+ debugC(kDebugView, "\t\t Type: %d", scriptResource.type);
+
+ switch (scriptResource.type) {
+ case MystView::kResourceImage:
+ debugC(kDebugView, "\t\t\t\t= Image");
+ break;
+ case MystView::kResourceSound:
+ debugC(kDebugView, "\t\t\t\t= Sound");
+ break;
+ case MystView::kResourceSwitch:
+ debugC(kDebugView, "\t\t\t\t= Resource Switch");
+ break;
+ case MystView::kResourceImageNoCache:
+ debugC(kDebugView, "\t\t\t\t= Image - Caching disabled");
+ break;
+ case MystView::kResourceSoundNoCache:
+ debugC(kDebugView, "\t\t\t\t= Sound - Caching disabled");
+ break;
+ default:
+ debugC(kDebugView, "\t\t\t\t= Unknown");
+ warning("Unknown script resource type '%d' in card '%d'", scriptResource.type, _curCard);
+ break;
+ }
- if (_view.scriptResources[i].type == 3) {
- _view.scriptResources[i].var = viewStream->readUint16LE();
- debugC(kDebugView, "\t\t Var: %d", _view.scriptResources[i].var);
- _view.scriptResources[i].count = viewStream->readUint16LE();
- debugC(kDebugView, "\t\t Resource List Count: %d", _view.scriptResources[i].count);
- _view.scriptResources[i].u0 = viewStream->readUint16LE();
- debugC(kDebugView, "\t\t u0: %d", _view.scriptResources[i].u0);
- _view.scriptResources[i].resource_list = new int16[_view.scriptResources[i].count];
-
- for (uint16 j = 0; j < _view.scriptResources[i].count; j++) {
- _view.scriptResources[i].resource_list[j] = viewStream->readSint16LE();
- debugC(kDebugView, "\t\t Resource List %d: %d", j, _view.scriptResources[i].resource_list[j]);
- }
- } else {
- _view.scriptResources[i].resource_list = NULL;
- _view.scriptResources[i].id = viewStream->readUint16LE();
- debugC(kDebugView, "\t\t Id: %d", _view.scriptResources[i].id);
+ if (scriptResource.type == MystView::kResourceSwitch) {
+ scriptResource.switchVar = viewStream->readUint16LE();
+ debugC(kDebugView, "\t\t Var: %d", scriptResource.switchVar);
+ uint16 count = viewStream->readUint16LE();
+ debugC(kDebugView, "\t\t Resource List Count: %d", count);
+ scriptResource.switchResourceType = (MystView::ScriptResourceType) viewStream->readUint16LE();
+ debugC(kDebugView, "\t\t u0: %d", scriptResource.switchResourceType);
+
+ for (uint16 j = 0; j < count; j++) {
+ scriptResource.switchResourceIds.push_back(viewStream->readSint16LE());
+ debugC(kDebugView, "\t\t Resource List %d: %d", j, scriptResource.switchResourceIds[j]);
}
+ } else {
+ scriptResource.id = viewStream->readUint16LE();
+ debugC(kDebugView, "\t\t Id: %d", scriptResource.id);
}
+
+ _view.scriptResources.push_back(scriptResource);
}
// Identifiers for other resources. 0 if non existent. There is always an RLST.
@@ -831,7 +770,6 @@ void MohawkEngine_Myst::loadCard() {
delete viewStream;
// Precache Card Resources
- // TODO: Deal with Mac ME External Picture File
uint32 cacheImageType;
if (getFeatures() & GF_ME)
cacheImageType = ID_PICT;
@@ -839,63 +777,58 @@ void MohawkEngine_Myst::loadCard() {
cacheImageType = ID_WDIB;
// Precache Image Block data
- if (_view.conditionalImageCount != 0) {
- for (uint16 i = 0; i < _view.conditionalImageCount; i++)
- for (uint16 j = 0; j < _view.conditionalImages[i].numStates; j++)
- cachePreload(cacheImageType, _view.conditionalImages[i].values[j]);
- } else
+ if (_view.conditionalImages.size() != 0) {
+ for (uint16 i = 0; i < _view.conditionalImages.size(); i++) {
+ uint16 value = _scriptParser->getVar(_view.conditionalImages[i].var);
+ cachePreload(cacheImageType, _view.conditionalImages[i].values[value]);
+ }
+ } else {
cachePreload(cacheImageType, _view.mainImage);
+ }
// Precache Sound Block data
- if (_view.sound > 0)
- cachePreload(ID_MSND, _view.sound);
- else if (_view.sound == kMystSoundActionConditional) {
- for (uint16 i = 0; i < _view.soundCount; i++) {
- if (_view.soundList[i] > 0)
- cachePreload(ID_MSND, _view.soundList[i]);
+ if (_view.soundBlock.sound > 0)
+ cachePreload(ID_MSND, _view.soundBlock.sound);
+ else if (_view.soundBlock.sound == kMystSoundActionConditional) {
+ uint16 value = _scriptParser->getVar(_view.soundBlock.soundVar);
+ if (_view.soundBlock.soundList[value].action > 0) {
+ cachePreload(ID_MSND, _view.soundBlock.soundList[value].action);
}
}
// Precache Script Resources
- if (_view.scriptResCount != 0) {
- for (uint16 i = 0; i < _view.scriptResCount; i++) {
- switch (_view.scriptResources[i].type) {
- case 1:
- cachePreload(cacheImageType, _view.scriptResources[i].id);
- break;
- case 2:
- cachePreload(ID_MSND, _view.scriptResources[i].id);
- break;
- case 3:
- warning("TODO: Precaching of Script Resource List not supported");
- break;
- default:
- warning("Unknown Resource in Script Resource List Precaching");
- break;
- }
+ for (uint16 i = 0; i < _view.scriptResources.size(); i++) {
+ MystView::ScriptResourceType type;
+ int16 id;
+ if (_view.scriptResources[i].type == MystView::kResourceSwitch) {
+ type = _view.scriptResources[i].switchResourceType;
+ uint16 value = _scriptParser->getVar(_view.scriptResources[i].switchVar);
+ id = _view.scriptResources[i].switchResourceIds[value];
+ } else {
+ type = _view.scriptResources[i].type;
+ id = _view.scriptResources[i].id;
+ }
+
+ if (id < 0) continue;
+
+ switch (type) {
+ case MystView::kResourceImage:
+ cachePreload(cacheImageType, id);
+ break;
+ case MystView::kResourceSound:
+ cachePreload(ID_MSND, id);
+ break;
+ default:
+ // The other resource types should not be cached
+ break;
}
}
}
void MohawkEngine_Myst::unloadCard() {
- for (uint16 i = 0; i < _view.conditionalImageCount; i++)
- delete[] _view.conditionalImages[i].values;
-
- delete[] _view.conditionalImages;
- _view.conditionalImageCount = 0;
- _view.conditionalImages = NULL;
-
- delete[] _view.soundList;
- _view.soundList = NULL;
- delete[] _view.soundListVolume;
- _view.soundListVolume = NULL;
-
- for (uint16 i = 0; i < _view.scriptResCount; i++)
- delete[] _view.scriptResources[i].resource_list;
-
- delete[] _view.scriptResources;
- _view.scriptResources = NULL;
- _view.scriptResCount = 0;
+ _view.conditionalImages.clear();
+ _view.soundBlock.soundList.clear();
+ _view.scriptResources.clear();
}
void MohawkEngine_Myst::runInitScript() {
@@ -968,14 +901,12 @@ void MohawkEngine_Myst::loadHelp(uint16 id) {
debugC(kDebugHelp, "\thelpText: \"%s\"", helpText.c_str());
delete[] u0;
+
+ delete helpStream;
}
void MohawkEngine_Myst::loadCursorHints() {
- for (uint16 i = 0; i < _cursorHintCount; i++)
- delete[] _cursorHints[i].variableHint.values;
- _cursorHintCount = 0;
- delete[] _cursorHints;
- _cursorHints = NULL;
+ _cursorHints.clear();
if (!_view.hint) {
debugC(kDebugHint, "No HINT Present");
@@ -985,33 +916,33 @@ void MohawkEngine_Myst::loadCursorHints() {
debugC(kDebugHint, "Loading Cursor Hints:");
Common::SeekableReadStream *hintStream = getResource(ID_HINT, _curCard);
- _cursorHintCount = hintStream->readUint16LE();
- debugC(kDebugHint, "Cursor Hint Count: %d", _cursorHintCount);
- _cursorHints = new MystCursorHint[_cursorHintCount];
+ uint16 cursorHintCount = hintStream->readUint16LE();
+ debugC(kDebugHint, "Cursor Hint Count: %d", cursorHintCount);
+
+ for (uint16 i = 0; i < cursorHintCount; i++) {
+ MystCursorHint hint;
- for (uint16 i = 0; i < _cursorHintCount; i++) {
debugC(kDebugHint, "Cursor Hint %d:", i);
- _cursorHints[i].id = hintStream->readUint16LE();
- debugC(kDebugHint, "\tId: %d", _cursorHints[i].id);
- _cursorHints[i].cursor = hintStream->readSint16LE();
- debugC(kDebugHint, "\tCursor: %d", _cursorHints[i].cursor);
+ hint.id = hintStream->readUint16LE();
+ debugC(kDebugHint, "\tId: %d", hint.id);
+ hint.cursor = hintStream->readSint16LE();
+ debugC(kDebugHint, "\tCursor: %d", hint.cursor);
- if (_cursorHints[i].cursor == -1) {
+ if (hint.cursor == -1) {
debugC(kDebugHint, "\tConditional Cursor Hints:");
- _cursorHints[i].variableHint.var = hintStream->readUint16LE();
- debugC(kDebugHint, "\tVar: %d", _cursorHints[i].variableHint.var);
- _cursorHints[i].variableHint.numStates = hintStream->readUint16LE();
- debugC(kDebugHint, "\tNumber of States: %d", _cursorHints[i].variableHint.numStates);
- _cursorHints[i].variableHint.values = new uint16[_cursorHints[i].variableHint.numStates];
- for (uint16 j = 0; j < _cursorHints[i].variableHint.numStates; j++) {
- _cursorHints[i].variableHint.values[j] = hintStream->readUint16LE();
- debugC(kDebugHint, "\t\t State %d: Cursor %d", j, _cursorHints[i].variableHint.values[j]);
+ hint.variableHint.var = hintStream->readUint16LE();
+ debugC(kDebugHint, "\tVar: %d", hint.variableHint.var);
+ uint16 numStates = hintStream->readUint16LE();
+ debugC(kDebugHint, "\tNumber of States: %d", numStates);
+ for (uint16 j = 0; j < numStates; j++) {
+ hint.variableHint.values.push_back(hintStream->readUint16LE());
+ debugC(kDebugHint, "\t\t State %d: Cursor %d", j, hint.variableHint.values[j]);
}
} else {
- _cursorHints[i].variableHint.var = 0;
- _cursorHints[i].variableHint.numStates = 0;
- _cursorHints[i].variableHint.values = NULL;
+ hint.variableHint.var = 0;
}
+
+ _cursorHints.push_back(hint);
}
delete hintStream;
@@ -1033,12 +964,12 @@ void MohawkEngine_Myst::checkCursorHints() {
}
// Check all the cursor hints to see if we're in a hotspot that contains a hint.
- for (uint16 i = 0; i < _cursorHintCount; i++)
+ for (uint16 i = 0; i < _cursorHints.size(); i++)
if (_cursorHints[i].id == _curResource && _resources[_cursorHints[i].id]->isEnabled()) {
if (_cursorHints[i].cursor == -1) {
uint16 var_value = _scriptParser->getVar(_cursorHints[i].variableHint.var);
- if (var_value >= _cursorHints[i].variableHint.numStates)
+ if (var_value >= _cursorHints[i].variableHint.values.size())
warning("Variable %d Out of Range in variable HINT Resource %d", _cursorHints[i].variableHint.var, i);
else {
_currentCursor = _cursorHints[i].variableHint.values[var_value];
@@ -1076,50 +1007,50 @@ void MohawkEngine_Myst::drawResourceImages() {
_resources[i]->drawDataToScreen();
}
-void MohawkEngine_Myst::redrawResource(MystResourceType8 *resource, bool update) {
- resource->drawConditionalDataToScreen(_scriptParser->getVar(resource->getType8Var()), update);
+void MohawkEngine_Myst::redrawResource(MystAreaImageSwitch *resource, bool update) {
+ resource->drawConditionalDataToScreen(_scriptParser->getVar(resource->getImageSwitchVar()), update);
}
void MohawkEngine_Myst::redrawArea(uint16 var, bool update) {
for (uint16 i = 0; i < _resources.size(); i++)
- if (_resources[i]->type == kMystConditionalImage && _resources[i]->getType8Var() == var)
- redrawResource(static_cast<MystResourceType8 *>(_resources[i]), update);
+ if (_resources[i]->type == kMystAreaImageSwitch && _resources[i]->getImageSwitchVar() == var)
+ redrawResource(static_cast<MystAreaImageSwitch *>(_resources[i]), update);
}
-MystResource *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream, MystResource *parent) {
- MystResource *resource = 0;
+MystArea *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent) {
+ MystArea *resource = nullptr;
ResourceType type = static_cast<ResourceType>(rlstStream->readUint16LE());
debugC(kDebugResource, "\tType: %d", type);
- debugC(kDebugResource, "\tSub_Record: %d", (parent == NULL) ? 0 : 1);
+ debugC(kDebugResource, "\tSub_Record: %d", (parent == nullptr) ? 0 : 1);
switch (type) {
- case kMystAction:
- resource = new MystResourceType5(this, rlstStream, parent);
+ case kMystAreaAction:
+ resource = new MystAreaAction(this, rlstStream, parent);
break;
- case kMystVideo:
- resource = new MystResourceType6(this, rlstStream, parent);
+ case kMystAreaVideo:
+ resource = new MystAreaVideo(this, rlstStream, parent);
break;
- case kMystSwitch:
- resource = new MystResourceType7(this, rlstStream, parent);
+ case kMystAreaActionSwitch:
+ resource = new MystAreaActionSwitch(this, rlstStream, parent);
break;
- case kMystConditionalImage:
- resource = new MystResourceType8(this, rlstStream, parent);
+ case kMystAreaImageSwitch:
+ resource = new MystAreaImageSwitch(this, rlstStream, parent);
break;
- case kMystSlider:
- resource = new MystResourceType10(this, rlstStream, parent);
+ case kMystAreaSlider:
+ resource = new MystAreaSlider(this, rlstStream, parent);
break;
- case kMystDragArea:
- resource = new MystResourceType11(this, rlstStream, parent);
+ case kMystAreaDrag:
+ resource = new MystAreaDrag(this, rlstStream, parent);
break;
case kMystVideoInfo:
- resource = new MystResourceType12(this, rlstStream, parent);
+ resource = new MystVideoInfo(this, rlstStream, parent);
break;
- case kMystHoverArea:
- resource = new MystResourceType13(this, rlstStream, parent);
+ case kMystAreaHover:
+ resource = new MystAreaHover(this, rlstStream, parent);
break;
default:
- resource = new MystResource(this, rlstStream, parent);
+ resource = new MystArea(this, rlstStream, parent);
break;
}
@@ -1145,34 +1076,42 @@ void MohawkEngine_Myst::loadResources() {
for (uint16 i = 0; i < resourceCount; i++) {
debugC(kDebugResource, "Resource #%d:", i);
- _resources.push_back(loadResource(rlstStream, NULL));
+ _resources.push_back(loadResource(rlstStream, nullptr));
}
delete rlstStream;
}
Common::Error MohawkEngine_Myst::loadGameState(int slot) {
- if (_gameState->load(_gameState->generateSaveGameList()[slot]))
+ if (_gameState->load(MystGameState::generateSaveGameList()[slot]))
return Common::kNoError;
return Common::kUnknownError;
}
Common::Error MohawkEngine_Myst::saveGameState(int slot, const Common::String &desc) {
- Common::StringArray saveList = _gameState->generateSaveGameList();
+ Common::StringArray saveList = MystGameState::generateSaveGameList();
if ((uint)slot < saveList.size())
- _gameState->deleteSave(saveList[slot]);
+ MystGameState::deleteSave(saveList[slot]);
+
+ return _gameState->save(desc) ? Common::kNoError : Common::kUnknownError;
+}
- return _gameState->save(Common::String(desc)) ? Common::kNoError : Common::kUnknownError;
+bool MohawkEngine_Myst::hasGameSaveSupport() const {
+ return !(getFeatures() & GF_DEMO) && getGameType() != GType_MAKINGOF;
}
bool MohawkEngine_Myst::canLoadGameStateCurrently() {
// No loading in the demo/makingof
- return !(getFeatures() & GF_DEMO) && getGameType() != GType_MAKINGOF;
+ return _canSafelySaveLoad && hasGameSaveSupport();
}
bool MohawkEngine_Myst::canSaveGameStateCurrently() {
+ if (!_canSafelySaveLoad) {
+ return false;
+ }
+
// There's a limited number of stacks the game can save in
switch (_curStack) {
case kChannelwoodStack:
@@ -1225,4 +1164,82 @@ void MohawkEngine_Myst::dropPage() {
checkCursorHints();
}
+MystSoundBlock MohawkEngine_Myst::readSoundBlock(Common::ReadStream *stream) const {
+ MystSoundBlock soundBlock;
+ soundBlock.sound = stream->readSint16LE();
+ debugCN(kDebugView, "Sound Control: %d = ", soundBlock.sound);
+
+ if (soundBlock.sound > 0) {
+ debugC(kDebugView, "Play new Sound, change volume");
+ debugC(kDebugView, "\tSound: %d", soundBlock.sound);
+ soundBlock.soundVolume = stream->readUint16LE();
+ debugC(kDebugView, "\tVolume: %d", soundBlock.soundVolume);
+ } else if (soundBlock.sound == kMystSoundActionContinue)
+ debugC(kDebugView, "Continue current sound");
+ else if (soundBlock.sound == kMystSoundActionChangeVolume) {
+ debugC(kDebugView, "Continue current sound, change volume");
+ soundBlock.soundVolume = stream->readUint16LE();
+ debugC(kDebugView, "\tVolume: %d", soundBlock.soundVolume);
+ } else if (soundBlock.sound == kMystSoundActionStop) {
+ debugC(kDebugView, "Stop sound");
+ } else if (soundBlock.sound == kMystSoundActionConditional) {
+ debugC(kDebugView, "Conditional sound list");
+ soundBlock.soundVar = stream->readUint16LE();
+ debugC(kDebugView, "\tVar: %d", soundBlock.soundVar);
+ uint16 soundCount = stream->readUint16LE();
+ debugC(kDebugView, "\tCount: %d", soundCount);
+
+ for (uint16 i = 0; i < soundCount; i++) {
+ MystSoundBlock::SoundItem sound;
+
+ sound.action = stream->readSint16LE();
+ debugC(kDebugView, "\t\tCondition %d: Action %d", i, sound.action);
+ if (sound.action == kMystSoundActionChangeVolume || sound.action >= 0) {
+ sound.volume = stream->readUint16LE();
+ debugC(kDebugView, "\t\tCondition %d: Volume %d", i, sound.volume);
+ }
+
+ soundBlock.soundList.push_back(sound);
+ }
+ } else {
+ debugC(kDebugView, "Unknown");
+ warning("Unknown sound control value '%d' in card '%d'", soundBlock.sound, _curCard);
+ }
+
+ return soundBlock;
+}
+
+void MohawkEngine_Myst::applySoundBlock(const MystSoundBlock &block) {
+ int16 soundAction = 0;
+ uint16 soundActionVolume = 0;
+
+ if (block.sound == kMystSoundActionConditional) {
+ uint16 soundVarValue = _scriptParser->getVar(block.soundVar);
+ if (soundVarValue >= block.soundList.size())
+ warning("Conditional sound variable outside range");
+ else {
+ soundAction = block.soundList[soundVarValue].action;
+ soundActionVolume = block.soundList[soundVarValue].volume;
+ }
+ } else {
+ soundAction = block.sound;
+ soundActionVolume = block.soundVolume;
+ }
+
+ if (soundAction == kMystSoundActionContinue)
+ debug(2, "Continuing with current sound");
+ else if (soundAction == kMystSoundActionChangeVolume) {
+ debug(2, "Continuing with current sound, changing volume");
+ _sound->changeBackgroundVolumeMyst(soundActionVolume);
+ } else if (soundAction == kMystSoundActionStop) {
+ debug(2, "Stopping sound");
+ _sound->stopBackgroundMyst();
+ } else if (soundAction > 0) {
+ debug(2, "Playing new sound %d", soundAction);
+ _sound->replaceBackgroundMyst(soundAction, soundActionVolume);
+ } else {
+ error("Unknown sound action %d", soundAction);
+ }
+}
+
} // End of namespace Mohawk
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 4d86642652..0b249e5499 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -28,10 +28,9 @@
#include "mohawk/resource_cache.h"
#include "mohawk/myst_scripts.h"
+#include "common/events.h"
#include "common/random.h"
-#include "gui/saveload.h"
-
namespace Mohawk {
class MohawkEngine_Myst;
@@ -41,9 +40,9 @@ class MystScriptParser;
class MystConsole;
class MystGameState;
class MystOptionsDialog;
-class MystResource;
-class MystResourceType8;
-class MystResourceType13;
+class MystArea;
+class MystAreaImageSwitch;
+class MystAreaHover;
// Engine Debug Flags
enum {
@@ -96,8 +95,19 @@ const uint16 kMasterpieceOnly = 0xFFFF;
struct MystCondition {
uint16 var;
- uint16 numStates;
- uint16 *values;
+ Common::Array<uint16> values;
+};
+
+struct MystSoundBlock {
+ struct SoundItem {
+ int16 action;
+ uint16 volume;
+ };
+
+ int16 sound;
+ uint16 soundVolume;
+ uint16 soundVar;
+ Common::Array<SoundItem> soundList;
};
// View Sound Action Type
@@ -118,29 +128,29 @@ struct MystView {
uint16 flags;
// Image Data
- uint16 conditionalImageCount;
- MystCondition *conditionalImages;
+ Common::Array<MystCondition> conditionalImages;
uint16 mainImage;
// Sound Data
- int16 sound;
- uint16 soundVolume;
- uint16 soundVar;
- uint16 soundCount;
- int16 *soundList;
- uint16 *soundListVolume;
+ MystSoundBlock soundBlock;
// Script Resources
- uint16 scriptResCount;
+ enum ScriptResourceType {
+ kResourceImage = 1,
+ kResourceSound = 2,
+ kResourceSwitch = 3,
+ kResourceImageNoCache = 4,
+ kResourceSoundNoCache = 5
+ };
+
struct ScriptResource {
- uint16 type;
- uint16 id; // Not used by type 3
- // TODO: Type 3 has more. Maybe use a union?
- uint16 var; // Used by type 3 only
- uint16 count; // Used by type 3 only
- uint16 u0; // Used by type 3 only
- int16 *resource_list; // Used by type 3 only
- } *scriptResources;
+ ScriptResourceType type;
+ uint16 id;
+ uint16 switchVar;
+ ScriptResourceType switchResourceType;
+ Common::Array<int16> switchResourceIds;
+ };
+ Common::Array<ScriptResource> scriptResources;
// Resource ID's
uint16 rlst;
@@ -158,18 +168,17 @@ struct MystCursorHint {
class MohawkEngine_Myst : public MohawkEngine {
protected:
- Common::Error run();
+ Common::Error run() override;
public:
MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription *gamedesc);
virtual ~MohawkEngine_Myst();
- Common::SeekableReadStream *getResource(uint32 tag, uint16 id);
+ Common::SeekableReadStream *getResource(uint32 tag, uint16 id) override;
+ Common::Array<uint16> getResourceIDList(uint32 type) const;
Common::String wrapMovieFilename(const Common::String &movieName, uint16 stack);
- void reloadSaveList();
-
void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound);
void changeToCard(uint16 card, TransitionType transition);
uint16 getCurCard() { return _curCard; }
@@ -177,46 +186,50 @@ public:
void setMainCursor(uint16 cursor);
uint16 getMainCursor() { return _mainCursor; }
void checkCursorHints();
- MystResource *updateCurrentResource();
+ MystArea *updateCurrentResource();
bool skippableWait(uint32 duration);
- bool _tweaksEnabled;
+ MystSoundBlock readSoundBlock(Common::ReadStream *stream) const;
+ void applySoundBlock(const MystSoundBlock &block);
+
bool _needsUpdate;
bool _needsPageDrop;
bool _needsShowMap;
bool _needsShowDemoMenu;
+ bool _needsShowCredits;
+
+ bool _showResourceRects;
- MystView _view;
MystGraphics *_gfx;
MystGameState *_gameState;
MystScriptParser *_scriptParser;
- Common::Array<MystResource *> _resources;
- MystResource *_dragResource;
+ Common::Array<MystArea *> _resources;
Common::RandomSource *_rnd;
- bool _showResourceRects;
- MystResource *loadResource(Common::SeekableReadStream *rlstStream, MystResource *parent);
+ MystArea *loadResource(Common::SeekableReadStream *rlstStream, MystArea *parent);
void setResourceEnabled(uint16 resourceId, bool enable);
void redrawArea(uint16 var, bool update = true);
- void redrawResource(MystResourceType8 *resource, bool update = true);
+ void redrawResource(MystAreaImageSwitch *resource, bool update = true);
void drawResourceImages();
void drawCardBackground();
uint16 getCardBackgroundId();
+ template<class T>
+ T *getViewResource(uint index);
+
void setCacheState(bool state) { _cache.enabled = state; }
bool getCacheState() { return _cache.enabled; }
- GUI::Debugger *getDebugger() { return _console; }
+ GUI::Debugger *getDebugger() override { return _console; }
- bool canLoadGameStateCurrently();
- bool canSaveGameStateCurrently();
- Common::Error loadGameState(int slot);
- Common::Error saveGameState(int slot, const Common::String &desc);
- bool hasFeature(EngineFeature f) const;
+ bool canLoadGameStateCurrently() override;
+ bool canSaveGameStateCurrently() override;
+ Common::Error loadGameState(int slot) override;
+ Common::Error saveGameState(int slot, const Common::String &desc) override;
+ bool hasFeature(EngineFeature f) const override;
private:
MystConsole *_console;
- GUI::SaveLoadChooser *_loadDialog;
MystOptionsDialog *_optionsDialog;
MystScriptParser *_prevStack;
ResourceCache _cache;
@@ -224,9 +237,18 @@ private:
uint16 _curStack;
uint16 _curCard;
+ MystView _view;
bool _runExitScript;
+ /**
+ * Saving / Loading is only allowed from the main event loop
+ */
+ bool _canSafelySaveLoad;
+ bool hasGameSaveSupport() const;
+
+ bool pollEvent(Common::Event &event);
+
void dropPage();
void loadCard();
@@ -240,15 +262,25 @@ private:
void drawResourceRects();
void checkCurrentResource();
int16 _curResource;
- MystResourceType13 *_hoverResource;
+ MystAreaHover *_hoverResource;
- uint16 _cursorHintCount;
- MystCursorHint *_cursorHints;
+ Common::Array<MystCursorHint> _cursorHints;
void loadCursorHints();
uint16 _currentCursor;
uint16 _mainCursor; // Also defines the current page being held (white, blue, red, or none)
};
+template<class T>
+T *MohawkEngine_Myst::getViewResource(uint index) {
+ T *resource = dynamic_cast<T *>(_resources[index]);
+
+ if (!resource) {
+ error("View resource '%d' has unexpected type", index);
+ }
+
+ return resource;
+}
+
} // End of namespace Mohawk
#endif
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 7a9596d8e0..4b9cf546fa 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -32,11 +32,11 @@
namespace Mohawk {
-MystResource::MystResource(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) {
+MystArea::MystArea(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) {
_vm = vm;
_parent = parent;
- if (parent == NULL) {
+ if (parent == nullptr) {
_flags = rlstStream->readUint16LE();
_rect.left = rlstStream->readSint16LE();
_rect.top = rlstStream->readSint16LE();
@@ -66,10 +66,10 @@ MystResource::MystResource(MohawkEngine_Myst *vm, Common::SeekableReadStream *rl
debugC(kDebugResource, "\tdest: %d", _dest);
}
-MystResource::~MystResource() {
+MystArea::~MystArea() {
}
-void MystResource::handleMouseUp() {
+void MystArea::handleMouseUp() {
if (_dest == 0) {
warning("Movement type resource with null destination at position (%d, %d), (%d, %d)", _rect.left, _rect.top, _rect.right, _rect.bottom);
return;
@@ -78,13 +78,13 @@ void MystResource::handleMouseUp() {
uint16 opcode;
switch (type) {
- case kMystForwardArea:
+ case kMystAreaForward:
opcode = 6;
break;
- case kMystLeftArea:
+ case kMystAreaLeft:
opcode = 8;
break;
- case kMystRightArea:
+ case kMystAreaRight:
opcode = 7;
break;
default:
@@ -96,27 +96,27 @@ void MystResource::handleMouseUp() {
_vm->_scriptParser->runOpcode(opcode, 0);
}
-bool MystResource::canBecomeActive() {
+bool MystArea::canBecomeActive() {
return !unreachableZipDest() && (isEnabled() || (_flags & kMystUnknownFlag));
}
-bool MystResource::unreachableZipDest() {
+bool MystArea::unreachableZipDest() {
return (_flags & kMystZipModeEnableFlag)
&& !_vm->_gameState->isReachableZipDest(_vm->getCurStack() , _dest);
}
-bool MystResource::isEnabled() {
+bool MystArea::isEnabled() {
return _flags & kMystHotspotEnableFlag;
}
-void MystResource::setEnabled(bool enabled) {
+void MystArea::setEnabled(bool enabled) {
if (enabled)
_flags |= kMystHotspotEnableFlag;
else
_flags &= ~kMystHotspotEnableFlag;
}
-const Common::String MystResource::describe() {
+const Common::String MystArea::describe() {
Common::String desc = Common::String::format("type: %2d rect: (%3d %3d %3d %3d)",
type, _rect.left, _rect.top, _rect.width(), _rect.height());
@@ -126,7 +126,7 @@ const Common::String MystResource::describe() {
return desc;
}
-void MystResource::drawBoundingRect() {
+void MystArea::drawBoundingRect() {
if (_rect.isValidRect()) {
if (!canBecomeActive())
_vm->_gfx->drawRect(_rect, kRectUnreachable);
@@ -137,18 +137,19 @@ void MystResource::drawBoundingRect() {
}
}
-MystResourceType5::MystResourceType5(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResource(vm, rlstStream, parent) {
+MystAreaAction::MystAreaAction(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, rlstStream, parent) {
debugC(kDebugResource, "\tResource Type 5 Script:");
_script = vm->_scriptParser->readScript(rlstStream, kMystScriptNormal);
}
-void MystResourceType5::handleMouseUp() {
+void MystAreaAction::handleMouseUp() {
_vm->_scriptParser->runScript(_script, this);
}
-const Common::String MystResourceType5::describe() {
- Common::String desc = MystResource::describe();
+const Common::String MystAreaAction::describe() {
+ Common::String desc = MystArea::describe();
if (_script->size() != 0) {
desc += " ops:";
@@ -161,7 +162,7 @@ const Common::String MystResourceType5::describe() {
}
// In Myst/Making of Myst, the paths are hardcoded ala Windows style without extension. Convert them.
-Common::String MystResourceType6::convertMystVideoName(Common::String name) {
+Common::String MystAreaVideo::convertMystVideoName(Common::String name) {
Common::String temp;
for (uint32 i = 1; i < name.size(); i++) {
@@ -174,7 +175,8 @@ Common::String MystResourceType6::convertMystVideoName(Common::String name) {
return temp + ".mov";
}
-MystResourceType6::MystResourceType6(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType5(vm, rlstStream, parent) {
+MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaAction(vm, rlstStream, parent) {
char c = 0;
do {
@@ -197,16 +199,7 @@ MystResourceType6::MystResourceType6(MohawkEngine_Myst *vm, Common::SeekableRead
_direction = rlstStream->readSint16LE();
_playBlocking = rlstStream->readUint16LE();
_loop = rlstStream->readUint16LE();
- _u3 = rlstStream->readUint16LE();
-
- // TODO: Out of bound values should clip the movie
- if (_left < 0)
- _left = 0;
- if (_top < 0)
- _top = 0;
-
- if (_u3 != 0)
- warning("Type 6 _u3 != 0");
+ _playRate = rlstStream->readUint16LE();
debugC(kDebugResource, "\tvideoFile: \"%s\"", _videoFile.c_str());
debugC(kDebugResource, "\tleft: %d", _left);
@@ -215,15 +208,15 @@ MystResourceType6::MystResourceType6(MohawkEngine_Myst *vm, Common::SeekableRead
debugC(kDebugResource, "\tdirection: %d", _direction);
debugC(kDebugResource, "\tplayBlocking: %d", _playBlocking);
debugC(kDebugResource, "\tplayOnCardChange: %d", _playOnCardChange);
- debugC(kDebugResource, "\tu3: %d", _u3);
+ debugC(kDebugResource, "\tplayRate: %d", _playRate);
}
-VideoHandle MystResourceType6::playMovie() {
+VideoHandle MystAreaVideo::playMovie() {
// Check if the video is already running
VideoHandle handle = _vm->_video->findVideoHandle(_videoFile);
// If the video is not running, play it
- if (!handle || handle->endOfVideo()) {
+ if (!handle) {
handle = _vm->_video->playMovie(_videoFile);
if (!handle)
error("Failed to open '%s'", _videoFile.c_str());
@@ -231,13 +224,23 @@ VideoHandle MystResourceType6::playMovie() {
handle->moveTo(_left, _top);
handle->setLooping(_loop != 0);
+ Common::Rational rate;
+ if (_playRate != 0) {
+ rate = Common::Rational(_playRate, 100);
+ } else {
+ rate = 1;
+ }
+
if (_direction == -1) {
+ rate = -rate;
handle->seek(handle->getDuration());
- handle->setRate(-1);
}
+
+ handle->setRate(rate);
} else {
// Resume the video
handle->pause(false);
+ handle->start();
}
if (_playBlocking) {
@@ -248,186 +251,156 @@ VideoHandle MystResourceType6::playMovie() {
return handle;
}
-void MystResourceType6::handleCardChange() {
+VideoHandle MystAreaVideo::getMovieHandle() {
+ // If the video is already in the manager, just return the handle
+ VideoHandle handle = _vm->_video->findVideoHandle(_videoFile);
+ if (!handle) {
+ // If the video has not been loaded yet, do it but don't start playing it
+ handle = _vm->_video->playMovie(_videoFile);
+ if (!handle)
+ error("Failed to open '%s'", _videoFile.c_str());
+ handle->stop();
+ }
+
+ return handle;
+}
+
+void MystAreaVideo::handleCardChange() {
if (_playOnCardChange)
playMovie();
}
-bool MystResourceType6::isPlaying() {
+bool MystAreaVideo::isPlaying() {
VideoHandle handle = _vm->_video->findVideoHandle(_videoFile);
return handle && !handle->endOfVideo();
}
-void MystResourceType6::pauseMovie(bool pause) {
+void MystAreaVideo::pauseMovie(bool pause) {
VideoHandle handle = _vm->_video->findVideoHandle(_videoFile);
if (handle && !handle->endOfVideo())
handle->pause(pause);
}
-MystResourceType7::MystResourceType7(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResource(vm, rlstStream, parent) {
- _var7 = rlstStream->readUint16LE();
- _numSubResources = rlstStream->readUint16LE();
- debugC(kDebugResource, "\tvar7: %d", _var7);
- debugC(kDebugResource, "\tnumSubResources: %d", _numSubResources);
+MystAreaActionSwitch::MystAreaActionSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, rlstStream, parent) {
+ _actionSwitchVar = rlstStream->readUint16LE();
+ uint16 numSubResources = rlstStream->readUint16LE();
+ debugC(kDebugResource, "\tactionSwitchVar: %d", _actionSwitchVar);
+ debugC(kDebugResource, "\tnumSubResources: %d", numSubResources);
- for (uint16 i = 0; i < _numSubResources; i++)
+ for (uint16 i = 0; i < numSubResources; i++)
_subResources.push_back(vm->loadResource(rlstStream, this));
}
-MystResourceType7::~MystResourceType7() {
+MystAreaActionSwitch::~MystAreaActionSwitch() {
for (uint32 i = 0; i < _subResources.size(); i++)
delete _subResources[i];
_subResources.clear();
}
-// TODO: All these functions to switch subresource are very similar.
-// Find way to share code (function pointer pass?)
-void MystResourceType7::drawDataToScreen() {
- if (_var7 == 0xFFFF) {
- if (_numSubResources == 1)
- _subResources[0]->drawDataToScreen();
- else if (_numSubResources != 0)
- warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources);
+void MystAreaActionSwitch::doSwitch(AreaHandler handler) {
+ if (_actionSwitchVar == 0xFFFF) {
+ if (_subResources.size() == 1)
+ (_subResources[0]->*handler)();
+ else if (_subResources.size() != 0)
+ warning("Action switch resource with _numSubResources of %d, but no control variable", _subResources.size());
} else {
- uint16 varValue = _vm->_scriptParser->getVar(_var7);
+ uint16 varValue = _vm->_scriptParser->getVar(_actionSwitchVar);
- if (_numSubResources == 1 && varValue != 0)
- _subResources[0]->drawDataToScreen();
- else if (_numSubResources != 0) {
- if (varValue < _numSubResources)
- _subResources[varValue]->drawDataToScreen();
+ if (_subResources.size() == 1 && varValue != 0)
+ (_subResources[0]->*handler)();
+ else if (_subResources.size() != 0) {
+ if (varValue < _subResources.size())
+ (_subResources[varValue]->*handler)();
else
- warning("Type 7 Resource Var %d: %d exceeds number of sub resources %d", _var7, varValue, _numSubResources);
+ warning("Action switch resource Var %d: %d exceeds number of sub resources %d", _actionSwitchVar, varValue, _subResources.size());
}
}
}
-void MystResourceType7::handleCardChange() {
- if (_var7 == 0xFFFF) {
- if (_numSubResources == 1)
- _subResources[0]->handleCardChange();
- else if (_numSubResources != 0)
- warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources);
- } else {
- uint16 varValue = _vm->_scriptParser->getVar(_var7);
-
- if (_numSubResources == 1 && varValue != 0)
- _subResources[0]->handleCardChange();
- else if (_numSubResources != 0) {
- if (varValue < _numSubResources)
- _subResources[varValue]->handleCardChange();
- else
- warning("Type 7 Resource Var %d: %d exceeds number of sub resources %d", _var7, varValue, _numSubResources);
- }
- }
+void MystAreaActionSwitch::drawDataToScreen() {
+ doSwitch(&MystArea::drawDataToScreen);
}
-void MystResourceType7::handleMouseUp() {
- if (_var7 == 0xFFFF) {
- if (_numSubResources == 1)
- _subResources[0]->handleMouseUp();
- else if (_numSubResources != 0)
- warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources);
- } else {
- uint16 varValue = _vm->_scriptParser->getVar(_var7);
-
- if (_numSubResources == 1 && varValue != 0)
- _subResources[0]->handleMouseUp();
- else if (_numSubResources != 0) {
- if (varValue < _numSubResources)
- _subResources[varValue]->handleMouseUp();
- else
- warning("Type 7 Resource Var %d: %d exceeds number of sub resources %d", _var7, varValue, _numSubResources);
- }
- }
+void MystAreaActionSwitch::handleCardChange() {
+ doSwitch(&MystArea::handleCardChange);
}
-void MystResourceType7::handleMouseDown() {
- if (_var7 == 0xFFFF) {
- if (_numSubResources == 1)
- _subResources[0]->handleMouseDown();
- else if (_numSubResources != 0)
- warning("Type 7 Resource with _numSubResources of %d, but no control variable", _numSubResources);
- } else {
- uint16 varValue = _vm->_scriptParser->getVar(_var7);
-
- if (_numSubResources == 1 && varValue != 0)
- _subResources[0]->handleMouseDown();
- else if (_numSubResources != 0) {
- if (varValue < _numSubResources)
- _subResources[varValue]->handleMouseDown();
- else
- warning("Type 7 Resource Var %d: %d exceeds number of sub resources %d", _var7, varValue, _numSubResources);
- }
- }
+void MystAreaActionSwitch::handleMouseUp() {
+ doSwitch(&MystArea::handleMouseUp);
}
-MystResourceType8::MystResourceType8(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType7(vm, rlstStream, parent) {
- _var8 = rlstStream->readUint16LE();
- _numSubImages = rlstStream->readUint16LE();
- debugC(kDebugResource, "\tvar8: %d", _var8);
- debugC(kDebugResource, "\tnumSubImages: %d", _numSubImages);
+void MystAreaActionSwitch::handleMouseDown() {
+ doSwitch(&MystArea::handleMouseDown);
+}
- _subImages = new MystResourceType8::SubImage[_numSubImages];
+MystAreaImageSwitch::MystAreaImageSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaActionSwitch(vm, rlstStream, parent) {
+ _imageSwitchVar = rlstStream->readUint16LE();
+ uint16 numSubImages = rlstStream->readUint16LE();
+ debugC(kDebugResource, "\tvar8: %d", _imageSwitchVar);
+ debugC(kDebugResource, "\tnumSubImages: %d", numSubImages);
- for (uint16 i = 0; i < _numSubImages; i++) {
+ for (uint16 i = 0; i < numSubImages; i++) {
debugC(kDebugResource, "\tSubimage %d:", i);
- _subImages[i].wdib = rlstStream->readUint16LE();
- _subImages[i].rect.left = rlstStream->readSint16LE();
+ SubImage subImage;
+ subImage.wdib = rlstStream->readUint16LE();
+ subImage.rect.left = rlstStream->readSint16LE();
- if (_subImages[i].rect.left != -1) {
- _subImages[i].rect.top = rlstStream->readSint16LE();
- _subImages[i].rect.right = rlstStream->readSint16LE();
- _subImages[i].rect.bottom = rlstStream->readSint16LE();
+ if (subImage.rect.left != -1) {
+ subImage.rect.top = rlstStream->readSint16LE();
+ subImage.rect.right = rlstStream->readSint16LE();
+ subImage.rect.bottom = rlstStream->readSint16LE();
} else {
// Use the hotspot rect as the source rect since the subimage is fullscreen
// Convert to bitmap coordinates (upside down)
- _subImages[i].rect.left = _rect.left;
- _subImages[i].rect.top = 333 - _rect.bottom;
- _subImages[i].rect.right = _rect.right;
- _subImages[i].rect.bottom = 333 - _rect.top;
+ subImage.rect.left = _rect.left;
+ subImage.rect.top = 333 - _rect.bottom;
+ subImage.rect.right = _rect.right;
+ subImage.rect.bottom = 333 - _rect.top;
}
- debugC(kDebugResource, "\twdib: %d", _subImages[i].wdib);
- debugC(kDebugResource, "\tleft: %d", _subImages[i].rect.left);
- debugC(kDebugResource, "\ttop: %d", _subImages[i].rect.top);
- debugC(kDebugResource, "\tright: %d", _subImages[i].rect.right);
- debugC(kDebugResource, "\tbottom: %d", _subImages[i].rect.bottom);
+ debugC(kDebugResource, "\twdib: %d", subImage.wdib);
+ debugC(kDebugResource, "\tleft: %d", subImage.rect.left);
+ debugC(kDebugResource, "\ttop: %d", subImage.rect.top);
+ debugC(kDebugResource, "\tright: %d", subImage.rect.right);
+ debugC(kDebugResource, "\tbottom: %d", subImage.rect.bottom);
+
+ _subImages.push_back(subImage);
}
}
-MystResourceType8::~MystResourceType8() {
- delete[] _subImages;
+MystAreaImageSwitch::~MystAreaImageSwitch() {
}
-void MystResourceType8::drawDataToScreen() {
- // Need to call overidden Type 7 function to ensure
+void MystAreaImageSwitch::drawDataToScreen() {
+ // Need to call overridden function to ensure
// switch section is processed correctly.
- MystResourceType7::drawDataToScreen();
+ MystAreaActionSwitch::drawDataToScreen();
bool drawSubImage = false;
int16 subImageId = 0;
- if (_var8 == 0xFFFF) {
- if (_numSubImages == 1) {
+ if (_imageSwitchVar == 0xFFFF) {
+ if (_subImages.size() == 1) {
subImageId = 0;
drawSubImage = true;
- } else if (_numSubImages != 0)
- warning("Type 8 Resource with _numSubImages of %d, but no control variable", _numSubImages);
+ } else if (_subImages.size() != 0)
+ warning("Image Switch resource with _numSubImages of %d, but no control variable", _subImages.size());
} else {
- uint16 varValue = _vm->_scriptParser->getVar(_var8);
+ uint16 varValue = _vm->_scriptParser->getVar(_imageSwitchVar);
- if (_numSubImages == 1 && varValue != 0) {
+ if (_subImages.size() == 1 && varValue != 0) {
subImageId = 0;
drawSubImage = true;
- } else if (_numSubImages != 0) {
- if (varValue < _numSubImages) {
+ } else if (_subImages.size() != 0) {
+ if (varValue < _subImages.size()) {
subImageId = varValue;
drawSubImage = true;
} else
- warning("Type 8 Image Var %d: %d exceeds number of subImages %d", _var8, varValue, _numSubImages);
+ warning("Image Switch Var %d: %d exceeds number of subImages %d", _imageSwitchVar, varValue, _subImages.size());
}
}
@@ -442,20 +415,21 @@ void MystResourceType8::drawDataToScreen() {
}
}
-void MystResourceType8::drawConditionalDataToScreen(uint16 state, bool update) {
+//TODO: Merge with the method above?
+void MystAreaImageSwitch::drawConditionalDataToScreen(uint16 state, bool update) {
bool drawSubImage = false;
int16 subImageId = 0;
- if (_numSubImages == 1 && state != 0) {
+ if (_subImages.size() == 1 && state != 0) {
subImageId = 0;
drawSubImage = true;
- } else if (_numSubImages != 0) {
- if (state < _numSubImages) {
+ } else if (_subImages.size() != 0) {
+ if (state < _subImages.size()) {
subImageId = state;
drawSubImage = true;
} else
- warning("Type 8 Image Var %d: %d exceeds number of subImages %d", _var8, state, _numSubImages);
+ warning("Image Switch Var %d: %d exceeds number of subImages %d", _imageSwitchVar, state, _subImages.size());
}
@@ -476,18 +450,26 @@ void MystResourceType8::drawConditionalDataToScreen(uint16 state, bool update) {
}
}
-uint16 MystResourceType8::getType8Var() {
- return _var8;
+uint16 MystAreaImageSwitch::getImageSwitchVar() {
+ return _imageSwitchVar;
+}
+
+MystAreaImageSwitch::SubImage MystAreaImageSwitch::getSubImage(uint index) const {
+ return _subImages[index];
}
-const Common::String MystResourceType8::describe() {
+void MystAreaImageSwitch::setSubImageRect(uint index, const Common::Rect &rect) {
+ _subImages[index].rect = rect;
+}
+
+const Common::String MystAreaImageSwitch::describe() {
Common::String desc = Common::String::format("%s var: %2d",
- MystResourceType7::describe().c_str(), _var8);
+ MystAreaActionSwitch::describe().c_str(), _imageSwitchVar);
- if (_numSubImages > 0) {
+ if (_subImages.size() > 0) {
desc += " subImgs:";
- for (uint i = 0; i < _numSubImages; i++)
+ for (uint i = 0; i < _subImages.size(); i++)
desc += Common::String::format(" %d", (int16)_subImages[i].wdib);
}
@@ -496,7 +478,8 @@ const Common::String MystResourceType8::describe() {
// No MystResourceType9!
-MystResourceType10::MystResourceType10(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType11(vm, rlstStream, parent) {
+MystAreaSlider::MystAreaSlider(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaDrag(vm, rlstStream, parent) {
_dragSound = rlstStream->readUint16LE();
debugC(kDebugResource, "\tdrag sound : %d", _dragSound);
@@ -505,23 +488,23 @@ MystResourceType10::MystResourceType10(MohawkEngine_Myst *vm, Common::SeekableRe
_sliderHeight = _rect.bottom - _rect.top;
}
-MystResourceType10::~MystResourceType10() {
+MystAreaSlider::~MystAreaSlider() {
}
-void MystResourceType10::setStep(uint16 step) {
+void MystAreaSlider::setStep(uint16 step) {
_rect.top = _minV + _stepV * step - _sliderHeight / 2;
_rect.bottom = _rect.top + _sliderHeight;
_subImages[0].rect.top = 333 - _rect.bottom - 1;
_subImages[0].rect.bottom = 333 - _rect.top - 1;
}
-void MystResourceType10::setPosition(uint16 pos) {
+void MystAreaSlider::setPosition(uint16 pos) {
Common::Point mouse;
mouse.y = pos;
updatePosition(mouse);
}
-Common::Rect MystResourceType10::boundingBox() {
+Common::Rect MystAreaSlider::boundingBox() {
Common::Rect bb;
bb.top = _rect.top;
@@ -544,7 +527,7 @@ Common::Rect MystResourceType10::boundingBox() {
return bb;
}
-void MystResourceType10::restoreBackground() {
+void MystAreaSlider::restoreBackground() {
// Restore background
Common::Rect src = boundingBox();
Common::Rect dest = boundingBox();
@@ -553,14 +536,11 @@ void MystResourceType10::restoreBackground() {
_vm->_gfx->copyImageSectionToScreen(_vm->getCardBackgroundId(), src, dest);
}
-void MystResourceType10::handleMouseDown() {
- // Tell the engine we are dragging a resource
- _vm->_dragResource = this;
-
+void MystAreaSlider::handleMouseDown() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
updatePosition(mouse);
- MystResourceType11::handleMouseDown();
+ MystAreaDrag::handleMouseDown();
// Restore background
restoreBackground();
@@ -569,7 +549,7 @@ void MystResourceType10::handleMouseDown() {
drawConditionalDataToScreen(2);
}
-void MystResourceType10::handleMouseUp() {
+void MystAreaSlider::handleMouseUp() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
updatePosition(mouse);
@@ -593,19 +573,16 @@ void MystResourceType10::handleMouseUp() {
value = _pos.x;
}
- _vm->_scriptParser->setVarValue(_var8, value);
-
- MystResourceType11::handleMouseUp();
+ _vm->_scriptParser->setVarValue(_imageSwitchVar, value);
- // No longer in drag mode
- _vm->_dragResource = 0;
+ MystAreaDrag::handleMouseUp();
}
-void MystResourceType10::handleMouseDrag() {
+void MystAreaSlider::handleMouseDrag() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
updatePosition(mouse);
- MystResourceType11::handleMouseDrag();
+ MystAreaDrag::handleMouseDrag();
// Restore background
restoreBackground();
@@ -614,7 +591,7 @@ void MystResourceType10::handleMouseDrag() {
drawConditionalDataToScreen(2);
}
-void MystResourceType10::updatePosition(const Common::Point &mouse) {
+void MystAreaSlider::updatePosition(const Common::Point &mouse) {
bool positionChanged = false;
Common::Point mouseClipped;
@@ -667,7 +644,8 @@ void MystResourceType10::updatePosition(const Common::Point &mouse) {
_vm->_sound->replaceSoundMyst(_dragSound);
}
-MystResourceType11::MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType8(vm, rlstStream, parent) {
+MystAreaDrag::MystAreaDrag(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaImageSwitch(vm, rlstStream, parent) {
_flagHV = rlstStream->readUint16LE();
_minH = rlstStream->readUint16LE();
_maxH = rlstStream->readUint16LE();
@@ -694,16 +672,15 @@ MystResourceType11::MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableRe
debugCN(kDebugResource, "Type 11 _mouseDragOpcode: %d\n", _mouseDragOpcode);
debugCN(kDebugResource, "Type 11 _mouseUpOpcode: %d\n", _mouseUpOpcode);
- for (byte i = 0; i < 3; i++) {
+ for (byte i = 0; i < ARRAYSIZE(_lists); i++) {
debugC(kDebugResource, "\tList %d:", i);
- _lists[i].listCount = rlstStream->readUint16LE();
- debugC(kDebugResource, "\t%d values", _lists[i].listCount);
+ uint16 listCount = rlstStream->readUint16LE();
+ debugC(kDebugResource, "\t%d values", listCount);
- _lists[i].list = new uint16[_lists[i].listCount];
- for (uint16 j = 0; j < _lists[i].listCount; j++) {
- _lists[i].list[j] = rlstStream->readUint16LE();
- debugC(kDebugResource, "\tValue %d: %d", j, _lists[i].list[j]);
+ for (uint16 j = 0; j < listCount; j++) {
+ _lists[i].push_back(rlstStream->readUint16LE());
+ debugC(kDebugResource, "\tValue %d: %d", j, _lists[i][j]);
}
}
@@ -717,44 +694,42 @@ MystResourceType11::MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableRe
_stepV = (_maxV - _minV) / (_stepsV - 1);
}
-MystResourceType11::~MystResourceType11() {
- for (byte i = 0; i < 3; i++)
- delete[] _lists[i].list;
+MystAreaDrag::~MystAreaDrag() {
}
-void MystResourceType11::handleMouseDown() {
+void MystAreaDrag::handleMouseDown() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
setPositionClipping(mouse, _pos);
_vm->_scriptParser->setInvokingResource(this);
- _vm->_scriptParser->runOpcode(_mouseDownOpcode, _var8);
+ _vm->_scriptParser->runOpcode(_mouseDownOpcode, _imageSwitchVar);
}
-void MystResourceType11::handleMouseUp() {
+void MystAreaDrag::handleMouseUp() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
setPositionClipping(mouse, _pos);
_vm->_scriptParser->setInvokingResource(this);
- _vm->_scriptParser->runOpcode(_mouseUpOpcode, _var8);
+ _vm->_scriptParser->runOpcode(_mouseUpOpcode, _imageSwitchVar);
}
-void MystResourceType11::handleMouseDrag() {
+void MystAreaDrag::handleMouseDrag() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
setPositionClipping(mouse, _pos);
_vm->_scriptParser->setInvokingResource(this);
- _vm->_scriptParser->runOpcode(_mouseDragOpcode, _var8);
+ _vm->_scriptParser->runOpcode(_mouseDragOpcode, _imageSwitchVar);
}
-const Common::String MystResourceType11::describe() {
+const Common::String MystAreaDrag::describe() {
return Common::String::format("%s down: %s drag: %s up: %s",
- MystResourceType8::describe().c_str(),
+ MystAreaImageSwitch::describe().c_str(),
_vm->_scriptParser->getOpcodeDesc(_mouseDownOpcode).c_str(),
_vm->_scriptParser->getOpcodeDesc(_mouseDragOpcode).c_str(),
_vm->_scriptParser->getOpcodeDesc(_mouseUpOpcode).c_str());
}
-void MystResourceType11::setPositionClipping(const Common::Point &mouse, Common::Point &dest) {
+void MystAreaDrag::setPositionClipping(const Common::Point &mouse, Common::Point &dest) {
if (_flagHV & 2)
dest.y = CLIP<uint16>(mouse.y, _minV, _maxV);
@@ -762,19 +737,20 @@ void MystResourceType11::setPositionClipping(const Common::Point &mouse, Common:
dest.x = CLIP<uint16>(mouse.x, _minH, _maxH);
}
-uint16 MystResourceType11::getList1(uint16 index) {
- return (index < _lists[0].listCount) ? _lists[0].list[index] : 0;
+uint16 MystAreaDrag::getList1(uint16 index) {
+ return (index < _lists[0].size()) ? _lists[0][index] : 0;
}
-uint16 MystResourceType11::getList2(uint16 index) {
- return (index < _lists[1].listCount) ? _lists[1].list[index] : 0;
+uint16 MystAreaDrag::getList2(uint16 index) {
+ return (index < _lists[1].size()) ? _lists[1][index] : 0;
}
-uint16 MystResourceType11::getList3(uint16 index) {
- return (index < _lists[2].listCount) ? _lists[2].list[index] : 0;
+uint16 MystAreaDrag::getList3(uint16 index) {
+ return (index < _lists[2].size()) ? _lists[2][index] : 0;
}
-MystResourceType12::MystResourceType12(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResourceType11(vm, rlstStream, parent) {
+MystVideoInfo::MystVideoInfo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaDrag(vm, rlstStream, parent) {
_numFrames = rlstStream->readUint16LE();
_firstFrame = rlstStream->readUint16LE();
uint16 frameWidth = rlstStream->readUint16LE();
@@ -795,16 +771,16 @@ MystResourceType12::MystResourceType12(MohawkEngine_Myst *vm, Common::SeekableRe
debugC(kDebugResource, "\t_frameRect.bottom: %d", _frameRect.bottom);
}
-MystResourceType12::~MystResourceType12() {
+MystVideoInfo::~MystVideoInfo() {
}
-void MystResourceType12::drawFrame(uint16 frame) {
+void MystVideoInfo::drawFrame(uint16 frame) {
_currentFrame = _firstFrame + frame;
_vm->_gfx->copyImageToScreen(_currentFrame, _frameRect);
_vm->_system->updateScreen();
}
-bool MystResourceType12::pullLeverV() {
+bool MystVideoInfo::pullLeverV() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
// Make the handle follow the mouse
@@ -820,7 +796,7 @@ bool MystResourceType12::pullLeverV() {
return step == maxStep;
}
-void MystResourceType12::releaseLeverV() {
+void MystVideoInfo::releaseLeverV() {
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
// Get current lever frame
@@ -836,7 +812,8 @@ void MystResourceType12::releaseLeverV() {
}
}
-MystResourceType13::MystResourceType13(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResource(vm, rlstStream, parent) {
+MystAreaHover::MystAreaHover(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, rlstStream, parent) {
_enterOpcode = rlstStream->readUint16LE();
_leaveOpcode = rlstStream->readUint16LE();
@@ -844,27 +821,27 @@ MystResourceType13::MystResourceType13(MohawkEngine_Myst *vm, Common::SeekableRe
debugC(kDebugResource, "\t_leaveOpcode: %d", _leaveOpcode);
}
-void MystResourceType13::handleMouseEnter() {
+void MystAreaHover::handleMouseEnter() {
// Pass along the enter opcode to the script parser
// The variable to use is stored in the dest field
_vm->_scriptParser->runOpcode(_enterOpcode, _dest);
}
-void MystResourceType13::handleMouseLeave() {
+void MystAreaHover::handleMouseLeave() {
// Pass along the leave opcode (with no parameters) to the script parser
// The variable to use is stored in the dest field
_vm->_scriptParser->runOpcode(_leaveOpcode, _dest);
}
-void MystResourceType13::handleMouseUp() {
+void MystAreaHover::handleMouseUp() {
// Type 13 Resources do nothing on Mouse Clicks.
// This is required to override the inherited default
- // i.e. MystResource::handleMouseUp
+ // i.e. MystArea::handleMouseUp
}
-const Common::String MystResourceType13::describe() {
+const Common::String MystAreaHover::describe() {
return Common::String::format("%s enter: %s leave: %s",
- MystResource::describe().c_str(),
+ MystArea::describe().c_str(),
_vm->_scriptParser->getOpcodeDesc(_enterOpcode).c_str(),
_vm->_scriptParser->getOpcodeDesc(_leaveOpcode).c_str());
}
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 97ec882497..b19a2df9e2 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -32,19 +32,19 @@ namespace Mohawk {
// Myst Resource Types
enum ResourceType {
- kMystForwardArea = 0,
- kMystLeftArea = 1,
- kMystRightArea = 2,
- kMystDownArea = 3,
- kMystUpArea = 4,
- kMystAction = 5,
- kMystVideo = 6,
- kMystSwitch = 7,
- kMystConditionalImage = 8,
- kMystSlider = 10,
- kMystDragArea = 11,
+ kMystAreaForward = 0,
+ kMystAreaLeft = 1,
+ kMystAreaRight = 2,
+ kMystAreaDown = 3,
+ kMystAreaUp = 4,
+ kMystAreaAction = 5,
+ kMystAreaVideo = 6,
+ kMystAreaActionSwitch = 7,
+ kMystAreaImageSwitch = 8,
+ kMystAreaSlider = 10,
+ kMystAreaDrag = 11,
kMystVideoInfo = 12,
- kMystHoverArea = 13
+ kMystAreaHover = 13
};
// Myst Resource Flags
@@ -56,16 +56,14 @@ enum {
kMystZipModeEnableFlag = (1 << 3)
};
-class MystResource {
+class MystArea {
public:
- MystResource(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResource();
+ MystArea(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystArea();
+
virtual const Common::String describe();
void drawBoundingRect();
- MystResource *_parent;
- ResourceType type;
-
bool contains(Common::Point point) { return _rect.contains(point); }
virtual void drawDataToScreen() {}
virtual void handleCardChange() {}
@@ -75,7 +73,7 @@ public:
void setEnabled(bool enabled);
bool isDrawSubimages() { return _flags & kMystSubimageEnableFlag; }
uint16 getDest() { return _dest; }
- virtual uint16 getType8Var() { return 0xFFFF; }
+ virtual uint16 getImageSwitchVar() { return 0xFFFF; }
bool unreachableZipDest();
bool canBecomeActive();
@@ -84,6 +82,8 @@ public:
virtual void handleMouseDown() {}
virtual void handleMouseDrag() {}
+ MystArea *_parent;
+ ResourceType type;
protected:
MohawkEngine_Myst *_vm;
@@ -92,21 +92,25 @@ protected:
uint16 _dest;
};
-class MystResourceType5 : public MystResource {
+class MystAreaAction : public MystArea {
public:
- MystResourceType5(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- void handleMouseUp();
- const Common::String describe();
+ MystAreaAction(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+
+ void handleMouseUp() override;
+ const Common::String describe() override;
protected:
MystScript _script;
};
-class MystResourceType6 : public MystResourceType5 {
+class MystAreaVideo : public MystAreaAction {
public:
- MystResourceType6(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
+ MystAreaVideo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+
VideoHandle playMovie();
- void handleCardChange();
+ VideoHandle getMovieHandle();
+
+ void handleCardChange() override;
bool isPlaying();
void setDirection(int16 direction) { _direction = direction; }
void setBlocking(bool blocking) { _playBlocking = blocking; }
@@ -114,6 +118,7 @@ public:
protected:
static Common::String convertMystVideoName(Common::String name);
+
Common::String _videoFile;
int16 _left;
int16 _top;
@@ -121,58 +126,63 @@ protected:
int16 _direction; // 1 => forward, -1 => backwards
uint16 _playBlocking;
uint16 _playOnCardChange;
- uint16 _u3;
+ uint16 _playRate; // percents
};
-class MystResourceType7 : public MystResource {
+class MystAreaActionSwitch : public MystArea {
public:
- MystResourceType7(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResourceType7();
+ MystAreaActionSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystAreaActionSwitch();
- virtual void drawDataToScreen();
- virtual void handleCardChange();
+ virtual void drawDataToScreen() override;
+ virtual void handleCardChange() override;
- virtual void handleMouseUp();
- virtual void handleMouseDown();
+ virtual void handleMouseUp() override;
+ virtual void handleMouseDown() override;
- MystResource *getSubResource(uint16 index) { return _subResources[index]; }
+ MystArea *getSubResource(uint16 index) { return _subResources[index]; }
protected:
- uint16 _var7;
- uint16 _numSubResources;
- Common::Array<MystResource *> _subResources;
+ typedef void (MystArea::*AreaHandler)();
+
+ void doSwitch(AreaHandler handler);
+
+ uint16 _actionSwitchVar;
+ Common::Array<MystArea *> _subResources;
};
-class MystResourceType8 : public MystResourceType7 {
+class MystAreaImageSwitch : public MystAreaActionSwitch {
public:
- MystResourceType8(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResourceType8();
- virtual const Common::String describe();
-
- virtual void drawDataToScreen();
- void drawConditionalDataToScreen(uint16 state, bool update = true);
- uint16 getType8Var();
+ MystAreaImageSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystAreaImageSwitch();
struct SubImage {
uint16 wdib;
Common::Rect rect;
- } *_subImages;
+ };
+
+ virtual const Common::String describe() override;
+ virtual void drawDataToScreen() override;
+ void drawConditionalDataToScreen(uint16 state, bool update = true);
+ uint16 getImageSwitchVar() override;
+
+ SubImage getSubImage(uint index) const;
+ void setSubImageRect(uint index, const Common::Rect &rect);
protected:
- uint16 _var8;
- uint16 _numSubImages;
+ uint16 _imageSwitchVar;
+ Common::Array<SubImage> _subImages;
};
-// No MystResourceType9!
-
-class MystResourceType11 : public MystResourceType8 {
+class MystAreaDrag : public MystAreaImageSwitch {
public:
- MystResourceType11(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResourceType11();
- const Common::String describe();
+ MystAreaDrag(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystAreaDrag();
- void handleMouseDown();
- void handleMouseUp();
- void handleMouseDrag();
+ const Common::String describe() override;
+
+ virtual void handleMouseDown() override;
+ virtual void handleMouseUp() override;
+ virtual void handleMouseDrag() override;
uint16 getList1(uint16 index);
uint16 getList2(uint16 index);
@@ -183,6 +193,8 @@ public:
Common::Point _pos;
protected:
+ typedef Common::Array<uint16> ValueList;
+
void setPositionClipping(const Common::Point &mouse, Common::Point &dest);
uint16 _flagHV;
@@ -197,21 +209,17 @@ protected:
uint16 _mouseDownOpcode;
uint16 _mouseDragOpcode;
uint16 _mouseUpOpcode;
- struct {
- uint16 listCount;
- uint16 *list;
- } _lists[3];
-
+ ValueList _lists[3];
};
-class MystResourceType10 : public MystResourceType11 {
+class MystAreaSlider : public MystAreaDrag {
public:
- MystResourceType10(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResourceType10();
+ MystAreaSlider(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystAreaSlider();
- void handleMouseDown();
- void handleMouseUp();
- void handleMouseDrag();
+ void handleMouseDown() override;
+ void handleMouseUp() override;
+ void handleMouseDrag() override;
void setStep(uint16 step);
void setPosition(uint16 pos);
void restoreBackground();
@@ -225,10 +233,11 @@ protected:
uint16 _sliderHeight;
};
-class MystResourceType12 : public MystResourceType11 {
+class MystVideoInfo : public MystAreaDrag {
public:
- MystResourceType12(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- virtual ~MystResourceType12();
+ MystVideoInfo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ virtual ~MystVideoInfo();
+
void drawFrame(uint16 frame);
bool pullLeverV();
void releaseLeverV();
@@ -243,12 +252,13 @@ private:
uint16 _currentFrame;
};
-class MystResourceType13 : public MystResource {
+class MystAreaHover : public MystArea {
public:
- MystResourceType13(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
- const Common::String describe();
+ MystAreaHover(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+
+ const Common::String describe() override;
- void handleMouseUp();
+ void handleMouseUp() override;
void handleMouseEnter();
void handleMouseLeave();
diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp
index 49f97cca63..5db9697a78 100644
--- a/engines/mohawk/myst_graphics.cpp
+++ b/engines/mohawk/myst_graphics.cpp
@@ -40,7 +40,7 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : GraphicsManager(), _vm(vm) {
if (_vm->getFeatures() & GF_ME) {
// High color
- initGraphics(_viewport.width(), _viewport.height(), true, NULL);
+ initGraphics(_viewport.width(), _viewport.height(), true, nullptr);
if (_vm->_system->getScreenFormat().bytesPerPixel == 1)
error("Myst ME requires greater than 256 colors to run");
@@ -73,7 +73,7 @@ MohawkSurface *MystGraphics::decodeImage(uint16 id) {
// if it's a PICT or WDIB resource. If it's Myst ME it's most likely a PICT, and if it's
// original it's definitely a WDIB. However, Myst ME throws us another curve ball in
// that PICT resources can contain WDIB's instead of PICT's.
- Common::SeekableReadStream *dataStream = NULL;
+ Common::SeekableReadStream *dataStream = nullptr;
if (_vm->getFeatures() & GF_ME && _vm->hasResource(ID_PICT, id)) {
// The PICT resource exists. However, it could still contain a MystBitmap
@@ -95,7 +95,7 @@ MohawkSurface *MystGraphics::decodeImage(uint16 id) {
dataStream->seek(0);
}
- MohawkSurface *mhkSurface = 0;
+ MohawkSurface *mhkSurface = nullptr;
if (isPict) {
Image::PICTDecoder pict;
@@ -103,6 +103,8 @@ MohawkSurface *MystGraphics::decodeImage(uint16 id) {
if (!pict.loadStream(*dataStream))
error("Could not decode Myst ME PICT");
+ delete dataStream;
+
mhkSurface = new MohawkSurface(pict.getSurface()->convertTo(_pixelFormat));
} else {
mhkSurface = _bmpDecoder->decodeImage(dataStream);
@@ -225,9 +227,8 @@ void MystGraphics::copyBackBufferToScreen(Common::Rect r) {
void MystGraphics::runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay) {
- // Do not artificially delay during transitions
- int oldEnableDrawingTimeSimulation = _enableDrawingTimeSimulation;
- _enableDrawingTimeSimulation = 0;
+ // Transitions are barely visible without adding delays between the draw calls
+ enableDrawingTimeSimulation(true);
switch (type) {
case kTransitionLeftToRight: {
@@ -288,7 +289,10 @@ void MystGraphics::runTransition(TransitionType type, Common::Rect rect, uint16
debugC(kDebugView, "Dissolve");
for (int16 step = 0; step < 8; step++) {
- simulatePreviousDrawDelay(rect);
+ // Only one eighth of the rect pixels are updated by a draw step,
+ // delay by one eighth of the regular time
+ simulatePreviousDrawDelay(Common::Rect(rect.width() / 8, rect.height()));
+
transitionDissolve(rect, step);
}
}
@@ -367,7 +371,7 @@ void MystGraphics::runTransition(TransitionType type, Common::Rect rect, uint16
error("Unknown transition %d", type);
}
- _enableDrawingTimeSimulation = oldEnableDrawingTimeSimulation;
+ enableDrawingTimeSimulation(false);
}
void MystGraphics::transitionDissolve(Common::Rect rect, uint step) {
@@ -639,8 +643,10 @@ void MystGraphics::simulatePreviousDrawDelay(const Common::Rect &dest) {
// Do not draw anything new too quickly after the previous draw call
// so that images stay at least a little while on screen
// This is enabled only for scripted draw calls
- if (time < _nextAllowedDrawTime)
+ if (time < _nextAllowedDrawTime) {
+ debugC(kDebugView, "Delaying draw call by %d ms", _nextAllowedDrawTime - time);
_vm->_system->delayMillis(_nextAllowedDrawTime - time);
+ }
}
// Next draw call allowed at DELAY + AERA * COEFF milliseconds from now
diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h
index 6281c94cc8..93e388cb83 100644
--- a/engines/mohawk/myst_graphics.h
+++ b/engines/mohawk/myst_graphics.h
@@ -61,8 +61,8 @@ public:
const byte *getPalette() const { return _palette; }
protected:
- MohawkSurface *decodeImage(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+ MohawkSurface *decodeImage(uint16 id) override;
+ MohawkEngine *getVM() override { return (MohawkEngine *)_vm; }
private:
MohawkEngine_Myst *_vm;
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index 487d0f45fe..04e7c5a9b7 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -29,6 +29,7 @@
#include "mohawk/video.h"
#include "common/system.h"
+#include "common/memstream.h"
#include "common/textconsole.h"
#include "gui/message.h"
@@ -38,7 +39,7 @@ MystScriptEntry::MystScriptEntry() {
type = kMystScriptNone;
var = 0;
argc = 0;
- argv = 0;
+ argv = nullptr;
resourceId = 0;
u1 = 0;
}
@@ -81,7 +82,7 @@ MystScriptParser::MystScriptParser(MohawkEngine_Myst *vm) :
_vm(vm),
_globals(vm->_gameState->_globals) {
setupCommonOpcodes();
- _invokingResource = NULL;
+ _invokingResource = nullptr;
_savedCardId = 0;
_savedCursorId = 0;
_tempVar = 0;
@@ -154,7 +155,7 @@ void MystScriptParser::setupCommonOpcodes() {
#undef OPCODE
-void MystScriptParser::runScript(MystScript script, MystResource *invokingResource) {
+void MystScriptParser::runScript(MystScript script, MystArea *invokingResource) {
debugC(kDebugScript, "Script Size: %d", script->size());
// Scripted drawing takes more time to simulate older hardware
@@ -260,15 +261,6 @@ bool MystScriptParser::setVarValue(uint16 var, uint16 value) {
return false;
}
-// NOTE: Check to be used on Opcodes where var is thought
-// not to be used. This emits a warning if var is nonzero.
-// It is possible that the opcode does use var 0 in this case,
-// but this will catch the majority of missed cases.
-void MystScriptParser::varUnusedCheck(uint16 op, uint16 var) {
- if (var != 0)
- warning("Opcode %d: Unused Var %d", op, var);
-}
-
void MystScriptParser::animatedUpdate(uint16 argc, uint16 *argv, uint16 delay) {
uint16 argsRead = 0;
@@ -331,7 +323,7 @@ void MystScriptParser::o_changeCardSwitch4(uint16 op, uint16 var, uint16 argc, u
if (value)
_vm->changeToCard(argv[value -1 ], kTransitionDissolve);
- else if (_invokingResource != NULL)
+ else if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve);
else
warning("Missing invokingResource in altDest call");
@@ -344,7 +336,7 @@ void MystScriptParser::o_changeCardSwitchLtR(uint16 op, uint16 var, uint16 argc,
if (value)
_vm->changeToCard(argv[value -1 ], kTransitionLeftToRight);
- else if (_invokingResource != NULL)
+ else if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionLeftToRight);
else
warning("Missing invokingResource in altDest call");
@@ -357,7 +349,7 @@ void MystScriptParser::o_changeCardSwitchRtL(uint16 op, uint16 var, uint16 argc,
if (value)
_vm->changeToCard(argv[value -1 ], kTransitionRightToLeft);
- else if (_invokingResource != NULL)
+ else if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionRightToLeft);
else
warning("Missing invokingResource in altDest call");
@@ -398,7 +390,7 @@ void MystScriptParser::o_redrawCard(uint16 op, uint16 var, uint16 argc, uint16 *
void MystScriptParser::o_goToDest(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op);
- if (_invokingResource != NULL)
+ if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionCopy);
else
warning("Opcode %d: Missing invokingResource", op);
@@ -407,7 +399,7 @@ void MystScriptParser::o_goToDest(uint16 op, uint16 var, uint16 argc, uint16 *ar
void MystScriptParser::o_goToDestForward(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op);
- if (_invokingResource != NULL)
+ if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve);
else
warning("Opcode %d: Missing invokingResource", op);
@@ -416,7 +408,7 @@ void MystScriptParser::o_goToDestForward(uint16 op, uint16 var, uint16 argc, uin
void MystScriptParser::o_goToDestLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op);
- if (_invokingResource != NULL)
+ if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionPartToRight);
else
warning("Opcode %d: Missing invokingResource", op);
@@ -425,7 +417,7 @@ void MystScriptParser::o_goToDestLeft(uint16 op, uint16 var, uint16 argc, uint16
void MystScriptParser::o_goToDestRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op);
- if (_invokingResource != NULL)
+ if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionPartToLeft);
else
warning("Opcode %d: Missing invokingResource", op);
@@ -434,7 +426,7 @@ void MystScriptParser::o_goToDestRight(uint16 op, uint16 var, uint16 argc, uint1
void MystScriptParser::o_goToDestUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op);
- if (_invokingResource != NULL)
+ if (_invokingResource != nullptr)
_vm->changeToCard(_invokingResource->getDest(), kTransitionTopToBottom);
else
warning("Opcode %d: Missing invokingResource", op);
@@ -442,7 +434,10 @@ void MystScriptParser::o_goToDestUp(uint16 op, uint16 var, uint16 argc, uint16 *
void MystScriptParser::o_triggerMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Trigger Type 6 Resource Movie..", op);
- // TODO: If movie has sound, pause background music
+ // The original has code to pause the background music before playing the movie,
+ // if the movie has a sound track, as well as code to resume it afterwards. But since
+ // the movie has not yet been loaded at this point, it is impossible to know
+ // if the movie actually has a sound track. The code is never executed.
int16 direction = 1;
if (argc == 1)
@@ -451,11 +446,9 @@ void MystScriptParser::o_triggerMovie(uint16 op, uint16 var, uint16 argc, uint16
debugC(kDebugScript, "\tDirection: %d", direction);
// Trigger resource 6 movie overriding play direction
- MystResourceType6 *resource = static_cast<MystResourceType6 *>(_invokingResource);
+ MystAreaVideo *resource = getInvokingResource<MystAreaVideo>();
resource->setDirection(direction);
resource->playMovie();
-
- // TODO: If movie has sound, resume background music
}
void MystScriptParser::o_toggleVarNoRedraw(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
@@ -468,7 +461,7 @@ void MystScriptParser::o_drawAreaState(uint16 op, uint16 var, uint16 argc, uint1
debugC(kDebugScript, "Opcode %d: drawAreaState, state: %d", op, argv[0]);
debugC(kDebugScript, "\tVar: %d", var);
- MystResourceType8 *parent = static_cast<MystResourceType8 *>(_invokingResource->_parent);
+ MystAreaImageSwitch *parent = static_cast<MystAreaImageSwitch *>(getInvokingResource<MystArea>()->_parent);
parent->drawConditionalDataToScreen(argv[0]);
}
@@ -517,6 +510,11 @@ void MystScriptParser::o_changeCardPop(uint16 op, uint16 var, uint16 argc, uint1
debugC(kDebugScript, "Opcode %d: Return To Stored Card Id", op);
debugC(kDebugScript, "\tCardId: %d", _savedCardId);
+ if (_savedCardId == 0) {
+ warning("No pushed card to go back to");
+ return;
+ }
+
TransitionType transition = static_cast<TransitionType>(argv[0]);
_vm->changeToCard(_savedCardId, transition);
@@ -531,7 +529,7 @@ void MystScriptParser::o_enableAreas(uint16 op, uint16 var, uint16 argc, uint16
for (uint16 i = 0; i < count; i++) {
debugC(kDebugScript, "Enable hotspot index %d", argv[i + 1]);
- MystResource *resource = 0;
+ MystArea *resource = nullptr;
if (argv[i + 1] == 0xFFFF)
resource = _invokingResource;
else
@@ -556,7 +554,7 @@ void MystScriptParser::o_disableAreas(uint16 op, uint16 var, uint16 argc, uint16
for (uint16 i = 0; i < count; i++) {
debugC(kDebugScript, "Disable hotspot index %d", argv[i + 1]);
- MystResource *resource = 0;
+ MystArea *resource = nullptr;
if (argv[i + 1] == 0xFFFF)
resource = _invokingResource;
else
@@ -587,7 +585,7 @@ void MystScriptParser::o_toggleAreasActivation(uint16 op, uint16 var, uint16 arg
for (uint16 i = 0; i < count; i++) {
debugC(kDebugScript, "Enable/Disable hotspot index %d", argv[i + 1]);
- MystResource *resource = 0;
+ MystArea *resource = nullptr;
if (argv[i + 1] == 0xFFFF)
resource = _invokingResource;
else
@@ -682,82 +680,15 @@ void MystScriptParser::o_copyImageToBackBuffer(uint16 op, uint16 var, uint16 arg
_vm->_gfx->copyImageSectionToBackBuffer(imageId, srcRect, dstRect);
}
-// TODO: Implement common engine function for read and processing of sound blocks
-// for use by this opcode and VIEW sound block.
-// TODO: Though the playSound and PlaySoundBlocking opcodes play sounds immediately,
-// this opcode changes the main background sound playing..
-// Current behavior here and with VIEW sound block is not right as demonstrated
-// by Channelwood Card 3280 (Tank Valve) and water flow sound behavior in pipe
-// on cards leading from shed...
void MystScriptParser::o_changeBackgroundSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- int16 *soundList = NULL;
- uint16 *soundListVolume = NULL;
-
// Used on Stoneship Card 2080
// Used on Channelwood Card 3225 with argc = 8 i.e. Conditional Sound List
- if (argc == 1 || argc == 2 || argc == 8) {
- debugC(kDebugScript, "Opcode %d: Process Sound Block", op);
- uint16 decodeIdx = 0;
-
- int16 soundAction = argv[decodeIdx++];
- uint16 soundVolume = 65535;
- if (soundAction == kMystSoundActionChangeVolume || soundAction > 0) {
- soundVolume = argv[decodeIdx++];
- } else if (soundAction == kMystSoundActionConditional) {
- debugC(kDebugScript, "Conditional sound list");
- uint16 condVar = argv[decodeIdx++];
- uint16 condVarValue = getVar(condVar);
- uint16 condCount = argv[decodeIdx++];
-
- debugC(kDebugScript, "\tcondVar: %d = %d", condVar, condVarValue);
- debugC(kDebugScript, "\tcondCount: %d", condCount);
-
- soundList = new int16[condCount];
- soundListVolume = new uint16[condCount];
-
- if (condVarValue >= condCount)
- warning("Opcode %d: Conditional sound variable outside range", op);
- else {
- for (uint16 i = 0; i < condCount; i++) {
- soundList[i] = argv[decodeIdx++];
- debugC(kDebugScript, "\t\tCondition %d: Action %d", i, soundList[i]);
- if (soundList[i] == kMystSoundActionChangeVolume || soundList[i] > 0) {
- soundListVolume[i] = argv[decodeIdx++];
- } else
- soundListVolume[i] = 65535;
- debugC(kDebugScript, "\t\tCondition %d: Volume %d", i, soundListVolume[i]);
- }
-
- soundAction = soundList[condVarValue];
- soundVolume = soundListVolume[condVarValue];
- }
- }
+ debugC(kDebugScript, "Opcode %d: Process Sound Block", op);
- if (soundAction == kMystSoundActionContinue)
- debugC(kDebugScript, "Continue current sound");
- else if (soundAction == kMystSoundActionChangeVolume) {
- debugC(kDebugScript, "Continue current sound, change volume");
- debugC(kDebugScript, "\tVolume: %d", soundVolume);
- _vm->_sound->changeBackgroundVolumeMyst(soundVolume);
- } else if (soundAction == kMystSoundActionStop) {
- debugC(kDebugScript, "Stop sound");
- _vm->_sound->stopBackgroundMyst();
- } else if (soundAction > 0) {
- debugC(kDebugScript, "Play new Sound, change volume");
- debugC(kDebugScript, "\tSound: %d", soundAction);
- debugC(kDebugScript, "\tVolume: %d", soundVolume);
- _vm->_sound->replaceBackgroundMyst(soundAction, soundVolume);
- } else {
- debugC(kDebugScript, "Unknown");
- warning("Unknown sound control value in opcode %d", op);
- }
- } else
- warning("Unknown arg count in opcode %d", op);
+ Common::MemoryReadStream stream = Common::MemoryReadStream((const byte *) argv, argc * sizeof(uint16));
- delete[] soundList;
- soundList = NULL;
- delete[] soundListVolume;
- soundListVolume = NULL;
+ MystSoundBlock soundBlock = _vm->readSoundBlock(&stream);
+ _vm->applySoundBlock(soundBlock);
}
void MystScriptParser::o_soundPlaySwitch(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h
index 7d8165c762..69052b10f5 100644
--- a/engines/mohawk/myst_scripts.h
+++ b/engines/mohawk/myst_scripts.h
@@ -34,7 +34,7 @@ namespace Mohawk {
#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
class MohawkEngine_Myst;
-class MystResource;
+class MystArea;
enum MystScriptType {
kMystScriptNone,
@@ -63,11 +63,11 @@ public:
MystScriptParser(MohawkEngine_Myst *vm);
virtual ~MystScriptParser();
- void runScript(MystScript script, MystResource *invokingResource = NULL);
- void runOpcode(uint16 op, uint16 var = 0, uint16 argc = 0, uint16 *argv = NULL);
+ void runScript(MystScript script, MystArea *invokingResource = nullptr);
+ void runOpcode(uint16 op, uint16 var = 0, uint16 argc = 0, uint16 *argv = nullptr);
const Common::String getOpcodeDesc(uint16 op);
MystScript readScript(Common::SeekableReadStream *stream, MystScriptType type);
- void setInvokingResource(MystResource *resource) { _invokingResource = resource; }
+ void setInvokingResource(MystArea *resource) { _invokingResource = resource; }
virtual void disablePersistentScripts() = 0;
virtual void runPersistentScripts() = 0;
@@ -151,8 +151,6 @@ protected:
Common::Array<MystOpcode *> _opcodes;
- MystResource *_invokingResource;
-
uint16 _savedCardId;
uint16 _savedMapCardId;
uint16 _savedCursorId;
@@ -163,9 +161,25 @@ protected:
static const uint16 _startCard[];
void setupCommonOpcodes();
- void varUnusedCheck(uint16 op, uint16 var);
+
+ template<class T>
+ T *getInvokingResource() const;
+
+private:
+ MystArea *_invokingResource;
};
+template<class T>
+T *MystScriptParser::getInvokingResource() const {
+ T *resource = dynamic_cast<T *>(_invokingResource);
+
+ if (!resource) {
+ error("Invoking resource has unexpected type");
+ }
+
+ return resource;
+}
+
} // End of namespace Mohawk
#undef DECLARE_OPCODE
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 0718f8e683..21c3042359 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -363,7 +363,7 @@ void Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uint16 var, uint16 a
void Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Open Animation", op);
- Common::Rect rect = _invokingResource->getRect();
+ Common::Rect rect = getInvokingResource<MystArea>()->getRect();
for (uint i = 0; i < 2; i++)
for (uint16 imageId = 3601; imageId >= 3595; imageId--) {
@@ -377,7 +377,7 @@ void Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint1
void Channelwood::o_leverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever start move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
_vm->_cursor->setCursor(700);
_leverPulled = false;
@@ -386,7 +386,7 @@ void Channelwood::o_leverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *a
void Channelwood::o_leverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
if (lever->pullLeverV()) {
if (!_leverPulled) {
@@ -401,7 +401,7 @@ void Channelwood::o_leverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv)
void Channelwood::o_leverMoveFail(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
if (lever->pullLeverV()) {
if (!_leverPulled) {
@@ -419,7 +419,7 @@ void Channelwood::o_leverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *arg
debugC(kDebugScript, "Opcode %d: Generic lever end move", op);
// Get current lever frame
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Release lever
lever->releaseLeverV();
@@ -439,7 +439,7 @@ void Channelwood::o_leverEndMoveResumeBackground(uint16 op, uint16 var, uint16 a
void Channelwood::o_leverEndMoveWithSound(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
o_leverEndMove(op, var, argc, argv);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
uint16 soundId = lever->getList3(0);
if (soundId)
_vm->_sound->replaceSoundMyst(soundId);
@@ -461,7 +461,7 @@ void Channelwood::o_leverElev3EndMove(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_pumpLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Pump lever move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
if (lever->pullLeverV()) {
uint16 soundId = lever->getList2(0);
@@ -475,7 +475,7 @@ void Channelwood::o_pumpLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *ar
void Channelwood::o_pumpLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
o_leverEndMove(op, var, argc, argv);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
uint16 soundId = lever->getList3(0);
if (soundId)
_vm->_sound->replaceBackgroundMyst(soundId, 36864);
@@ -484,7 +484,7 @@ void Channelwood::o_pumpLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Play stairs door video", op);
- MystResourceType6 *movie = static_cast<MystResourceType6 *>(_invokingResource);
+ MystAreaVideo *movie = getInvokingResource<MystAreaVideo>();
if (_state.stairsUpperDoorState) {
// Close door, play the open movie backwards
@@ -500,7 +500,7 @@ void Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_valveHandleMove1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
if (handle->getRect().contains(mouse)) {
@@ -516,7 +516,7 @@ void Channelwood::o_valveHandleMove1(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_valveHandleMoveStart1(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
uint16 soundId = handle->getList1(0);
if (soundId)
_vm->_sound->replaceSoundMyst(soundId);
@@ -528,7 +528,7 @@ void Channelwood::o_valveHandleMoveStart1(uint16 op, uint16 var, uint16 argc, ui
void Channelwood::o_valveHandleMoveStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move stop", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
// Update state with valve position
if (_tempVar <= 5)
@@ -551,7 +551,7 @@ void Channelwood::o_valveHandleMoveStop(uint16 op, uint16 var, uint16 argc, uint
void Channelwood::o_valveHandleMove2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
if (handle->getRect().contains(mouse)) {
@@ -567,7 +567,7 @@ void Channelwood::o_valveHandleMove2(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_valveHandleMoveStart2(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
uint16 soundId = handle->getList1(0);
if (soundId)
_vm->_sound->replaceSoundMyst(soundId);
@@ -579,7 +579,7 @@ void Channelwood::o_valveHandleMoveStart2(uint16 op, uint16 var, uint16 argc, ui
void Channelwood::o_valveHandleMove3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
if (handle->getRect().contains(mouse)) {
@@ -595,7 +595,7 @@ void Channelwood::o_valveHandleMove3(uint16 op, uint16 var, uint16 argc, uint16
void Channelwood::o_valveHandleMoveStart3(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Valve handle move start", op);
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
uint16 soundId = handle->getList1(0);
if (soundId)
_vm->_sound->replaceSoundMyst(soundId);
@@ -621,24 +621,32 @@ void Channelwood::o_hologramMonitor(uint16 op, uint16 var, uint16 argc, uint16 *
switch (button) {
case 0:
handle = _vm->_video->playMovie(_vm->wrapMovieFilename("monalgh", kChannelwoodStack));
+ if (!handle)
+ error("Failed to open monalgh movie");
+ handle->moveTo(227, 70);
break;
case 1:
handle = _vm->_video->playMovie(_vm->wrapMovieFilename("monamth", kChannelwoodStack));
+ if (!handle)
+ error("Failed to open monamth movie");
+ handle->moveTo(227, 70);
break;
case 2:
handle = _vm->_video->playMovie(_vm->wrapMovieFilename("monasirs", kChannelwoodStack));
+ if (!handle)
+ error("Failed to open monasirs movie");
+ handle->moveTo(227, 70);
break;
case 3:
handle = _vm->_video->playMovie(_vm->wrapMovieFilename("monsmsg", kChannelwoodStack));
+ if (!handle)
+ error("Failed to open monsmsg movie");
+ handle->moveTo(226, 68);
break;
default:
warning("Opcode %d Control Variable Out of Range", op);
break;
}
-
- // Move the video to the right location
- if (handle)
- handle->moveTo(227, 70);
}
}
@@ -680,13 +688,13 @@ void Channelwood::o_hologramTemple(uint16 op, uint16 var, uint16 argc, uint16 *a
void Channelwood::o_executeMouseUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Execute mouse up", op);
- MystResourceType5 *resource = static_cast<MystResourceType5 *>(_vm->_resources[argv[0]]);
+ MystArea *resource = _vm->getViewResource<MystArea>(argv[0]);
resource->handleMouseUp();
}
void Channelwood::o_waterTankValveClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Do Water Tank Valve Close Animation", op);
- Common::Rect rect = _invokingResource->getRect();
+ Common::Rect rect = getInvokingResource<MystArea>()->getRect();
for (uint i = 0; i < 2; i++)
for (uint16 imageId = 3595; imageId <= 3601; imageId++) {
@@ -747,13 +755,14 @@ void Channelwood::o_soundReplace(uint16 op, uint16 var, uint16 argc, uint16 *arg
uint16 soundId = argv[0];
- // TODO: If is foreground playing
- _vm->_sound->replaceSoundMyst(soundId);
+ if (!_vm->_sound->isPlaying()) {
+ _vm->_sound->replaceSoundMyst(soundId);
+ }
}
void Channelwood::o_lever_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generic lever init", op);
- _leverAction = static_cast<MystResourceType5 *>(_invokingResource);
+ _leverAction = getInvokingResource<MystArea>();
}
void Channelwood::o_pipeValve_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/myst_stacks/channelwood.h b/engines/mohawk/myst_stacks/channelwood.h
index bd5d7ffe94..ac875e52d8 100644
--- a/engines/mohawk/myst_stacks/channelwood.h
+++ b/engines/mohawk/myst_stacks/channelwood.h
@@ -40,16 +40,16 @@ public:
Channelwood(MohawkEngine_Myst *vm);
~Channelwood();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
- void toggleVar(uint16 var);
- bool setVarValue(uint16 var, uint16 value);
+ uint16 getVar(uint16 var) override;
+ void toggleVar(uint16 var) override;
+ bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() { return 9932; }
+ virtual uint16 getMap() override { return 9932; }
DECLARE_OPCODE(o_bridgeToggle);
DECLARE_OPCODE(o_pipeExtend);
@@ -94,7 +94,7 @@ private:
uint16 _doorOpened; // 68
bool _leverPulled;
- MystResourceType5 *_leverAction; // 72
+ MystArea *_leverAction; // 72
bool pipeChangeValve(bool open, uint16 mask);
};
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index b9ff8b26aa..b4a2076528 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -37,6 +37,7 @@ namespace MystStacks {
Credits::Credits(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
setupOpcodes();
+ _curImage = 0;
}
Credits::~Credits() {
@@ -66,8 +67,10 @@ void Credits::runPersistentScripts() {
_curImage++;
// After the 6th image has shown, it's time to quit
- if (_curImage == 7)
+ if (_curImage == 7) {
_vm->quitGame();
+ return;
+ }
// Draw next image
_vm->drawCardBackground();
diff --git a/engines/mohawk/myst_stacks/credits.h b/engines/mohawk/myst_stacks/credits.h
index 3c0f969203..c2c20372bd 100644
--- a/engines/mohawk/myst_stacks/credits.h
+++ b/engines/mohawk/myst_stacks/credits.h
@@ -40,12 +40,12 @@ public:
Credits(MohawkEngine_Myst *vm);
~Credits();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
+ uint16 getVar(uint16 var) override;
DECLARE_OPCODE(o_runCredits);
diff --git a/engines/mohawk/myst_stacks/demo.h b/engines/mohawk/myst_stacks/demo.h
index f19b9a6c2c..64a392502f 100644
--- a/engines/mohawk/myst_stacks/demo.h
+++ b/engines/mohawk/myst_stacks/demo.h
@@ -40,8 +40,8 @@ public:
Demo(MohawkEngine_Myst *vm);
~Demo();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/dni.h b/engines/mohawk/myst_stacks/dni.h
index 3dc4645bd3..1a5f0911f9 100644
--- a/engines/mohawk/myst_stacks/dni.h
+++ b/engines/mohawk/myst_stacks/dni.h
@@ -40,12 +40,12 @@ public:
Dni(MohawkEngine_Myst *vm);
~Dni();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
+ uint16 getVar(uint16 var) override;
void atrus_run();
void loopVideo_run();
diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp
index dc66984398..1d733d8100 100644
--- a/engines/mohawk/myst_stacks/intro.cpp
+++ b/engines/mohawk/myst_stacks/intro.cpp
@@ -170,7 +170,7 @@ void Intro::mystLinkBook_run() {
void Intro::o_mystLinkBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Myst link book init", op);
- _linkBookMovie = static_cast<MystResourceType6 *>(_invokingResource);
+ _linkBookMovie = getInvokingResource<MystAreaVideo>();
_startTime = 1;
_linkBookRunning = true;
}
diff --git a/engines/mohawk/myst_stacks/intro.h b/engines/mohawk/myst_stacks/intro.h
index a6c4a594d2..0095706795 100644
--- a/engines/mohawk/myst_stacks/intro.h
+++ b/engines/mohawk/myst_stacks/intro.h
@@ -29,7 +29,7 @@
namespace Mohawk {
-class MystResourceType6;
+class MystAreaVideo;
struct MystScriptEntry;
namespace MystStacks {
@@ -41,12 +41,12 @@ public:
Intro(MohawkEngine_Myst *vm);
~Intro();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
+ uint16 getVar(uint16 var) override;
DECLARE_OPCODE(o_useLinkBook);
@@ -60,7 +60,7 @@ private:
uint16 _introStep;
bool _linkBookRunning;
- MystResourceType6 *_linkBookMovie;
+ MystAreaVideo *_linkBookMovie;
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/makingof.h b/engines/mohawk/myst_stacks/makingof.h
index 79ef913bcf..41f91bc3fa 100644
--- a/engines/mohawk/myst_stacks/makingof.h
+++ b/engines/mohawk/myst_stacks/makingof.h
@@ -40,8 +40,8 @@ public:
MakingOf(MohawkEngine_Myst *vm);
~MakingOf();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index ffcaa226c6..3324c9a22d 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -40,6 +40,9 @@ Mechanical::Mechanical(MohawkEngine_Myst *vm) :
setupOpcodes();
_elevatorGoingMiddle = false;
+ _elevatorPosition = 0;
+
+ _crystalLit = 0;
_mystStaircaseState = false;
_fortressPosition = 0;
@@ -277,7 +280,7 @@ void Mechanical::o_throneEnablePassage(uint16 op, uint16 var, uint16 argc, uint1
void Mechanical::o_birdCrankStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Mechanical bird crank start", op);
- MystResourceType11 *crank = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *crank = getInvokingResource<MystAreaDrag>();
uint16 crankSoundId = crank->getList2(0);
_vm->_sound->replaceSoundMyst(crankSoundId, Audio::Mixer::kMaxChannelVolume, true);
@@ -285,16 +288,16 @@ void Mechanical::o_birdCrankStart(uint16 op, uint16 var, uint16 argc, uint16 *ar
_birdSingEndTime = 0;
_birdCrankStartTime = _vm->_system->getMillis();
- MystResourceType6 *crankMovie = static_cast<MystResourceType6 *>(crank->getSubResource(0));
+ MystAreaVideo *crankMovie = static_cast<MystAreaVideo *>(crank->getSubResource(0));
crankMovie->playMovie();
}
void Mechanical::o_birdCrankStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Mechanical bird crank stop", op);
- MystResourceType11 *crank = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *crank = getInvokingResource<MystAreaDrag>();
- MystResourceType6 *crankMovie = static_cast<MystResourceType6 *>(crank->getSubResource(0));
+ MystAreaVideo *crankMovie = static_cast<MystAreaVideo *>(crank->getSubResource(0));
crankMovie->pauseMovie(true);
uint16 crankSoundId = crank->getList2(1);
@@ -334,7 +337,7 @@ void Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var, uint16 argc, ui
void Mechanical::o_elevatorRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Elevator rotation lever start", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
_elevatorRotationLeverMoving = true;
@@ -349,7 +352,7 @@ void Mechanical::o_elevatorRotationMove(uint16 op, uint16 var, uint16 argc, uint
debugC(kDebugScript, "Opcode %d: Elevator rotation lever move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Make the handle follow the mouse
int16 maxStep = lever->getNumFrames() - 1;
@@ -367,7 +370,7 @@ void Mechanical::o_elevatorRotationStop(uint16 op, uint16 var, uint16 argc, uint
debugC(kDebugScript, "Opcode %d: Elevator rotation lever stop", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Get current lever frame
int16 maxStep = lever->getNumFrames() - 1;
@@ -416,7 +419,7 @@ void Mechanical::o_fortressRotationSpeedStart(uint16 op, uint16 var, uint16 argc
_vm->_cursor->setCursor(700);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
}
@@ -424,7 +427,7 @@ void Mechanical::o_fortressRotationSpeedMove(uint16 op, uint16 var, uint16 argc,
debugC(kDebugScript, "Opcode %d Fortress rotation speed lever move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Make the handle follow the mouse
int16 maxStep = lever->getNumFrames() - 1;
@@ -441,7 +444,7 @@ void Mechanical::o_fortressRotationSpeedMove(uint16 op, uint16 var, uint16 argc,
void Mechanical::o_fortressRotationSpeedStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d Fortress rotation speed lever stop", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Release lever
for (int i = _fortressRotationSpeed; i >= 0; i--) {
@@ -459,7 +462,7 @@ void Mechanical::o_fortressRotationBrakeStart(uint16 op, uint16 var, uint16 argc
_vm->_cursor->setCursor(700);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(_fortressRotationBrake);
}
@@ -467,7 +470,7 @@ void Mechanical::o_fortressRotationBrakeMove(uint16 op, uint16 var, uint16 argc,
debugC(kDebugScript, "Opcode %d Fortress rotation brake lever move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Make the handle follow the mouse
int16 maxStep = lever->getNumFrames() - 1;
@@ -484,7 +487,7 @@ void Mechanical::o_fortressRotationBrakeMove(uint16 op, uint16 var, uint16 argc,
void Mechanical::o_fortressRotationBrakeStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d Fortress rotation brake lever stop", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(_fortressRotationBrake);
_vm->checkCursorHints();
@@ -495,7 +498,7 @@ void Mechanical::o_fortressSimulationSpeedStart(uint16 op, uint16 var, uint16 ar
_vm->_cursor->setCursor(700);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
}
@@ -503,7 +506,7 @@ void Mechanical::o_fortressSimulationSpeedMove(uint16 op, uint16 var, uint16 arg
debugC(kDebugScript, "Opcode %d Fortress rotation simulator speed lever move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Make the handle follow the mouse
int16 maxStep = lever->getNumFrames() - 1;
@@ -520,7 +523,7 @@ void Mechanical::o_fortressSimulationSpeedMove(uint16 op, uint16 var, uint16 arg
void Mechanical::o_fortressSimulationSpeedStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d Fortress rotation simulator speed lever stop", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Release lever
for (int i = _fortressSimulationSpeed; i >= 0; i--) {
@@ -538,7 +541,7 @@ void Mechanical::o_fortressSimulationBrakeStart(uint16 op, uint16 var, uint16 ar
_vm->_cursor->setCursor(700);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(_fortressSimulationBrake);
}
@@ -546,7 +549,7 @@ void Mechanical::o_fortressSimulationBrakeMove(uint16 op, uint16 var, uint16 arg
debugC(kDebugScript, "Opcode %d Fortress rotation simulator brake lever move", op);
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// Make the handle follow the mouse
int16 maxStep = lever->getNumFrames() - 1;
@@ -563,7 +566,7 @@ void Mechanical::o_fortressSimulationBrakeMove(uint16 op, uint16 var, uint16 arg
void Mechanical::o_fortressSimulationBrakeStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d Fortress rotation simulator brake lever stop", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(_fortressSimulationBrake);
_vm->checkCursorHints();
@@ -664,7 +667,7 @@ void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 *
void Mechanical::o_fortressRotationSetPosition(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Set fortress position", op);
- VideoHandle gears = _fortressRotationGears->playMovie();
+ VideoHandle gears = _fortressRotationGears->getMovieHandle();
uint32 moviePosition = Audio::Timestamp(gears->getTime(), 600).totalNumberOfFrames();
// Myst ME short movie workaround, explained in o_fortressRotation_init
@@ -737,7 +740,7 @@ void Mechanical::o_throne_init(uint16 op, uint16 var, uint16 argc, uint16 *argv)
// Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
debugC(kDebugScript, "Opcode %d: Brother throne init", op);
- _invokingResource->setEnabled(getVar(var));
+ getInvokingResource<MystArea>()->setEnabled(getVar(var));
}
void Mechanical::o_fortressStaircase_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
@@ -763,13 +766,13 @@ void Mechanical::o_bird_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_birdSinging = false;
_birdSingEndTime = 0;
- _bird = static_cast<MystResourceType6 *>(_invokingResource);
+ _bird = getInvokingResource<MystAreaVideo>();
}
void Mechanical::o_snakeBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Snake box init", op);
- _snakeBox = static_cast<MystResourceType6 *>(_invokingResource);
+ _snakeBox = getInvokingResource<MystAreaVideo>();
}
void Mechanical::elevatorRotation_run() {
@@ -798,7 +801,7 @@ void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uin
}
void Mechanical::fortressRotation_run() {
- VideoHandle gears = _fortressRotationGears->playMovie();
+ VideoHandle gears = _fortressRotationGears->getMovieHandle();
double oldRate = gears->getRate().toDouble();
uint32 moviePosition = Audio::Timestamp(gears->getTime(), 600).totalNumberOfFrames();
@@ -872,7 +875,7 @@ void Mechanical::fortressRotation_run() {
void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Fortress rotation init", op);
- _fortressRotationGears = static_cast<MystResourceType6 *>(_invokingResource);
+ _fortressRotationGears = getInvokingResource<MystAreaVideo>();
VideoHandle gears = _fortressRotationGears->playMovie();
gears->setLooping(true);
@@ -938,13 +941,22 @@ void Mechanical::fortressSimulation_run() {
holo->setLooping(true);
holo->setRate(0);
+ // HACK: Support negative rates with edit lists
+ _fortressSimulationHoloRate = 0;
+ // END HACK
+
_vm->_cursor->showCursor();
_fortressSimulationInit = false;
} else {
- VideoHandle holo = _fortressSimulationHolo->playMovie();
+ VideoHandle holo = _fortressSimulationHolo->getMovieHandle();
double oldRate = holo->getRate().toDouble();
+
+ // HACK: Support negative rates with edit lists
+ oldRate = _fortressSimulationHoloRate;
+ // END HACK
+
uint32 moviePosition = Audio::Timestamp(holo->getTime(), 600).totalNumberOfFrames();
int32 positionInQuarter = 900 - (moviePosition + 900) % 1800;
@@ -978,7 +990,26 @@ void Mechanical::fortressSimulation_run() {
newRate = CLIP<double>(newRate, -2.5, 2.5);
- holo->setRate(Common::Rational((int)(newRate * 1000.0), 1000));
+ // HACK: Support negative rates with edit lists
+
+ // Our current QuickTime implementation does not support negative
+ // playback rates for movies using edit lists.
+ // The fortress rotation simulator movie this code handles is the
+ // only movie in the game requiring that feature.
+
+ // This hack approximates the next frame to display when the rate
+ // is negative, and seeks to it. It's not intended to be precise.
+
+ _fortressSimulationHoloRate = newRate;
+
+ if (_fortressSimulationHoloRate < 0) {
+ double newMoviePosition = moviePosition + _fortressSimulationHoloRate * 10;
+ holo->setRate(0);
+ holo->seek(Audio::Timestamp(0, (uint)newMoviePosition, 600));
+ } else {
+ holo->setRate(Common::Rational((int)(newRate * 1000.0), 1000));
+ }
+ // END HACK
_gearsWereRunning = true;
} else if (_gearsWereRunning) {
@@ -986,6 +1017,11 @@ void Mechanical::fortressSimulation_run() {
uint16 simulationPosition = (moviePosition + 900) / 1800 % 4;
holo->setRate(0);
+
+ // HACK: Support negative rates with edit lists
+ _fortressSimulationHoloRate = 0;
+ // END HACK
+
holo->seek(Audio::Timestamp(0, 1800 * simulationPosition, 600));
_vm->_sound->playSoundBlocking( _fortressRotationSounds[simulationPosition]);
@@ -997,7 +1033,7 @@ void Mechanical::fortressSimulation_run() {
void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Fortress rotation simulator init", op);
- _fortressSimulationHolo = static_cast<MystResourceType6 *>(_invokingResource);
+ _fortressSimulationHolo = getInvokingResource<MystAreaVideo>();
_fortressSimulationStartSound1 = argv[0];
_fortressSimulationStartSound2 = argv[1];
@@ -1019,7 +1055,7 @@ void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, u
void Mechanical::o_fortressSimulationStartup_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Fortress rotation simulator startup init", op);
- _fortressSimulationStartup = static_cast<MystResourceType6 *>(_invokingResource);
+ _fortressSimulationStartup = getInvokingResource<MystAreaVideo>();
}
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h
index 6360b2be2d..aae02df433 100644
--- a/engines/mohawk/myst_stacks/mechanical.h
+++ b/engines/mohawk/myst_stacks/mechanical.h
@@ -40,16 +40,16 @@ public:
Mechanical(MohawkEngine_Myst *vm);
~Mechanical();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
- void toggleVar(uint16 var);
- bool setVarValue(uint16 var, uint16 value);
+ uint16 getVar(uint16 var) override;
+ void toggleVar(uint16 var) override;
+ bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() { return 9931; }
+ virtual uint16 getMap() override { return 9931; }
void birdSing_run();
void elevatorRotation_run();
@@ -109,7 +109,7 @@ private:
uint16 _fortressRotationBrake; // 80
uint16 _fortressPosition; // 82
uint16 _fortressRotationSounds[4]; // 86 to 92
- MystResourceType6 *_fortressRotationGears; // 172
+ MystAreaVideo *_fortressRotationGears; // 172
bool _fortressRotationShortMovieWorkaround;
uint32 _fortressRotationShortMovieCount;
@@ -121,8 +121,12 @@ private:
uint16 _fortressSimulationBrake; // 98
uint16 _fortressSimulationStartSound1; // 102
uint16 _fortressSimulationStartSound2; // 100
- MystResourceType6 *_fortressSimulationHolo; // 160
- MystResourceType6 *_fortressSimulationStartup; // 164
+ MystAreaVideo *_fortressSimulationHolo; // 160
+ MystAreaVideo *_fortressSimulationStartup; // 164
+
+ // HACK: Support negative rates with edit lists
+ double _fortressSimulationHoloRate;
+ // END HACK
uint16 _elevatorGoingDown; // 112
@@ -143,10 +147,10 @@ private:
bool _birdSinging; // 144
uint32 _birdCrankStartTime; // 136
uint32 _birdSingEndTime; // 140
- MystResourceType6 *_bird; // 152
+ MystAreaVideo *_bird; // 152
- MystResourceType6 *_snakeBox; // 156
+ MystAreaVideo *_snakeBox; // 156
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 9ad1635757..9d23d2fb10 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -50,14 +50,16 @@ Myst::Myst(MohawkEngine_Myst *vm) :
_libraryBookcaseChanged = false;
_dockVaultState = 0;
_cabinDoorOpened = 0;
+ _cabinHandleDown = 0;
_cabinMatchState = 2;
+ _cabinGaugeMovieEnabled = false;
_matchBurning = false;
- _tree = 0;
- _treeAlcove = 0;
+ _tree = nullptr;
+ _treeAlcove = nullptr;
_treeStopped = false;
_treeMinPosition = 0;
_imagerValidationStep = 0;
- _observatoryCurrentSlider = 0;
+ _observatoryCurrentSlider = nullptr;
_butterfliesMoviePlayed = false;
_state.treeLastMoveTime = _vm->_system->getMillis();
}
@@ -626,7 +628,7 @@ uint16 Myst::getVar(uint16 var) {
case 307: // Cabin Boiler Fully Pressurized
return _state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12;
case 308: // Cabin handle position
- return 0; // Not implemented in the original
+ return _cabinHandleDown;
default:
return MystScriptParser::getVar(var);
}
@@ -764,6 +766,9 @@ bool Myst::setVarValue(uint16 var, uint16 value) {
case 304: // Myst Library Image Present on Tower Rotation Map
_towerRotationMapInitialized = value;
break;
+ case 308: // Cabin handle position
+ _cabinHandleDown = value;
+ break;
case 309: // Tree stopped
_treeStopped = value;
break;
@@ -860,14 +865,14 @@ void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *a
if (line & bitmask) {
// Unset button
for (uint i = 4795; i >= 4779; i--) {
- _vm->_gfx->copyImageToScreen(i, _invokingResource->getRect());
+ _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect());
_vm->_system->updateScreen();
}
_fireplaceLines[var - 17] &= ~bitmask;
} else {
// Set button
for (uint i = 4779; i <= 4795; i++) {
- _vm->_gfx->copyImageToScreen(i, _invokingResource->getRect());
+ _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect());
_vm->_system->updateScreen();
}
_fireplaceLines[var - 17] |= bitmask;
@@ -1251,7 +1256,7 @@ void Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv)
void Myst::o_imagerEraseButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager erase button", op);
- _imagerRedButton = static_cast<MystResourceType8 *>(_invokingResource->_parent);
+ _imagerRedButton = static_cast<MystAreaImageSwitch *>(getInvokingResource<MystArea>()->_parent);
for (uint i = 0; i < 4; i++)
_imagerSound[i] = argv[i];
_imagerValidationCard = argv[4];
@@ -1351,7 +1356,7 @@ void Myst::o_towerElevatorAnimation(uint16 op, uint16 var, uint16 argc, uint16 *
void Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator button pressed", op);
- MystResource *button = _invokingResource->_parent;
+ MystArea *button = getInvokingResource<MystArea>()->_parent;
generatorRedrawRocket();
@@ -1376,7 +1381,7 @@ void Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *
if (_generatorVoltage)
_vm->_sound->replaceSoundMyst(6297);
else {
- _vm->_sound->replaceSoundMyst(7297); // TODO: Replace with play sound and replace background 4297
+ _vm->_sound->replaceSoundMyst(7297);
_vm->_sound->replaceBackgroundMyst(4297);
}
@@ -1385,7 +1390,7 @@ void Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *
}
// Redraw button
- _vm->redrawArea(button->getType8Var());
+ _vm->redrawArea(button->getImageSwitchVar());
// Blow breaker
if (_state.generatorVoltage > 59)
@@ -1398,8 +1403,8 @@ void Myst::generatorRedrawRocket() {
_vm->redrawArea(97);
}
-void Myst::generatorButtonValue(MystResource *button, uint16 &mask, uint16 &value) {
- switch (button->getType8Var()) {
+void Myst::generatorButtonValue(MystArea *button, uint16 &mask, uint16 &value) {
+ switch (button->getImageSwitchVar()) {
case 52: // Generator Switch #1
mask = 1;
value = 10;
@@ -1466,7 +1471,7 @@ void Myst::o_cabinSafeHandleStartMove(uint16 op, uint16 var, uint16 argc, uint16
debugC(kDebugScript, "Opcode %d: Cabin safe handle start move", op);
// Used on Card 4100
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
handle->drawFrame(0);
_vm->_cursor->setCursor(700);
_tempVar = 0;
@@ -1476,7 +1481,7 @@ void Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *arg
debugC(kDebugScript, "Opcode %d: Cabin safe handle move", op);
// Used on Card 4100
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
if (handle->pullLeverV()) {
// Sound not played yet
@@ -1506,7 +1511,7 @@ void Myst::o_cabinSafeHandleEndMove(uint16 op, uint16 var, uint16 argc, uint16 *
debugC(kDebugScript, "Opcode %d: Cabin safe handle end move", op);
// Used on Card 4100
- MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *handle = getInvokingResource<MystVideoInfo>();
handle->drawFrame(0);
_vm->checkCursorHints();
}
@@ -1804,7 +1809,7 @@ void Myst::o_observatoryTimeSliderMove(uint16 op, uint16 var, uint16 argc, uint1
void Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker start move", op);
- MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *breaker = getInvokingResource<MystVideoInfo>();
breaker->drawFrame(0);
_vm->_cursor->setCursor(700);
_tempVar = 0;
@@ -1813,7 +1818,7 @@ void Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uint16 argc, uint16
void Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker move", op);
- MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *breaker = getInvokingResource<MystVideoInfo>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
int16 maxStep = breaker->getStepsV() - 1;
@@ -1828,7 +1833,7 @@ void Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv
// Breaker switched
if (step == maxStep) {
// Choose breaker
- if (breaker->getType8Var() == 93) {
+ if (breaker->getImageSwitchVar() == 93) {
// Voltage is still too high or not broken
if (_state.generatorVoltage > 59 || _state.generatorBreakers != 1) {
uint16 soundId = breaker->getList2(1);
@@ -1864,8 +1869,8 @@ void Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv
void Myst::o_circuitBreakerEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Circuit breaker end move", op);
- MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
- _vm->redrawArea(breaker->getType8Var());
+ MystVideoInfo *breaker = getInvokingResource<MystVideoInfo>();
+ _vm->redrawArea(breaker->getImageSwitchVar());
_vm->checkCursorHints();
}
@@ -2138,7 +2143,7 @@ void Myst::tree_run() {
// Check if alcove is accessible
treeSetAlcoveAccessible();
- if (_cabinGaugeMovie) {
+ if (_cabinGaugeMovieEnabled) {
Common::Rational rate = boilerComputeGaugeRate(pressure, delay);
boilerResetGauge(rate);
}
@@ -2187,22 +2192,22 @@ void Myst::o_rocketSoundSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16
if (_state.generatorVoltage == 59 && !_state.generatorBreakers && _rocketSliderSound)
_vm->_sound->stopSound();
- if (_invokingResource == _rocketSlider1)
+ if (getInvokingResource<MystArea>() == _rocketSlider1)
_state.rocketSliderPosition[0] = _rocketSlider1->_pos.y;
- else if (_invokingResource == _rocketSlider2)
+ else if (getInvokingResource<MystArea>() == _rocketSlider2)
_state.rocketSliderPosition[1] = _rocketSlider2->_pos.y;
- else if (_invokingResource == _rocketSlider3)
+ else if (getInvokingResource<MystArea>() == _rocketSlider3)
_state.rocketSliderPosition[2] = _rocketSlider3->_pos.y;
- else if (_invokingResource == _rocketSlider4)
+ else if (getInvokingResource<MystArea>() == _rocketSlider4)
_state.rocketSliderPosition[3] = _rocketSlider4->_pos.y;
- else if (_invokingResource == _rocketSlider5)
+ else if (getInvokingResource<MystArea>() == _rocketSlider5)
_state.rocketSliderPosition[4] = _rocketSlider5->_pos.y;
_vm->_sound->resumeBackgroundMyst();
}
void Myst::rocketSliderMove() {
- MystResourceType10 *slider = static_cast<MystResourceType10 *>(_invokingResource);
+ MystAreaSlider *slider = getInvokingResource<MystAreaSlider>();
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
uint16 soundId = rocketSliderGetSound(slider->_pos.y);
@@ -2262,7 +2267,7 @@ void Myst::rocketCheckSolution() {
if (solved) {
// Reset lever position
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
// Book appearing
@@ -2299,17 +2304,17 @@ void Myst::rocketCheckSolution() {
void Myst::o_rocketPianoStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket piano start move", op);
- MystResourceType11 *key = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *key = getInvokingResource<MystAreaDrag>();
// What the hell??
- Common::Rect src = key->_subImages[1].rect;
- Common::Rect rect = key->_subImages[0].rect;
+ Common::Rect src = key->getSubImage(1).rect;
+ Common::Rect rect = key->getSubImage(0).rect;
Common::Rect dest = rect;
dest.top = 332 - rect.bottom;
dest.bottom = 332 - rect.top;
// Draw pressed piano key
- _vm->_gfx->copyImageSectionToScreen(key->_subImages[1].wdib, src, dest);
+ _vm->_gfx->copyImageSectionToScreen(key->getSubImage(1).wdib, src, dest);
_vm->_system->updateScreen();
// Play note
@@ -2326,29 +2331,29 @@ void Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
Common::Rect piano = Common::Rect(85, 123, 460, 270);
// Unpress previous key
- MystResourceType11 *key = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *key = getInvokingResource<MystAreaDrag>();
- Common::Rect src = key->_subImages[0].rect;
+ Common::Rect src = key->getSubImage(0).rect;
Common::Rect dest = src;
dest.top = 332 - src.bottom;
dest.bottom = 332 - src.top;
// Draw unpressed piano key
- _vm->_gfx->copyImageSectionToScreen(key->_subImages[0].wdib, src, dest);
+ _vm->_gfx->copyImageSectionToScreen(key->getSubImage(0).wdib, src, dest);
if (piano.contains(mouse)) {
- MystResource *resource = _vm->updateCurrentResource();
- if (resource && resource->type == kMystDragArea) {
+ MystArea *resource = _vm->updateCurrentResource();
+ if (resource && resource->type == kMystAreaDrag) {
// Press new key
- key = static_cast<MystResourceType11 *>(resource);
- src = key->_subImages[1].rect;
- Common::Rect rect = key->_subImages[0].rect;
+ key = static_cast<MystAreaDrag *>(resource);
+ src = key->getSubImage(1).rect;
+ Common::Rect rect = key->getSubImage(0).rect;
dest = rect;
dest.top = 332 - rect.bottom;
dest.bottom = 332 - rect.top;
// Draw pressed piano key
- _vm->_gfx->copyImageSectionToScreen(key->_subImages[1].wdib, src, dest);
+ _vm->_gfx->copyImageSectionToScreen(key->getSubImage(1).wdib, src, dest);
// Play note
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
@@ -2368,15 +2373,15 @@ void Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
void Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket piano end move", op);
- MystResourceType8 *key = static_cast<MystResourceType8 *>(_invokingResource);
+ MystAreaImageSwitch *key = getInvokingResource<MystAreaImageSwitch>();
- Common::Rect &src = key->_subImages[0].rect;
+ Common::Rect src = key->getSubImage(0).rect;
Common::Rect dest = src;
dest.top = 332 - src.bottom;
dest.bottom = 332 - src.top;
// Draw unpressed piano key
- _vm->_gfx->copyImageSectionToScreen(key->_subImages[0].wdib, src, dest);
+ _vm->_gfx->copyImageSectionToScreen(key->getSubImage(0).wdib, src, dest);
_vm->_system->updateScreen();
_vm->_sound->stopSound();
@@ -2386,7 +2391,7 @@ void Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
void Myst::o_rocketLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever start move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
_vm->_cursor->setCursor(700);
_rocketLeverPosition = 0;
@@ -2406,7 +2411,7 @@ void Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
void Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
// Make the lever follow the mouse
@@ -2435,7 +2440,7 @@ void Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
void Myst::o_rocketLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket lever end move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
_vm->checkCursorHints();
_rocketLeverPosition = 0;
@@ -2712,7 +2717,7 @@ void Myst::clockWheel_run() {
}
void Myst::clockWheelStartTurn(uint16 wheel) {
- MystResourceType11 *resource = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *resource = getInvokingResource<MystAreaDrag>();
uint16 soundId = resource->getList1(0);
if (soundId)
@@ -2835,10 +2840,10 @@ void Myst::o_observatoryChangeSettingStop(uint16 op, uint16 var, uint16 argc, ui
_observatoryIncrement = 0;
// Restore button and slider
- _vm->_gfx->copyBackBufferToScreen(_invokingResource->getRect());
+ _vm->_gfx->copyBackBufferToScreen(getInvokingResource<MystArea>()->getRect());
if (_observatoryCurrentSlider) {
_vm->redrawResource(_observatoryCurrentSlider);
- _observatoryCurrentSlider = 0;
+ _observatoryCurrentSlider = nullptr;
}
_vm->_sound->resumeBackgroundMyst();
}
@@ -2874,7 +2879,7 @@ void Myst::o_imagerEraseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
void Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock lever start move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
_vm->_cursor->setCursor(700);
_clockMiddleGearMovedAlone = false;
@@ -2885,7 +2890,7 @@ void Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock left lever move", op);
if (!_clockLeverPulled) {
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// If lever pulled
if (lever->pullLeverV()) {
@@ -2977,7 +2982,7 @@ void Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv)
_vm->_sound->replaceSoundMyst(8113);
// Release lever
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->releaseLeverV();
// Check if puzzle is solved
@@ -3021,7 +3026,7 @@ void Myst::clockGearsCheckSolution() {
void Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock reset lever start move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->drawFrame(0);
_vm->_cursor->setCursor(700);
}
@@ -3029,7 +3034,7 @@ void Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16
void Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Clock reset lever move", op);
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
// If pulled
if (lever->pullLeverV() && _clockWeightPosition != 0)
@@ -3125,7 +3130,7 @@ void Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *
debugC(kDebugScript, "Opcode %d: Clock reset lever end move", op);
// Get current lever frame
- MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ MystVideoInfo *lever = getInvokingResource<MystVideoInfo>();
lever->releaseLeverV();
@@ -3189,8 +3194,8 @@ void Myst::towerRotationMap_run() {
void Myst::o_towerRotationMap_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_towerRotationMapRunning = true;
- _towerRotationMapTower = static_cast<MystResourceType11 *>(_invokingResource);
- _towerRotationMapLabel = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
+ _towerRotationMapTower = getInvokingResource<MystAreaImageSwitch>();
+ _towerRotationMapLabel = _vm->getViewResource<MystAreaImageSwitch>(argv[0]);
_tempVar = 0;
_startTime = 0;
_towerRotationMapClicked = false;
@@ -3202,7 +3207,7 @@ void Myst::towerRotationDrawBuildings() {
// Draw other resources
for (uint i = 1; i <= 10; i++) {
- MystResourceType8 *resource = static_cast<MystResourceType8 *>(_vm->_resources[i]);
+ MystAreaImageSwitch *resource = _vm->getViewResource<MystAreaImageSwitch>(i);
_vm->redrawResource(resource, false);
}
}
@@ -3313,7 +3318,7 @@ void Myst::o_forechamberDoor_init(uint16 op, uint16 var, uint16 argc, uint16 *ar
void Myst::o_shipAccess_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Enable acces to the ship
if (_state.shipFloating) {
- _invokingResource->setEnabled(true);
+ getInvokingResource<MystArea>()->setEnabled(true);
}
}
@@ -3322,7 +3327,7 @@ void Myst::o_butterflies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv)
// Used for Card 4256 (Butterfly Movie Activation)
if (!_butterfliesMoviePlayed) {
- MystResourceType6 *butterflies = static_cast<MystResourceType6 *>(_invokingResource);
+ MystAreaVideo *butterflies = getInvokingResource<MystAreaVideo>();
butterflies->playMovie();
_butterfliesMoviePlayed = true;
@@ -3333,8 +3338,8 @@ void Myst::o_imager_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Imager init", op);
debugC(kDebugScript, "Var: %d", var);
- MystResourceType7 *select = static_cast<MystResourceType7 *>(_invokingResource);
- _imagerMovie = static_cast<MystResourceType6 *>(select->getSubResource(getVar(var)));
+ MystAreaActionSwitch *select = getInvokingResource<MystAreaActionSwitch>();
+ _imagerMovie = static_cast<MystAreaVideo *>(select->getSubResource(getVar(var)));
_imagerRunning = true;
}
@@ -3377,8 +3382,8 @@ void Myst::libraryBookcaseTransform_run(void) {
void Myst::o_libraryBookcaseTransform_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
if (_libraryBookcaseChanged) {
- MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource);
- _libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(0)));
+ MystAreaActionSwitch *resource = getInvokingResource<MystAreaActionSwitch>();
+ _libraryBookcaseMovie = static_cast<MystAreaVideo *>(resource->getSubResource(getVar(0)));
_libraryBookcaseSoundId = argv[0];
_libraryBookcaseMoving = true;
}
@@ -3471,17 +3476,17 @@ void Myst::o_observatory_init(uint16 op, uint16 var, uint16 argc, uint16 *argv)
_tempVar = 0;
_observatoryNotInitialized = true;
- _observatoryVisualizer = static_cast<MystResourceType8 *>(_invokingResource);
- _observatoryGoButton = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
+ _observatoryVisualizer = getInvokingResource<MystAreaImageSwitch>();
+ _observatoryGoButton = _vm->getViewResource<MystAreaImageSwitch>(argv[0]);
if (observatoryIsDDMMYYYY2400()) {
- _observatoryDaySlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
- _observatoryMonthSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
+ _observatoryDaySlider = _vm->getViewResource<MystAreaSlider>(argv[1]);
+ _observatoryMonthSlider = _vm->getViewResource<MystAreaSlider>(argv[2]);
} else {
- _observatoryMonthSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
- _observatoryDaySlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
+ _observatoryMonthSlider = _vm->getViewResource<MystAreaSlider>(argv[1]);
+ _observatoryDaySlider = _vm->getViewResource<MystAreaSlider>(argv[2]);
}
- _observatoryYearSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[3]]);
- _observatoryTimeSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[4]]);
+ _observatoryYearSlider = _vm->getViewResource<MystAreaSlider>(argv[3]);
+ _observatoryTimeSlider = _vm->getViewResource<MystAreaSlider>(argv[4]);
// Set date selection sliders position
_observatoryDaySlider->setPosition(_state.observatoryDaySlider);
@@ -3503,18 +3508,14 @@ bool Myst::observatoryIsDDMMYYYY2400() {
}
void Myst::observatoryUpdateVisualizer(uint16 x, uint16 y) {
- Common::Rect &visu0 = _observatoryVisualizer->_subImages[0].rect;
- Common::Rect &visu1 = _observatoryVisualizer->_subImages[1].rect;
-
- visu0.left = x;
- visu0.right = visu0.left + 105;
- visu0.bottom = 512 - y;
- visu0.top = visu0.bottom - 106;
+ Common::Rect visu;
+ visu.left = x;
+ visu.right = visu.left + 105;
+ visu.bottom = 512 - y;
+ visu.top = visu.bottom - 106;
- visu1.left = visu0.left;
- visu1.top = visu0.top;
- visu1.right = visu0.right;
- visu1.bottom = visu0.bottom;
+ _observatoryVisualizer->setSubImageRect(0, visu);
+ _observatoryVisualizer->setSubImageRect(1, visu);
}
void Myst::observatorySetTargetToSetting() {
@@ -3618,13 +3619,13 @@ void Myst::gullsFly2_run() {
void Myst::o_treeCard_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Enter tree card", op);
- _tree = static_cast<MystResourceType8 *>(_invokingResource);
+ _tree = getInvokingResource<MystAreaImageSwitch>();
}
void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Enter tree card with entry", op);
- _treeAlcove = static_cast<MystResourceType5 *>(_invokingResource);
+ _treeAlcove = getInvokingResource<MystArea>();
_treeMinAccessiblePosition = argv[0];
_treeMaxAccessiblePosition = argv[1];
@@ -3703,16 +3704,18 @@ void Myst::boilerGaugeInit() {
frame = Audio::Timestamp(0, 0, 600);
_vm->_video->drawVideoFrame(_cabinGaugeMovie, frame);
+
+ _cabinGaugeMovieEnabled = true;
}
void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Rocket sliders init", op);
- _rocketSlider1 = static_cast<MystResourceType10 *>(_vm->_resources[argv[0]]);
- _rocketSlider2 = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
- _rocketSlider3 = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
- _rocketSlider4 = static_cast<MystResourceType10 *>(_vm->_resources[argv[3]]);
- _rocketSlider5 = static_cast<MystResourceType10 *>(_vm->_resources[argv[4]]);
+ _rocketSlider1 = _vm->getViewResource<MystAreaSlider>(argv[0]);
+ _rocketSlider2 = _vm->getViewResource<MystAreaSlider>(argv[1]);
+ _rocketSlider3 = _vm->getViewResource<MystAreaSlider>(argv[2]);
+ _rocketSlider4 = _vm->getViewResource<MystAreaSlider>(argv[3]);
+ _rocketSlider5 = _vm->getViewResource<MystAreaSlider>(argv[4]);
// Initialize sliders position
for (uint i = 0; i < 5; i++)
@@ -3828,13 +3831,13 @@ void Myst::o_bookAddSpecialPage_exit(uint16 op, uint16 var, uint16 argc, uint16
void Myst::o_treeCard_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Exit tree card", op);
- _tree = 0;
+ _tree = nullptr;
}
void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Exit tree card with entry", op);
- _treeAlcove = 0;
+ _treeAlcove = nullptr;
}
void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
@@ -3842,6 +3845,8 @@ void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_cabinGaugeMovie = VideoHandle();
_cabinFireMovie = VideoHandle();
+
+ _cabinGaugeMovieEnabled = false;
}
void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index a83609f640..6e2f7cc1c8 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -40,21 +40,20 @@ public:
Myst(MohawkEngine_Myst *vm);
~Myst();
- virtual void disablePersistentScripts();
- virtual void runPersistentScripts();
+ virtual void disablePersistentScripts() override;
+ virtual void runPersistentScripts() override;
protected:
void setupOpcodes();
- uint16 getVar(uint16 var);
- void toggleVar(uint16 var);
- bool setVarValue(uint16 var, uint16 value);
+ uint16 getVar(uint16 var) override;
+ void toggleVar(uint16 var) override;
+ bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() { return 9934; }
+ virtual uint16 getMap() override { return 9934; }
void towerRotationMap_run();
virtual void libraryBookcaseTransform_run();
void generatorControlRoom_run();
- void opcode_212_run();
void libraryCombinationBook_run();
void clockWheel_run();
void matchBurn_run();
@@ -192,11 +191,11 @@ protected:
bool _generatorControlRoomRunning;
uint16 _generatorVoltage; // 58
- MystResourceType10 *_rocketSlider1; // 248
- MystResourceType10 *_rocketSlider2; // 252
- MystResourceType10 *_rocketSlider3; // 256
- MystResourceType10 *_rocketSlider4; // 260
- MystResourceType10 *_rocketSlider5; // 264
+ MystAreaSlider *_rocketSlider1; // 248
+ MystAreaSlider *_rocketSlider2; // 252
+ MystAreaSlider *_rocketSlider3; // 256
+ MystAreaSlider *_rocketSlider4; // 260
+ MystAreaSlider *_rocketSlider5; // 264
uint16 _rocketSliderSound; // 294
uint16 _rocketLeverPosition; // 296
VideoHandle _rocketLinkBook;
@@ -214,7 +213,7 @@ protected:
uint32 _gullsNextTime; // 216
bool _libraryBookcaseMoving;
- MystResourceType6 *_libraryBookcaseMovie; // 104
+ MystAreaVideo *_libraryBookcaseMovie; // 104
uint16 _libraryBookcaseSoundId; // 284
bool _libraryBookcaseChanged; // 288
uint16 _libraryBookSound1; // 298
@@ -223,13 +222,13 @@ protected:
uint16 _courtyardBoxSound; // 302
bool _imagerValidationRunning;
- MystResourceType8 *_imagerRedButton; // 304
+ MystAreaImageSwitch *_imagerRedButton; // 304
uint16 _imagerSound[4]; // 308 to 314
uint16 _imagerValidationCard; // 316
uint16 _imagerValidationStep; // 318
bool _imagerRunning;
- MystResourceType6 *_imagerMovie; // 64
+ MystAreaVideo *_imagerMovie; // 64
uint16 _fireplaceLines[6]; // 74 to 84
@@ -248,8 +247,8 @@ protected:
bool _towerRotationBlinkLabel;
uint16 _towerRotationBlinkLabelCount;
uint16 _towerRotationMapInitialized; // 292
- MystResourceType11 *_towerRotationMapTower; // 108
- MystResourceType8 *_towerRotationMapLabel; // 112
+ MystAreaImageSwitch *_towerRotationMapTower; // 108
+ MystAreaImageSwitch *_towerRotationMapLabel; // 112
uint16 _towerRotationSpeed; // 124
bool _towerRotationMapClicked; // 132
bool _towerRotationOverSpot; // 136
@@ -257,10 +256,13 @@ protected:
bool _matchBurning;
uint16 _matchGoOutCnt;
uint16 _cabinDoorOpened; // 56
+ uint16 _cabinHandleDown; // 344
uint16 _cabinMatchState; // 60
uint32 _matchGoOutTime; // 144
VideoHandle _cabinFireMovie; // 240
+
+ bool _cabinGaugeMovieEnabled;
VideoHandle _cabinGaugeMovie; // 244
bool _boilerPressureIncreasing;
@@ -269,8 +271,8 @@ protected:
bool _basementPressureDecreasing;
bool _treeStopped; // 236
- MystResourceType8 *_tree; // 220
- MystResourceType5 *_treeAlcove; // 224
+ MystAreaImageSwitch *_tree; // 220
+ MystArea *_treeAlcove; // 224
uint16 _treeMinPosition; // 228
uint16 _treeMinAccessiblePosition; // 230
uint16 _treeMaxAccessiblePosition; // 232
@@ -280,21 +282,21 @@ protected:
bool _observatoryDayChanging;
bool _observatoryYearChanging;
bool _observatoryTimeChanging;
- MystResourceType8 *_observatoryVisualizer; // 184
- MystResourceType8 *_observatoryGoButton; // 188
- MystResourceType10 *_observatoryDaySlider; // 192
- MystResourceType10 *_observatoryMonthSlider; // 196
- MystResourceType10 *_observatoryYearSlider; // 200
- MystResourceType10 *_observatoryTimeSlider; // 204
+ MystAreaImageSwitch *_observatoryVisualizer; // 184
+ MystAreaImageSwitch *_observatoryGoButton; // 188
+ MystAreaSlider *_observatoryDaySlider; // 192
+ MystAreaSlider *_observatoryMonthSlider; // 196
+ MystAreaSlider *_observatoryYearSlider; // 200
+ MystAreaSlider *_observatoryTimeSlider; // 204
uint32 _observatoryLastTime; // 208
bool _observatoryNotInitialized; // 212
int16 _observatoryIncrement; // 346
- MystResourceType10 *_observatoryCurrentSlider; // 348
+ MystAreaSlider *_observatoryCurrentSlider; // 348
bool _greenBookRunning;
void generatorRedrawRocket();
- void generatorButtonValue(MystResource *button, uint16 &offset, uint16 &value);
+ void generatorButtonValue(MystArea *button, uint16 &offset, uint16 &value);
void rocketSliderMove();
uint16 rocketSliderGetSound(uint16 pos);
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index 4cae4aaca7..42458758f5 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -239,13 +239,13 @@ void Preview::o_library_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Library init", op);
// Used for Card 3002 (Myst Island Overview)
- _library = static_cast<MystResourceType8 *>(_invokingResource);
+ _library = getInvokingResource<MystAreaImageSwitch>();
}
void Preview::o_libraryBookcaseTransformDemo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
if (_libraryBookcaseChanged) {
- MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource);
- _libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(303)));
+ MystAreaActionSwitch *resource = getInvokingResource<MystAreaActionSwitch>();
+ _libraryBookcaseMovie = static_cast<MystAreaVideo *>(resource->getSubResource(getVar(303)));
_libraryBookcaseSoundId = argv[0];
_libraryBookcaseMoving = true;
}
diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h
index 0959e935f5..9d833b35e2 100644
--- a/engines/mohawk/myst_stacks/preview.h
+++ b/engines/mohawk/myst_stacks/preview.h
@@ -40,8 +40,8 @@ public:
Preview(MohawkEngine_Myst *vm);
~Preview();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
@@ -56,7 +56,7 @@ private:
DECLARE_OPCODE(o_library_init);
uint16 _libraryState; // 4
- MystResourceType8 *_library; // 32
+ MystAreaImageSwitch *_library; // 32
bool _speechRunning;
uint _speechStep;
@@ -67,7 +67,7 @@ private:
void speech_run();
void speechUpdateCue();
- void libraryBookcaseTransform_run();
+ void libraryBookcaseTransform_run() override;
};
} // End of namespace MystStacks
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 8b95c7fa53..5402e5a581 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -39,9 +39,12 @@ namespace MystStacks {
Selenitic::Selenitic(MohawkEngine_Myst *vm) :
MystScriptParser(vm), _state(vm->_gameState->_selenitic) {
setupOpcodes();
- _invokingResource = NULL;
_mazeRunnerPosition = 288;
_mazeRunnerDirection = 8;
+ _mazeRunnerDoorOpened = false;
+
+ _soundReceiverDirection = 0;
+ _soundReceiverStartTime = 0;
}
Selenitic::~Selenitic() {
@@ -669,14 +672,20 @@ void Selenitic::soundReceiverUpdate() {
}
void Selenitic::soundReceiverDrawView() {
+ soundReceiverSetSubimageRect();
+ soundReceiverDrawAngle();
+}
+
+void Selenitic::soundReceiverSetSubimageRect() const {
uint32 left = ((*_soundReceiverPosition) * 1800) / 3600;
- _soundReceiverViewer->_subImages->rect.left = left;
- _soundReceiverViewer->_subImages->rect.right = left + 136;
+ Common::Rect rect = _soundReceiverViewer->getSubImage(0).rect;
- _soundReceiverViewer->drawConditionalDataToScreen(0);
+ rect.left = left;
+ rect.right = left + 136;
- soundReceiverDrawAngle();
+ _soundReceiverViewer->setSubImageRect(0, rect);
+ _soundReceiverViewer->drawConditionalDataToScreen(0);
}
void Selenitic::soundReceiverDrawAngle() {
@@ -770,7 +779,7 @@ uint16 Selenitic::soundLockCurrentSound(uint16 position, bool pixels) {
return 0;
}
-MystResourceType10 *Selenitic::soundLockSliderFromVar(uint16 var) {
+MystAreaSlider *Selenitic::soundLockSliderFromVar(uint16 var) {
switch (var) {
case 20:
return _soundLockSlider1;
@@ -784,13 +793,13 @@ MystResourceType10 *Selenitic::soundLockSliderFromVar(uint16 var) {
return _soundLockSlider5;
}
- return 0;
+ return nullptr;
}
void Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock move", op);
- MystResourceType10 *slider = soundLockSliderFromVar(var);
+ MystAreaSlider *slider = soundLockSliderFromVar(var);
uint16 soundId = soundLockCurrentSound(slider->_pos.y, true);
if (_soundLockSoundId != soundId) {
@@ -802,7 +811,7 @@ void Selenitic::o_soundLockMove(uint16 op, uint16 var, uint16 argc, uint16 *argv
void Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock start move", op);
- MystResourceType10 *slider = soundLockSliderFromVar(var);
+ MystAreaSlider *slider = soundLockSliderFromVar(var);
_vm->_cursor->setCursor(700);
_vm->_sound->pauseBackgroundMyst();
@@ -814,7 +823,7 @@ void Selenitic::o_soundLockStartMove(uint16 op, uint16 var, uint16 argc, uint16
void Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Sound lock end move", op);
- MystResourceType10 *slider = soundLockSliderFromVar(var);
+ MystAreaSlider *slider = soundLockSliderFromVar(var);
uint16 *value = &_state.soundLockSliderPositions[0];
switch (var) {
@@ -858,7 +867,7 @@ void Selenitic::o_soundLockEndMove(uint16 op, uint16 var, uint16 argc, uint16 *a
_vm->_sound->resumeBackgroundMyst();
}
-void Selenitic::soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved) {
+void Selenitic::soundLockCheckSolution(MystAreaSlider *slider, uint16 value, uint16 solution, bool &solved) {
slider->drawConditionalDataToScreen(2);
_vm->_sound->replaceSoundMyst(soundLockCurrentSound(value / 12, false));
_vm->_system->delayMillis(1500);
@@ -926,15 +935,15 @@ void Selenitic::o_soundReceiverEndMove(uint16 op, uint16 var, uint16 argc, uint1
}
void Selenitic::o_mazeRunnerCompass_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _mazeRunnerCompass = static_cast<MystResourceType8 *>(_invokingResource);
+ _mazeRunnerCompass = getInvokingResource<MystAreaImageSwitch>();
}
void Selenitic::o_mazeRunnerWindow_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _mazeRunnerWindow = static_cast<MystResourceType8 *>(_invokingResource);
+ _mazeRunnerWindow = getInvokingResource<MystAreaImageSwitch>();
}
void Selenitic::o_mazeRunnerLight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _mazeRunnerLight = static_cast<MystResourceType8 *>(_invokingResource);
+ _mazeRunnerLight = getInvokingResource<MystAreaImageSwitch>();
}
void Selenitic::soundReceiver_run() {
@@ -942,10 +951,13 @@ void Selenitic::soundReceiver_run() {
if (_soundReceiverDirection) {
uint32 currentTime = _vm->_system->getMillis();
- if (_soundReceiverSpeed == 50 && currentTime > _soundReceiverStartTime + 500)
- soundReceiverIncreaseSpeed();
- else if (currentTime > _soundReceiverStartTime + 1000)
- soundReceiverIncreaseSpeed();
+ if (_soundReceiverSpeed == 50 && currentTime > _soundReceiverStartTime + 500) {
+ soundReceiverIncreaseSpeed();
+ _soundReceiverStartTime = currentTime;
+ } else if (currentTime > _soundReceiverStartTime + 1000) {
+ soundReceiverIncreaseSpeed();
+ _soundReceiverStartTime = currentTime;
+ }
if (currentTime > _soundReceiverStartTime + 100)
soundReceiverUpdate();
@@ -1056,24 +1068,26 @@ void Selenitic::o_soundReceiver_init(uint16 op, uint16 var, uint16 argc, uint16
// Used for Card 1245 (Sound Receiver)
_soundReceiverRunning = true;
- _soundReceiverRightButton = static_cast<MystResourceType8 *>(_vm->_resources[0]);
- _soundReceiverLeftButton = static_cast<MystResourceType8 *>(_vm->_resources[1]);
- _soundReceiverSigmaButton = static_cast<MystResourceType8 *>(_vm->_resources[2]);
- _soundReceiverSources[4] = static_cast<MystResourceType8 *>(_vm->_resources[3]);
- _soundReceiverSources[3] = static_cast<MystResourceType8 *>(_vm->_resources[4]);
- _soundReceiverSources[2] = static_cast<MystResourceType8 *>(_vm->_resources[5]);
- _soundReceiverSources[1] = static_cast<MystResourceType8 *>(_vm->_resources[6]);
- _soundReceiverSources[0] = static_cast<MystResourceType8 *>(_vm->_resources[7]);
- _soundReceiverViewer = static_cast<MystResourceType8 *>(_vm->_resources[8]);
- _soundReceiverAngle1 = static_cast<MystResourceType8 *>(_vm->_resources[10]);
- _soundReceiverAngle2 = static_cast<MystResourceType8 *>(_vm->_resources[11]);
- _soundReceiverAngle3 = static_cast<MystResourceType8 *>(_vm->_resources[12]);
- _soundReceiverAngle4 = static_cast<MystResourceType8 *>(_vm->_resources[13]);
+ _soundReceiverRightButton = _vm->getViewResource<MystAreaImageSwitch>(0);
+ _soundReceiverLeftButton = _vm->getViewResource<MystAreaImageSwitch>(1);
+ _soundReceiverSigmaButton = _vm->getViewResource<MystAreaImageSwitch>(2);
+ _soundReceiverSources[4] = _vm->getViewResource<MystAreaImageSwitch>(3);
+ _soundReceiverSources[3] = _vm->getViewResource<MystAreaImageSwitch>(4);
+ _soundReceiverSources[2] = _vm->getViewResource<MystAreaImageSwitch>(5);
+ _soundReceiverSources[1] = _vm->getViewResource<MystAreaImageSwitch>(6);
+ _soundReceiverSources[0] = _vm->getViewResource<MystAreaImageSwitch>(7);
+ _soundReceiverViewer = _vm->getViewResource<MystAreaImageSwitch>(8);
+ _soundReceiverAngle1 = _vm->getViewResource<MystAreaImageSwitch>(10);
+ _soundReceiverAngle2 = _vm->getViewResource<MystAreaImageSwitch>(11);
+ _soundReceiverAngle3 = _vm->getViewResource<MystAreaImageSwitch>(12);
+ _soundReceiverAngle4 = _vm->getViewResource<MystAreaImageSwitch>(13);
uint16 currentSource = _state.soundReceiverCurrentSource;
_soundReceiverPosition = &_state.soundReceiverPositions[currentSource];
_soundReceiverCurrentSource = _soundReceiverSources[currentSource];
+ soundReceiverSetSubimageRect();
+
_soundReceiverSigmaPressed = false;
}
@@ -1081,31 +1095,31 @@ void Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16 argc, uint16 *arg
debugC(kDebugScript, "Opcode %d: Sound lock init", op);
for (uint i = 0; i < _vm->_resources.size(); i++) {
- if (_vm->_resources[i]->type == kMystSlider) {
- switch (_vm->_resources[i]->getType8Var()) {
+ if (_vm->_resources[i]->type == kMystAreaSlider) {
+ switch (_vm->_resources[i]->getImageSwitchVar()) {
case 20:
- _soundLockSlider1 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider1 = _vm->getViewResource<MystAreaSlider>(i);
_soundLockSlider1->setStep(_state.soundLockSliderPositions[0]);
break;
case 21:
- _soundLockSlider2 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider2 = _vm->getViewResource<MystAreaSlider>(i);
_soundLockSlider2->setStep(_state.soundLockSliderPositions[1]);
break;
case 22:
- _soundLockSlider3 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider3 = _vm->getViewResource<MystAreaSlider>(i);
_soundLockSlider3->setStep(_state.soundLockSliderPositions[2]);
break;
case 23:
- _soundLockSlider4 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider4 = _vm->getViewResource<MystAreaSlider>(i);
_soundLockSlider4->setStep(_state.soundLockSliderPositions[3]);
break;
case 24:
- _soundLockSlider5 = static_cast<MystResourceType10 *>(_vm->_resources[i]);
+ _soundLockSlider5 = _vm->getViewResource<MystAreaSlider>(i);
_soundLockSlider5->setStep(_state.soundLockSliderPositions[4]);
break;
}
- } else if (_vm->_resources[i]->type == kMystConditionalImage && _vm->_resources[i]->getType8Var() == 28) {
- _soundLockButton = static_cast<MystResourceType8 *>(_vm->_resources[i]);
+ } else if (_vm->_resources[i]->type == kMystAreaImageSwitch && _vm->_resources[i]->getImageSwitchVar() == 28) {
+ _soundLockButton = _vm->getViewResource<MystAreaImageSwitch>(i);
}
}
@@ -1113,11 +1127,11 @@ void Selenitic::o_soundLock_init(uint16 op, uint16 var, uint16 argc, uint16 *arg
}
void Selenitic::o_mazeRunnerRight_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _mazeRunnerRightButton = static_cast<MystResourceType8 *>(_invokingResource);
+ _mazeRunnerRightButton = getInvokingResource<MystAreaImageSwitch>();
}
void Selenitic::o_mazeRunnerLeft_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- _mazeRunnerLeftButton = static_cast<MystResourceType8 *>(_invokingResource);
+ _mazeRunnerLeftButton = getInvokingResource<MystAreaImageSwitch>();
}
const uint16 Selenitic::_mazeRunnerMap[300][4] = {
diff --git a/engines/mohawk/myst_stacks/selenitic.h b/engines/mohawk/myst_stacks/selenitic.h
index c669d01012..fc9649755d 100644
--- a/engines/mohawk/myst_stacks/selenitic.h
+++ b/engines/mohawk/myst_stacks/selenitic.h
@@ -29,7 +29,7 @@
namespace Mohawk {
-class MystResourceType8;
+class MystAreaImageSwitch;
struct MystScriptEntry;
namespace MystStacks {
@@ -41,16 +41,16 @@ public:
Selenitic(MohawkEngine_Myst *vm);
~Selenitic();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
- void toggleVar(uint16 var);
- bool setVarValue(uint16 var, uint16 value);
+ uint16 getVar(uint16 var) override;
+ void toggleVar(uint16 var) override;
+ bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() { return 9930; }
+ virtual uint16 getMap() override { return 9930; }
DECLARE_OPCODE(o_mazeRunnerMove);
DECLARE_OPCODE(o_mazeRunnerSoundRepeat);
@@ -80,43 +80,44 @@ private:
bool _soundReceiverRunning;
bool _soundReceiverSigmaPressed; // 6
- MystResourceType8 *_soundReceiverSources[5]; // 92 -> 108
- MystResourceType8 *_soundReceiverCurrentSource; // 112
+ MystAreaImageSwitch *_soundReceiverSources[5]; // 92 -> 108
+ MystAreaImageSwitch *_soundReceiverCurrentSource; // 112
uint16 *_soundReceiverPosition; // 116
uint16 _soundReceiverDirection; // 120
uint16 _soundReceiverSpeed; // 122
uint32 _soundReceiverStartTime; //124
- MystResourceType8 *_soundReceiverViewer; // 128
- MystResourceType8 *_soundReceiverRightButton; // 132
- MystResourceType8 *_soundReceiverLeftButton; // 136
- MystResourceType8 *_soundReceiverAngle1; // 140
- MystResourceType8 *_soundReceiverAngle2; // 144
- MystResourceType8 *_soundReceiverAngle3; // 148
- MystResourceType8 *_soundReceiverAngle4; // 152
- MystResourceType8 *_soundReceiverSigmaButton; // 156
+ MystAreaImageSwitch *_soundReceiverViewer; // 128
+ MystAreaImageSwitch *_soundReceiverRightButton; // 132
+ MystAreaImageSwitch *_soundReceiverLeftButton; // 136
+ MystAreaImageSwitch *_soundReceiverAngle1; // 140
+ MystAreaImageSwitch *_soundReceiverAngle2; // 144
+ MystAreaImageSwitch *_soundReceiverAngle3; // 148
+ MystAreaImageSwitch *_soundReceiverAngle4; // 152
+ MystAreaImageSwitch *_soundReceiverSigmaButton; // 156
static const uint16 _mazeRunnerMap[300][4];
static const uint8 _mazeRunnerVideos[300][4];
uint16 _mazeRunnerPosition; // 56
uint16 _mazeRunnerDirection; // 58
- MystResourceType8 *_mazeRunnerWindow; // 68
- MystResourceType8 *_mazeRunnerCompass; // 72
- MystResourceType8 *_mazeRunnerLight; // 76
- MystResourceType8 *_mazeRunnerRightButton; // 80
- MystResourceType8 *_mazeRunnerLeftButton; // 84
+ MystAreaImageSwitch *_mazeRunnerWindow; // 68
+ MystAreaImageSwitch *_mazeRunnerCompass; // 72
+ MystAreaImageSwitch *_mazeRunnerLight; // 76
+ MystAreaImageSwitch *_mazeRunnerRightButton; // 80
+ MystAreaImageSwitch *_mazeRunnerLeftButton; // 84
bool _mazeRunnerDoorOpened; // 160
uint16 _soundLockSoundId;
- MystResourceType10 *_soundLockSlider1; // 164
- MystResourceType10 *_soundLockSlider2; // 168
- MystResourceType10 *_soundLockSlider3; // 172
- MystResourceType10 *_soundLockSlider4; // 176
- MystResourceType10 *_soundLockSlider5; // 180
- MystResourceType8 *_soundLockButton; // 184
+ MystAreaSlider *_soundLockSlider1; // 164
+ MystAreaSlider *_soundLockSlider2; // 168
+ MystAreaSlider *_soundLockSlider3; // 172
+ MystAreaSlider *_soundLockSlider4; // 176
+ MystAreaSlider *_soundLockSlider5; // 180
+ MystAreaImageSwitch *_soundLockButton; // 184
void soundReceiverLeftRight(uint direction);
void soundReceiverUpdate();
+ void soundReceiverSetSubimageRect() const;
void soundReceiverDrawView();
void soundReceiverDrawAngle();
void soundReceiverIncreaseSpeed();
@@ -125,8 +126,8 @@ private:
void soundReceiverSolution(uint16 source, uint16 &solution, bool &enabled);
uint16 soundLockCurrentSound(uint16 position, bool pixels);
- MystResourceType10 *soundLockSliderFromVar(uint16 var);
- void soundLockCheckSolution(MystResourceType10 *slider, uint16 value, uint16 solution, bool &solved);
+ MystAreaSlider *soundLockSliderFromVar(uint16 var);
+ void soundLockCheckSolution(MystAreaSlider *slider, uint16 value, uint16 solution, bool &solved);
bool mazeRunnerForwardAllowed(uint16 position);
void mazeRunnerUpdateCompass();
diff --git a/engines/mohawk/myst_stacks/slides.h b/engines/mohawk/myst_stacks/slides.h
index fb7868a03c..a0c9ae5821 100644
--- a/engines/mohawk/myst_stacks/slides.h
+++ b/engines/mohawk/myst_stacks/slides.h
@@ -40,8 +40,8 @@ public:
Slides(MohawkEngine_Myst *vm);
~Slides();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 1113ceeac9..293c0f96f4 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -50,6 +50,8 @@ Stoneship::Stoneship(MohawkEngine_Myst *vm) :
_chestDrawersOpen = 0;
_chestAchenarBottomDrawerClosed = 1;
+ _brotherDoorOpen = 0;
+
// Drop key
if (_state.trapdoorKeyState == 1)
_state.trapdoorKeyState = 2;
@@ -402,9 +404,9 @@ void Stoneship::o_pumpTurnOff(uint16 op, uint16 var, uint16 argc, uint16 *argv)
}
for (uint i = 0; i < _vm->_resources.size(); i++) {
- MystResource *resource = _vm->_resources[i];
- if (resource->type == kMystConditionalImage && resource->getType8Var() == buttonVar) {
- static_cast<MystResourceType8 *>(resource)->drawConditionalDataToScreen(0, true);
+ MystArea *resource = _vm->_resources[i];
+ if (resource->type == kMystAreaImageSwitch && resource->getImageSwitchVar() == buttonVar) {
+ static_cast<MystAreaImageSwitch *>(resource)->drawConditionalDataToScreen(0, true);
break;
}
}
@@ -437,9 +439,9 @@ void Stoneship::o_cabinBookMovie(uint16 op, uint16 var, uint16 argc, uint16 *arg
void Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open drawer", op);
- MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
+ MystAreaImageSwitch *drawer = _vm->getViewResource<MystAreaImageSwitch>(argv[0]);
- if (drawer->getType8Var() == 35) {
+ if (drawer->getImageSwitchVar() == 35) {
drawer->drawConditionalDataToScreen(getVar(102), 0);
} else {
drawer->drawConditionalDataToScreen(0, 0);
@@ -466,7 +468,7 @@ void Stoneship::o_telescopeStart(uint16 op, uint16 var, uint16 argc, uint16 *arg
void Stoneship::o_telescopeMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Telescope move", op);
- MystResourceType11 *display = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *display = getInvokingResource<MystAreaDrag>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
// Compute telescope position
@@ -489,7 +491,7 @@ void Stoneship::o_telescopeStop(uint16 op, uint16 var, uint16 argc, uint16 *argv
void Stoneship::o_generatorStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Generator start", op);
- MystResourceType11 *handle = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *handle = getInvokingResource<MystAreaDrag>();
uint16 soundId = handle->getList1(0);
if (soundId)
@@ -504,7 +506,7 @@ void Stoneship::o_generatorStart(uint16 op, uint16 var, uint16 argc, uint16 *arg
_batteryNextTime = _vm->_system->getMillis() + 1000;
// Start handle movie
- MystResourceType6 *movie = static_cast<MystResourceType6 *>(handle->getSubResource(0));
+ MystAreaVideo *movie = static_cast<MystAreaVideo *>(handle->getSubResource(0));
movie->playMovie();
soundId = handle->getList2(0);
@@ -530,8 +532,8 @@ void Stoneship::o_generatorStop(uint16 op, uint16 var, uint16 argc, uint16 *argv
}
// Pause handle movie
- MystResourceType11 *handle = static_cast<MystResourceType11 *>(_invokingResource);
- MystResourceType6 *movie = static_cast<MystResourceType6 *>(handle->getSubResource(0));
+ MystAreaDrag *handle = getInvokingResource<MystAreaDrag>();
+ MystAreaVideo *movie = static_cast<MystAreaVideo *>(handle->getSubResource(0));
movie->pauseMovie(true);
uint16 soundId = handle->getList3(0);
@@ -582,7 +584,7 @@ void Stoneship::batteryDeplete_run() {
void Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Open drawer", op);
- MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
+ MystAreaImageSwitch *drawer = _vm->getViewResource<MystAreaImageSwitch>(argv[0]);
drawer->drawConditionalDataToScreen(0, 0);
_vm->_gfx->runTransition(kTransitionTopToBottom, drawer->getRect(), 25, 5);
}
@@ -617,7 +619,7 @@ void Stoneship::o_hologramSelectionStart(uint16 op, uint16 var, uint16 argc, uin
void Stoneship::o_hologramSelectionMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram move", op);
- MystResourceType11 *handle = static_cast<MystResourceType11 *>(_invokingResource);
+ MystAreaDrag *handle = getInvokingResource<MystAreaDrag>();
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
if (handle->getRect().contains(mouse)) {
@@ -806,7 +808,7 @@ void Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv
_cloudOrbMovie->pauseMovie(true);
_vm->_sound->replaceSoundMyst(_cloudOrbStopSound);
- _vm->_gfx->runTransition(kTransitionTopToBottom, _invokingResource->getRect(), 4, 0);
+ _vm->_gfx->runTransition(kTransitionTopToBottom, getInvokingResource<MystArea>()->getRect(), 4, 0);
}
void Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
@@ -822,20 +824,20 @@ void Stoneship::drawerClose(uint16 drawer) {
_vm->drawCardBackground();
_vm->drawResourceImages();
- MystResource *res = _vm->_resources[drawer];
+ MystArea *res = _vm->_resources[drawer];
_vm->_gfx->runTransition(kTransitionBottomToTop, res->getRect(), 25, 5);
}
void Stoneship::o_hologramDisplay_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram display init", op);
- _hologramDisplay = static_cast<MystResourceType6 *>(_invokingResource);
+ _hologramDisplay = getInvokingResource<MystAreaVideo>();
_hologramDisplayPos = 0;
}
void Stoneship::o_hologramSelection_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Hologram selection init", op);
- _hologramSelection = static_cast<MystResourceType6 *>(_invokingResource);
+ _hologramSelection = getInvokingResource<MystAreaVideo>();
}
void Stoneship::batteryGaugeUpdate() {
@@ -856,7 +858,7 @@ void Stoneship::o_battery_init(uint16 op, uint16 var, uint16 argc, uint16 *argv)
// Used for Card 2160 (Lighthouse Battery Pack Closeup)
debugC(kDebugScript, "Opcode %d: Battery init", op);
- _batteryGauge = static_cast<MystResourceType8 *>(_invokingResource);
+ _batteryGauge = getInvokingResource<MystAreaImageSwitch>();
batteryGaugeUpdate();
}
@@ -1014,7 +1016,7 @@ void Stoneship::o_achenarDrawers_init(uint16 op, uint16 var, uint16 argc, uint16
void Stoneship::o_cloudOrb_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Cloud orb init", op);
- _cloudOrbMovie = static_cast<MystResourceType6 *>(_invokingResource);
+ _cloudOrbMovie = getInvokingResource<MystAreaVideo>();
_cloudOrbSound = argv[0];
_cloudOrbStopSound = argv[1];
}
diff --git a/engines/mohawk/myst_stacks/stoneship.h b/engines/mohawk/myst_stacks/stoneship.h
index 4e1b42f26b..776641a787 100644
--- a/engines/mohawk/myst_stacks/stoneship.h
+++ b/engines/mohawk/myst_stacks/stoneship.h
@@ -40,16 +40,16 @@ public:
Stoneship(MohawkEngine_Myst *vm);
~Stoneship();
- void disablePersistentScripts();
- void runPersistentScripts();
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
private:
void setupOpcodes();
- uint16 getVar(uint16 var);
- void toggleVar(uint16 var);
- bool setVarValue(uint16 var, uint16 value);
+ uint16 getVar(uint16 var) override;
+ void toggleVar(uint16 var) override;
+ bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() { return 9933; }
+ virtual uint16 getMap() override { return 9933; }
DECLARE_OPCODE(o_pumpTurnOff);
DECLARE_OPCODE(o_brotherDoorOpen);
@@ -98,7 +98,7 @@ private:
bool _batteryGaugeRunning;
uint16 _batteryLastCharge; // 92
- MystResourceType8 *_batteryGauge; // 96
+ MystAreaImageSwitch *_batteryGauge; // 96
void batteryGaugeUpdate();
void batteryGauge_run();
@@ -113,8 +113,8 @@ private:
void drawerClose(uint16 drawer);
uint16 _hologramTurnedOn; // 80
- MystResourceType6 *_hologramDisplay; // 84
- MystResourceType6 *_hologramSelection; // 88
+ MystAreaVideo *_hologramDisplay; // 84
+ MystAreaVideo *_hologramSelection; // 88
uint16 _hologramDisplayPos;
bool _tunnelRunning;
@@ -135,7 +135,7 @@ private:
void telescope_run();
void telescopeLighthouseDraw();
- MystResourceType6 *_cloudOrbMovie; // 136
+ MystAreaVideo *_cloudOrbMovie; // 136
uint16 _cloudOrbSound; // 140
uint16 _cloudOrbStopSound; // 142
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index 3e54017df8..06cd69b23c 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -26,11 +26,41 @@
#include "common/debug.h"
#include "common/serializer.h"
+#include "common/system.h"
#include "common/textconsole.h"
#include "common/util.h"
+#include "graphics/thumbnail.h"
+
namespace Mohawk {
+MystSaveMetadata::MystSaveMetadata() {
+ saveDay = 0;
+ saveMonth = 0;
+ saveYear = 0;
+ saveHour = 0;
+ saveMinute = 0;
+ totalPlayTime = 0;
+}
+
+bool MystSaveMetadata::sync(Common::Serializer &s) {
+ static const Common::Serializer::Version kCurrentVersion = 1;
+
+ if (!s.syncVersion(kCurrentVersion)) {
+ return false;
+ }
+
+ s.syncAsByte(saveDay);
+ s.syncAsByte(saveMonth);
+ s.syncAsUint16LE(saveYear);
+ s.syncAsByte(saveHour);
+ s.syncAsByte(saveMinute);
+ s.syncString(saveDescription);
+ s.syncAsUint32LE(totalPlayTime);
+
+ return true;
+}
+
MystGameState::MystGameState(MohawkEngine_Myst *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
// Most of the variables are zero at game start.
memset(&_globals, 0, sizeof(_globals));
@@ -77,28 +107,15 @@ MystGameState::~MystGameState() {
}
Common::StringArray MystGameState::generateSaveGameList() {
- return _saveFileMan->listSavefiles("*.mys");
+ return g_system->getSavefileManager()->listSavefiles("*.mys");
}
bool MystGameState::load(const Common::String &filename) {
- Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
- if (!loadFile)
- return false;
-
- debugC(kDebugSaveLoad, "Loading game from '%s'", filename.c_str());
-
- // First, let's make sure we're using a saved game file from this version of Myst
- // By checking length of file...
- int32 size = loadFile->size();
- if (size != 664 && size != 601) {
- warning("Incompatible saved game version");
- delete loadFile;
+ if (!loadState(filename)) {
return false;
}
- Common::Serializer s(loadFile, 0);
- syncGameState(s, size == 664);
- delete loadFile;
+ loadMetadata(filename);
// Set Channelwood elevator state to down, because we start on the lower level
_channelwood.elevatorState = 0;
@@ -119,19 +136,76 @@ bool MystGameState::load(const Common::String &filename) {
return true;
}
-bool MystGameState::save(const Common::String &fname) {
- Common::String filename(fname);
- // Make sure we have the right extension
- if (!filename.hasSuffix(".mys") && !filename.hasSuffix(".MYS"))
- filename += ".mys";
+bool MystGameState::loadState(const Common::String &filename) {
+ Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename);
+ if (!loadFile) {
+ return false;
+ }
+
+ debugC(kDebugSaveLoad, "Loading game from '%s'", filename.c_str());
+
+ // First, let's make sure we're using a saved game file from this version of Myst
+ // By checking length of file...
+ int32 size = loadFile->size();
+ if (size != 664 && size != 601) {
+ warning("Incompatible saved game version");
+ delete loadFile;
+ return false;
+ }
+
+ Common::Serializer s(loadFile, nullptr);
+ syncGameState(s, size == 664);
+ delete loadFile;
+
+ return true;
+}
+
+void MystGameState::loadMetadata(const Common::String &filename) {
+ // Open the metadata file
+ Common::InSaveFile *metadataFile = openMetadataFile(filename);
+ if (!metadataFile) {
+ return;
+ }
+
+ debugC(kDebugSaveLoad, "Loading metadata from '%s'", filename.c_str());
+
+ Common::Serializer m(metadataFile, nullptr);
+
+ // Read the metadata file
+ if (_metadata.sync(m)) {
+ _vm->setTotalPlayTime(_metadata.totalPlayTime);
+ }
+ delete metadataFile;
+}
+
+bool MystGameState::save(const Common::String &filename) {
+ // Make sure the description does not have an extension
+ Common::String desc = filename;
+ if (filename.hasSuffix(".mys") || filename.hasSuffix(".MYS")) {
+ desc = removeExtension(filename);
+ }
+
+ if (!saveState(desc)) {
+ return false;
+ }
+
+ updateMetadateForSaving(desc);
+
+ return saveMetadata(desc);
+}
+
+bool MystGameState::saveState(const Common::String &desc) {
+ // Make sure we have the right extension
+ Common::String filename = desc + ".mys";
Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename);
- if (!saveFile)
+ if (!saveFile) {
return false;
+ }
debugC(kDebugSaveLoad, "Saving game to '%s'", filename.c_str());
- Common::Serializer s(0, saveFile);
+ Common::Serializer s(nullptr, saveFile);
syncGameState(s, _vm->getFeatures() & GF_ME);
saveFile->finalize();
delete saveFile;
@@ -139,6 +213,88 @@ bool MystGameState::save(const Common::String &fname) {
return true;
}
+void MystGameState::updateMetadateForSaving(const Common::String &desc) {
+ // Update save creation info
+ TimeDate t;
+ g_system->getTimeAndDate(t);
+ _metadata.saveYear = t.tm_year + 1900;
+ _metadata.saveMonth = t.tm_mon + 1;
+ _metadata.saveDay = t.tm_mday;
+ _metadata.saveHour = t.tm_hour;
+ _metadata.saveMinute = t.tm_min;
+ _metadata.saveDescription = desc;
+ _metadata.totalPlayTime = _vm->getTotalPlayTime();
+}
+
+bool MystGameState::saveMetadata(const Common::String &desc) {
+ // Write the metadata to a separate file so that the save files
+ // are still compatible with the original engine
+ Common::String metadataFilename = desc + ".mym";
+ Common::OutSaveFile *metadataFile = _saveFileMan->openForSaving(metadataFilename);
+ if (!metadataFile) {
+ return false;
+ }
+
+ // Save the metadata
+ Common::Serializer m(nullptr, metadataFile);
+ _metadata.sync(m);
+
+ // Append a thumbnail
+ Graphics::saveThumbnail(*metadataFile);
+
+ metadataFile->finalize();
+ delete metadataFile;
+
+ return true;
+}
+
+SaveStateDescriptor MystGameState::querySaveMetaInfos(const Common::String filename) {
+ SaveStateDescriptor desc;
+ desc.setDescription(filename);
+
+ // Open the metadata file
+ Common::InSaveFile *metadataFile = openMetadataFile(filename);
+ if (!metadataFile) {
+ return desc;
+ }
+
+ Common::Serializer m(metadataFile, nullptr);
+
+ // Read the metadata file
+ Mohawk::MystSaveMetadata metadata;
+ if (!metadata.sync(m)) {
+ delete metadataFile;
+ return desc;
+ }
+
+ // Set the save description
+ desc.setDescription(metadata.saveDescription);
+ desc.setSaveDate(metadata.saveYear, metadata.saveMonth, metadata.saveDay);
+ desc.setSaveTime(metadata.saveHour, metadata.saveMinute);
+ desc.setPlayTime(metadata.totalPlayTime);
+ desc.setThumbnail(Graphics::loadThumbnail(*metadataFile));
+
+ delete metadataFile;
+
+ return desc;
+}
+
+Common::InSaveFile *MystGameState::openMetadataFile(const Common::String &filename) {
+ // Remove the extension
+ Common::String baseName = removeExtension(filename);
+
+ // Open the metadata file
+ return g_system->getSavefileManager()->openForLoading(baseName + ".mym");
+}
+
+Common::String MystGameState::removeExtension(const Common::String &filename) {
+ Common::String baseName = filename;
+ for (uint i = 0; i < 4; i++) {
+ baseName.deleteLastChar();
+ }
+ return baseName;
+}
+
void MystGameState::syncGameState(Common::Serializer &s, bool isME) {
// Globals first
s.syncAsUint16LE(_globals.u0);
@@ -317,11 +473,14 @@ void MystGameState::syncGameState(Common::Serializer &s, bool isME) {
void MystGameState::deleteSave(const Common::String &saveName) {
debugC(kDebugSaveLoad, "Deleting save file \'%s\'", saveName.c_str());
- _saveFileMan->removeSavefile(saveName.c_str());
+ Common::String basename = removeExtension(saveName);
+
+ g_system->getSavefileManager()->removeSavefile(saveName);
+ g_system->getSavefileManager()->removeSavefile(basename + ".mym");
}
void MystGameState::addZipDest(uint16 stack, uint16 view) {
- ZipDests *zipDests = 0;
+ ZipDests *zipDests = nullptr;
// The demo has no zip dest storage
if (_vm->getFeatures() & GF_DEMO)
diff --git a/engines/mohawk/myst_state.h b/engines/mohawk/myst_state.h
index b07a0f2469..50359a5b52 100644
--- a/engines/mohawk/myst_state.h
+++ b/engines/mohawk/myst_state.h
@@ -27,6 +27,8 @@
#include "common/file.h"
#include "common/str.h"
+#include "engines/savestate.h"
+
namespace Common {
class Serializer;
}
@@ -35,15 +37,33 @@ namespace Mohawk {
class MohawkEngine_Myst;
+struct MystSaveMetadata {
+ uint8 saveDay;
+ uint8 saveMonth;
+ uint16 saveYear;
+
+ uint8 saveHour;
+ uint8 saveMinute;
+
+ uint32 totalPlayTime;
+
+ Common::String saveDescription;
+
+ MystSaveMetadata();
+ bool sync(Common::Serializer &s);
+};
+
class MystGameState {
public:
MystGameState(MohawkEngine_Myst*, Common::SaveFileManager*);
~MystGameState();
- Common::StringArray generateSaveGameList();
- bool load(const Common::String &);
- bool save(const Common::String &);
- void deleteSave(const Common::String &);
+ static Common::StringArray generateSaveGameList();
+ static SaveStateDescriptor querySaveMetaInfos(const Common::String filename);
+
+ bool load(const Common::String &filename);
+ bool save(const Common::String &filename);
+ static void deleteSave(const Common::String &saveName);
void addZipDest(uint16 stack, uint16 view);
bool isReachableZipDest(uint16 stack, uint16 view);
@@ -268,8 +288,17 @@ public:
uint32 generatorDepletionTime;
} _stoneship;
+ MystSaveMetadata _metadata;
+
private:
void syncGameState(Common::Serializer &s, bool isME);
+ static Common::InSaveFile *openMetadataFile(const Common::String &filename);
+ bool loadState(const Common::String &filename);
+ void loadMetadata(const Common::String &filename);
+ bool saveState(const Common::String &desc);
+ void updateMetadateForSaving(const Common::String &desc);
+ bool saveMetadata(const Common::String &desc);
+ static Common::String removeExtension(const Common::String &filename);
// The values in these regions are lists of VIEW resources
// which correspond to visited zip destinations
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 198627e012..a2c08d4a92 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -21,6 +21,7 @@
*/
#include "common/debug.h"
+#include "common/events.h"
#include "common/system.h"
#include "common/util.h"
#include "common/textconsole.h"
@@ -163,8 +164,26 @@ Audio::SoundHandle *Sound::replaceSoundMyst(uint16 id, byte volume, bool loop) {
void Sound::playSoundBlocking(uint16 id, byte volume) {
Audio::SoundHandle *handle = playSound(id, volume);
- while (_vm->_mixer->isSoundHandleActive(*handle))
+ while (_vm->_mixer->isSoundHandleActive(*handle) && !_vm->shouldQuit()) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_SPACE:
+ _vm->pauseGame();
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
_vm->_system->delayMillis(10);
+ }
}
void Sound::playMidi(uint16 id) {
@@ -625,7 +644,7 @@ uint16 Sound::convertMystID(uint16 id) {
return id;
}
-Audio::SoundHandle *Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
+void Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
debug(0, "Replacing background sound with %d", id);
// TODO: The original engine does fading
@@ -641,8 +660,11 @@ Audio::SoundHandle *Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
// Check if sound is already playing
if (_mystBackgroundSound.type == kUsedHandle && _vm->_mixer->isSoundHandleActive(_mystBackgroundSound.handle)
- && _vm->getResourceName(ID_MSND, convertMystID(_mystBackgroundSound.id)).hasPrefix(prefix))
- return &_mystBackgroundSound.handle;
+ && _vm->getResourceName(ID_MSND, convertMystID(_mystBackgroundSound.id)).hasPrefix(prefix)) {
+ // The sound is already playing, just change the volume
+ changeBackgroundVolumeMyst(volume);
+ return;
+ }
// Stop old background sound
stopBackgroundMyst();
@@ -659,10 +681,7 @@ Audio::SoundHandle *Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mystBackgroundSound.handle, audStream, -1, volume >> 8);
- return &_mystBackgroundSound.handle;
}
-
- return NULL;
}
void Sound::stopBackgroundMyst() {
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 75c9492d96..c62e6e9874 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -136,7 +136,7 @@ public:
// Myst-specific sound functions
Audio::SoundHandle *replaceSoundMyst(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
- Audio::SoundHandle *replaceBackgroundMyst(uint16 id, uint16 volume = 0xFFFF);
+ void replaceBackgroundMyst(uint16 id, uint16 volume = 0xFFFF);
void pauseBackgroundMyst();
void resumeBackgroundMyst();
void stopBackgroundMyst();
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index ff4a69cd28..eec543235e 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -146,7 +146,7 @@ VideoHandle::VideoHandle(const VideoHandle &handle) : _ptr(handle._ptr) {
VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) {
// Set dithering enabled, if required
- _enableDither = _vm->getGameType() == GType_MYST && !(_vm->getFeatures() & GF_ME);
+ _enableDither = (_vm->getGameType() == GType_MYST || _vm->getGameType() == GType_MAKINGOF) && !(_vm->getFeatures() & GF_ME);
}
VideoManager::~VideoManager() {
@@ -184,7 +184,7 @@ void VideoManager::playMovieBlocking(const Common::String &fileName, uint16 x, u
}
ptr->start();
- waitUntilMovieEnds(ptr);
+ waitUntilMovieEnds(VideoHandle(ptr));
}
void VideoManager::playMovieBlockingCentered(const Common::String &fileName, bool clearScreen) {
@@ -200,7 +200,7 @@ void VideoManager::playMovieBlockingCentered(const Common::String &fileName, boo
ptr->center();
ptr->start();
- waitUntilMovieEnds(ptr);
+ waitUntilMovieEnds(VideoHandle(ptr));
}
void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
@@ -278,7 +278,7 @@ VideoHandle VideoManager::playMovie(const Common::String &fileName) {
return VideoHandle();
ptr->start();
- return ptr;
+ return VideoHandle(ptr);
}
VideoHandle VideoManager::playMovie(uint16 id) {
@@ -287,7 +287,7 @@ VideoHandle VideoManager::playMovie(uint16 id) {
return VideoHandle();
ptr->start();
- return ptr;
+ return VideoHandle(ptr);
}
bool VideoManager::updateMovies() {
@@ -317,50 +317,13 @@ bool VideoManager::updateMovies() {
// Check if we need to draw a frame
if (video->needsUpdate()) {
- const Graphics::Surface *frame = video->decodeNextFrame();
- Graphics::Surface *convertedFrame = 0;
-
- if (frame && (*it)->isEnabled()) {
- Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
-
- if (frame->format != pixelFormat) {
- // We don't support downconverting to 8bpp without having
- // support in the codec. Set _enableDither if shows up.
- if (pixelFormat.bytesPerPixel == 1) {
- warning("Cannot convert high color video frame to 8bpp");
- (*it)->close();
- it = _videos.erase(it);
- continue;
- }
-
- // Convert to the current screen format
- convertedFrame = frame->convertTo(pixelFormat, video->getPalette());
- frame = convertedFrame;
- } else if (pixelFormat.bytesPerPixel == 1 && video->hasDirtyPalette()) {
- // Set the palette when running in 8bpp mode only
- // Don't do this for Myst, which has its own per-stack handling
- if (_vm->getGameType() != GType_MYST)
- _vm->_system->getPaletteManager()->setPalette(video->getPalette(), 0, 256);
- }
-
- // Clip the width/height to make sure we stay on the screen (Myst does this a few times)
- uint16 width = MIN<int32>(video->getWidth(), _vm->_system->getWidth() - (*it)->getX());
- uint16 height = MIN<int32>(video->getHeight(), _vm->_system->getHeight() - (*it)->getY());
- _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, (*it)->getX(), (*it)->getY(), width, height);
-
- // We've drawn something to the screen, make sure we update it
+ if (drawNextFrame(*it)) {
updateScreen = true;
-
- // Delete 8bpp conversion surface
- if (convertedFrame) {
- convertedFrame->free();
- delete convertedFrame;
- }
}
}
// Check the video time
- _vm->doVideoTimer(*it, false);
+ _vm->doVideoTimer(VideoHandle(*it), false);
// Remember to increase the iterator
it++;
@@ -370,6 +333,74 @@ bool VideoManager::updateMovies() {
return updateScreen;
}
+bool VideoManager::drawNextFrame(VideoEntryPtr videoEntry) {
+ Video::VideoDecoder *video = videoEntry->_video;
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (!frame || !videoEntry->isEnabled()) {
+ return false;
+ }
+
+ Graphics::Surface *convertedFrame = 0;
+ Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
+
+ if (frame->format != pixelFormat) {
+ // We don't support downconverting to 8bpp without having
+ // support in the codec. Set _enableDither if shows up.
+ if (pixelFormat.bytesPerPixel == 1) {
+ warning("Cannot convert high color video frame to 8bpp");
+ return false;
+ }
+
+ // Convert to the current screen format
+ convertedFrame = frame->convertTo(pixelFormat, video->getPalette());
+ frame = convertedFrame;
+ } else if (pixelFormat.bytesPerPixel == 1 && video->hasDirtyPalette()) {
+ // Set the palette when running in 8bpp mode only
+ // Don't do this for Myst, which has its own per-stack handling
+ if (_vm->getGameType() != GType_MYST)
+ _vm->_system->getPaletteManager()->setPalette(video->getPalette(), 0, 256);
+ }
+
+ // Clip the video to make sure it stays on the screen (Myst does this a few times)
+ Common::Rect targetRect = Common::Rect(video->getWidth(), video->getHeight());
+ targetRect.translate(videoEntry->getX(), videoEntry->getY());
+
+ Common::Rect frameRect = Common::Rect(video->getWidth(), video->getHeight());
+
+ if (targetRect.left < 0) {
+ frameRect.left -= targetRect.left;
+ targetRect.left = 0;
+ }
+
+ if (targetRect.top < 0) {
+ frameRect.top -= targetRect.top;
+ targetRect.top = 0;
+ }
+
+ if (targetRect.right > _vm->_system->getWidth()) {
+ frameRect.right -= targetRect.right - _vm->_system->getWidth();
+ targetRect.right = _vm->_system->getWidth();
+ }
+
+ if (targetRect.bottom > _vm->_system->getHeight()) {
+ frameRect.bottom -= targetRect.bottom - _vm->_system->getHeight();
+ targetRect.bottom = _vm->_system->getHeight();
+ }
+
+ _vm->_system->copyRectToScreen(frame->getBasePtr(frameRect.left, frameRect.top), frame->pitch,
+ targetRect.left, targetRect.top, targetRect.width(), targetRect.height());
+
+ // Delete 8bpp conversion surface
+ if (convertedFrame) {
+ convertedFrame->free();
+ delete convertedFrame;
+ }
+
+ // We've drawn something to the screen, make sure we update it
+ return true;
+}
+
void VideoManager::activateMLST(uint16 mlstId, uint16 card) {
Common::SeekableReadStream *mlstStream = _vm->getResource(ID_MLST, card);
uint16 recordCount = mlstStream->readUint16BE();
@@ -430,7 +461,7 @@ VideoHandle VideoManager::playMovieRiven(uint16 id) {
ptr->start();
}
- return ptr;
+ return VideoHandle(ptr);
}
}
@@ -445,7 +476,7 @@ void VideoManager::playMovieBlockingRiven(uint16 id) {
ptr->moveTo(_mlstRecords[i].left, _mlstRecords[i].top);
ptr->setVolume(_mlstRecords[i].volume);
ptr->start();
- waitUntilMovieEnds(ptr);
+ waitUntilMovieEnds(VideoHandle(ptr));
return;
}
}
@@ -522,7 +553,7 @@ VideoHandle VideoManager::findVideoHandleRiven(uint16 id) {
if (_mlstRecords[i].code == id)
for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++)
if ((*it)->getID() == _mlstRecords[i].movieID)
- return *it;
+ return VideoHandle(*it);
return VideoHandle();
}
@@ -533,7 +564,7 @@ VideoHandle VideoManager::findVideoHandle(uint16 id) {
for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++)
if ((*it)->getID() == id)
- return *it;
+ return VideoHandle(*it);
return VideoHandle();
}
@@ -544,7 +575,7 @@ VideoHandle VideoManager::findVideoHandle(const Common::String &fileName) {
for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++)
if ((*it)->getFileName().equalsIgnoreCase(fileName))
- return *it;
+ return VideoHandle(*it);
return VideoHandle();
}
@@ -558,12 +589,10 @@ bool VideoManager::isVideoPlaying() {
}
void VideoManager::drawVideoFrame(VideoHandle handle, const Audio::Timestamp &time) {
- // FIXME: This should be done separately from the "playing"
- // videos eventually.
assert(handle);
handle->seek(time);
- updateMovies();
- handle->close();
+ drawNextFrame(handle._ptr);
+ handle->stop();
}
VideoManager::VideoList::iterator VideoManager::findEntry(VideoEntryPtr ptr) {
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 106a32f8e2..d0edab9def 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -293,7 +293,7 @@ private:
/**
* Constructor for internal VideoManager use
*/
- VideoHandle(VideoEntryPtr ptr);
+ explicit VideoHandle(VideoEntryPtr ptr);
/**
* The video entry this is associated with
@@ -350,6 +350,8 @@ private:
VideoList::iterator findEntry(VideoEntryPtr ptr);
void removeEntry(VideoEntryPtr ptr);
+ bool drawNextFrame(VideoEntryPtr videoEntry);
+
// Dithering control
bool _enableDither;
void checkEnableDither(VideoEntryPtr &entry);
diff --git a/engines/mortevielle/configure.engine b/engines/mortevielle/configure.engine
index a7fb2ccda6..0fe89acc99 100644
--- a/engines/mortevielle/configure.engine
+++ b/engines/mortevielle/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 mortevielle "Mortevielle" yes
+add_engine mortevielle "Mortevielle" yes "" "" "highres"
diff --git a/engines/mortevielle/detection.cpp b/engines/mortevielle/detection.cpp
index b6c27e6b12..6791707dd5 100644
--- a/engines/mortevielle/detection.cpp
+++ b/engines/mortevielle/detection.cpp
@@ -55,7 +55,7 @@ public:
MortevielleMetaEngine() : AdvancedMetaEngine(Mortevielle::MortevielleGameDescriptions, sizeof(Mortevielle::MortevielleGameDescription),
MortevielleGame) {
_md5Bytes = 512;
- _singleid = "mortevielle";
+ _singleId = "mortevielle";
// Use kADFlagUseExtraAsHint to distinguish between original and improved versions
// (i.e. use or not of the game data file).
_flags = kADFlagUseExtraAsHint;
diff --git a/engines/neverhood/configure.engine b/engines/neverhood/configure.engine
index 46910e293e..f04e6c69f6 100644
--- a/engines/neverhood/configure.engine
+++ b/engines/neverhood/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 neverhood "Neverhood" yes
+add_engine neverhood "Neverhood" yes "" "" "highres"
diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp
index 4d545e136c..cfddc2d6b4 100644
--- a/engines/neverhood/detection.cpp
+++ b/engines/neverhood/detection.cpp
@@ -41,7 +41,7 @@ struct NeverhoodGameDescription {
};
const char *NeverhoodEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
uint32 NeverhoodEngine::getFeatures() const {
@@ -181,8 +181,8 @@ static const ExtraGuiOption neverhoodExtraGuiOption3 = {
class NeverhoodMetaEngine : public AdvancedMetaEngine {
public:
NeverhoodMetaEngine() : AdvancedMetaEngine(Neverhood::gameDescriptions, sizeof(Neverhood::NeverhoodGameDescription), neverhoodGames) {
- _singleid = "neverhood";
- _guioptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOMIDI);
+ _singleId = "neverhood";
+ _guiOptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOMIDI);
}
virtual const char *getName() const {
@@ -245,7 +245,6 @@ SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- 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++) {
@@ -262,6 +261,8 @@ SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index daeee1fee4..4c52990874 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -220,7 +220,7 @@ static const PARALLACTIONGameDescription gameDescriptions[] = {
class ParallactionMetaEngine : public AdvancedMetaEngine {
public:
ParallactionMetaEngine() : AdvancedMetaEngine(Parallaction::gameDescriptions, sizeof(Parallaction::PARALLACTIONGameDescription), parallactionGames) {
- _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
+ _guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
}
virtual const char *getName() const {
@@ -273,7 +273,6 @@ SaveStateList ParallactionMetaEngine::listSaves(const char *target) const {
Common::String pattern(ConfMan.getDomain(target)->getVal("gameid") + ".0##");
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -290,6 +289,8 @@ SaveStateList ParallactionMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 72e9400acd..6d598d9557 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -194,7 +194,7 @@ int SaveLoad::selectSaveFile(Common::String &selectedName, bool saveMode, const
bool SaveLoad::loadGame() {
Common::String null;
- int _di = selectSaveFile(null, false, "Load file", "Load");
+ int _di = selectSaveFile(null, false, _("Load file"), _("Load"));
if (_di == -1) {
return false;
}
@@ -209,7 +209,7 @@ bool SaveLoad::loadGame() {
bool SaveLoad::saveGame() {
Common::String saveName;
- int slot = selectSaveFile(saveName, true, "Save file", "Save");
+ int slot = selectSaveFile(saveName, true, _("Save file"), _("Save"));
if (slot == -1) {
return false;
}
diff --git a/engines/pegasus/configure.engine b/engines/pegasus/configure.engine
index ed7e295287..650d57a602 100644
--- a/engines/pegasus/configure.engine
+++ b/engines/pegasus/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 pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit"
+add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit highres"
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index 721c382d4f..161a133c8b 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -134,7 +134,7 @@ static const PegasusGameDescription gameDescriptions[] = {
class PegasusMetaEngine : public AdvancedMetaEngine {
public:
PegasusMetaEngine() : AdvancedMetaEngine(Pegasus::gameDescriptions, sizeof(Pegasus::PegasusGameDescription), pegasusGames) {
- _singleid = "pegasus";
+ _singleId = "pegasus";
}
virtual const char *getName() const {
diff --git a/engines/prince/configure.engine b/engines/prince/configure.engine
index 50740d9f41..827579b00d 100644
--- a/engines/prince/configure.engine
+++ b/engines/prince/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 prince "The Prince and The Coward" no
+add_engine prince "The Prince and The Coward" no "" "" "highres"
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
index 3fe7993fdb..1c6f63aff3 100644
--- a/engines/prince/detection.cpp
+++ b/engines/prince/detection.cpp
@@ -29,7 +29,7 @@ int PrinceEngine::getGameType() const {
}
const char *PrinceEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
uint32 PrinceEngine::getFeatures() const {
diff --git a/engines/prince/detection.h b/engines/prince/detection.h
index 7e5bdd6b7b..3076253cf5 100644
--- a/engines/prince/detection.h
+++ b/engines/prince/detection.h
@@ -104,7 +104,7 @@ const static char *directoryGlobs[] = {
class PrinceMetaEngine : public AdvancedMetaEngine {
public:
PrinceMetaEngine() : AdvancedMetaEngine(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
- _singleid = "prince";
+ _singleId = "prince";
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp
index 3482d79f69..d5178efc17 100644
--- a/engines/prince/graphics.cpp
+++ b/engines/prince/graphics.cpp
@@ -279,7 +279,7 @@ void GraphicsMan::drawTransparentWithTransDrawNode(Graphics::Surface *screen, Dr
// first and last row at the same time (height = 1) - no anti-alias
continue;
}
- // new color value based on orginal screen surface color and sprite's edge pixel color
+ // new color value based on original screen surface color and sprite's edge pixel color
*dst2 = transTableData[*dst2 * 256 + value];
}
}
diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp
index 96075a0f0c..81e0767836 100644
--- a/engines/queen/detection.cpp
+++ b/engines/queen/detection.cpp
@@ -185,6 +185,19 @@ static const QueenGameDescription gameDescriptions[] = {
},
},
+ // DOS Floppy - Russian
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", "0d1c10d5c3a1bd90bc0b3859a3258093", 22677657),
+ Common::RU_RUS,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
// DOS CD - French
{
{
@@ -388,7 +401,7 @@ static const QueenGameDescription gameDescriptions[] = {
class QueenMetaEngine : public AdvancedMetaEngine {
public:
QueenMetaEngine() : AdvancedMetaEngine(Queen::gameDescriptions, sizeof(Queen::QueenGameDescription), queenGames, optionsList) {
- _singleid = "queen";
+ _singleId = "queen";
}
virtual const char *getName() const {
@@ -430,25 +443,25 @@ const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles
}
Queen::DetectedGameVersion version;
if (Queen::Resource::detectVersion(&version, &dataFile)) {
- desc.gameid = "queen";
+ desc.gameId = "queen";
desc.language = version.language;
desc.platform = version.platform;
desc.flags = ADGF_NO_FLAGS;
- desc.guioptions = GUIO0();
+ desc.guiOptions = GUIO0();
if (version.features & Queen::GF_DEMO) {
desc.extra = "Demo";
desc.flags = ADGF_DEMO;
- desc.guioptions = GUIO_NOSPEECH;
+ desc.guiOptions = GUIO_NOSPEECH;
} else if (version.features & Queen::GF_INTERVIEW) {
desc.extra = "Interview";
desc.flags = ADGF_DEMO;
- desc.guioptions = GUIO_NOSPEECH;
+ desc.guiOptions = GUIO_NOSPEECH;
} else if (version.features & Queen::GF_FLOPPY) {
desc.extra = "Floppy";
- desc.guioptions = GUIO_NOSPEECH;
+ desc.guiOptions = GUIO_NOSPEECH;
} else if (version.features & Queen::GF_TALKIE) {
desc.extra = "Talkie";
- desc.guioptions = GAMEOPTION_ALT_INTRO;
+ desc.guiOptions = GAMEOPTION_ALT_INTRO;
}
return (const ADGameDescription *)&desc;
}
@@ -464,7 +477,6 @@ SaveStateList QueenMetaEngine::listSaves(const char *target) const {
Common::String pattern("queen.s##");
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -483,6 +495,8 @@ SaveStateList QueenMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/saga/configure.engine b/engines/saga/configure.engine
index 99e2ab367b..adb904a6dd 100644
--- a/engines/saga/configure.engine
+++ b/engines/saga/configure.engine
@@ -1,5 +1,5 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine saga "SAGA" yes "ihnm saga2" "ITE"
-add_engine ihnm "IHNM" yes
-add_engine saga2 "SAGA 2 games" no
+add_engine ihnm "IHNM" yes "" "" "highres"
+add_engine saga2 "SAGA 2 games" no "" "" "highres"
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 13ca63525a..0677e84d67 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -102,11 +102,11 @@ static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = {
class SagaMetaEngine : public AdvancedMetaEngine {
public:
SagaMetaEngine() : AdvancedMetaEngine(Saga::gameDescriptions, sizeof(Saga::SAGAGameDescription), sagaGames) {
- _singleid = "saga";
+ _singleId = "saga";
}
- virtual GameDescriptor findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+ virtual GameDescriptor findGame(const char *gameId) const {
+ return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
virtual const char *getName() const {
@@ -183,7 +183,6 @@ SaveStateList SagaMetaEngine::listSaves(const char *target) const {
pattern += ".s##";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
int slotNum = 0;
@@ -203,6 +202,8 @@ SaveStateList SagaMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 44581f26fc..ad940aaf8b 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -332,6 +332,9 @@ void Interface::saveReminderCallback(void *refCon) {
}
void Interface::updateSaveReminder() {
+ // CHECKME: This is potentially called from a different thread because it is
+ // called from a timer callback. However, it does not seem to take any
+ // precautions to avoid race conditions.
if (_active && _panelMode == kPanelMain) {
_saveReminderState = _saveReminderState % _vm->getDisplayInfo().saveReminderNumSprites + 1;
drawStatusBar();
@@ -1859,8 +1862,10 @@ void Interface::drawStatusBar() {
int stringWidth;
int color;
// The default colors in the Spanish version of IHNM are shifted by one
- // Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)"
- int offset = (_vm->getLanguage() == Common::ES_ESP) ? 1 : 0;
+ // Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)". This
+ // also applies to the German and French versions (bug #7064 - "IHNM:
+ // text mistake in german version").
+ int offset = (_vm->getLanguage() == Common::ES_ESP || _vm->getLanguage() == Common::DE_DEU || _vm->getLanguage() == Common::FR_FRA) ? 1 : 0;
// Disable the status text in IHNM when the chapter is 8
if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 8)
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 663f5991d0..cd48ebaa4d 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -224,6 +224,9 @@ void Music::musicVolumeGaugeCallback(void *refCon) {
}
void Music::musicVolumeGauge() {
+ // CHECKME: This is potentially called from a different thread because it is
+ // called from a timer callback. However, it does not seem to take any
+ // precautions to avoid race conditions.
int volume;
_currentVolumePercent += 10;
diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp
index 705834f1b7..099bf79e6b 100644
--- a/engines/saga/puzzle.cpp
+++ b/engines/saga/puzzle.cpp
@@ -399,6 +399,9 @@ void Puzzle::hintTimerCallback(void *refCon) {
}
void Puzzle::solicitHint() {
+ // CHECKME: This is potentially called from a different thread because it is
+ // called from a timer callback. However, it does not seem to take any
+ // precautions to avoid race conditions.
int i;
_vm->_actor->setSpeechColor(1, kITEColorBlack);
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 1f23a388d0..b932e228ad 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -276,6 +276,9 @@ void Render::fpsTimerCallback(void *refCon) {
}
void Render::fpsTimer() {
+ // CHECKME: This is potentially called from a different thread because it is
+ // called from a timer callback. However, it does not seem to take any
+ // precautions to avoid race conditions.
_fps = _renderedFrameCount;
_renderedFrameCount = 0;
}
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 532b59d3c7..77a21e7f93 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -578,9 +578,11 @@ ColorId SagaEngine::KnownColor2ColorId(KnownColor knownColor) {
}
#ifdef ENABLE_IHNM
} else if (getGameId() == GID_IHNM) {
- // The default colors in the Spanish version of IHNM are shifted by one
- // Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)"
- int offset = (getLanguage() == Common::ES_ESP) ? 1 : 0;
+ // The default colors in the Spanish, version of IHNM are shifted by one
+ // Fixes bug #1848016 - "IHNM: Wrong Subtitles Color (Spanish)". This
+ // also applies to the German and French versions (bug #7064 - "IHNM:
+ // text mistake in german version").
+ int offset = (getLanguage() == Common::ES_ESP || getLanguage() == Common::DE_DEU || getLanguage() == Common::FR_FRA) ? 1 : 0;
switch (knownColor) {
case(kKnownColorTransparent):
diff --git a/engines/savestate.h b/engines/savestate.h
index 54eff0f8cb..21ade602fa 100644
--- a/engines/savestate.h
+++ b/engines/savestate.h
@@ -27,7 +27,6 @@
#include "common/str.h"
#include "common/ptr.h"
-
namespace Graphics {
struct Surface;
}
@@ -205,5 +204,13 @@ private:
/** List of savestates. */
typedef Common::Array<SaveStateDescriptor> SaveStateList;
+/**
+ * Comparator object to compare SaveStateDescriptor's based on slot.
+ */
+struct SaveStateDescriptorSlotComparator {
+ bool operator()(const SaveStateDescriptor &x, const SaveStateDescriptor &y) const {
+ return x.getSaveSlot() < y.getSaveSlot();
+ }
+};
#endif
diff --git a/engines/sci/configure.engine b/engines/sci/configure.engine
index d1c45a4654..f8a519002e 100644
--- a/engines/sci/configure.engine
+++ b/engines/sci/configure.engine
@@ -1,4 +1,4 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine sci "SCI" yes "sci32" "SCI 0-1.1 games"
-add_engine sci32 "SCI32 games" no
+add_engine sci32 "SCI32 games" no "" "" "highres"
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 438c725324..a092e0676d 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -137,8 +137,12 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias
registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList));
registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias
+ registerCmd("visible_plane_list", WRAP_METHOD(Console, cmdVisiblePlaneList));
+ registerCmd("vpl", WRAP_METHOD(Console, cmdVisiblePlaneList)); // alias
registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList));
registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias
+ registerCmd("visible_plane_items", WRAP_METHOD(Console, cmdVisiblePlaneItemList));
+ registerCmd("vpi", WRAP_METHOD(Console, cmdVisiblePlaneItemList)); // alias
registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits));
registerCmd("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits));
// Segments
@@ -190,6 +194,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("send", WRAP_METHOD(Console, cmdSend));
registerCmd("go", WRAP_METHOD(Console, cmdGo));
registerCmd("logkernel", WRAP_METHOD(Console, cmdLogKernel));
+ registerCmd("vocab994", WRAP_METHOD(Console, cmdMapVocab994));
// Breakpoints
registerCmd("bp_list", WRAP_METHOD(Console, cmdBreakpointList));
registerCmd("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias
@@ -330,6 +335,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf("debugflag_list - Lists the available debug flags and their status\n");
debugPrintf("debugflag_enable - Enables a debug flag\n");
debugPrintf("debugflag_disable - Disables a debug flag\n");
+ debugPrintf("debuglevel - Shows or sets debug level\n");
debugPrintf("\n");
debugPrintf("Commands\n");
debugPrintf("--------\n");
@@ -380,7 +386,9 @@ bool Console::cmdHelp(int argc, const char **argv) {
debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n");
debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n");
debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n");
+ debugPrintf(" visible_plane_list / vpl - Shows a list of all the planes in the visible draw list (SCI2+)\n");
debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n");
+ debugPrintf(" visible_plane_items / vpi - Shows a list of all items for a plane in the visible draw list (SCI2+)\n");
debugPrintf(" saved_bits - List saved bits on the hunk\n");
debugPrintf(" show_saved_bits - Display saved bits\n");
debugPrintf("\n");
@@ -487,6 +495,9 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)");
#endif
debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ debugPrintf("kAnimate fastCast enabled: %s\n", g_sci->_gfxAnimate->isFastCastEnabled() ? "yes" : "no");
+ }
debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette16->isMerging() ? "yes" : "no");
debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette16->isUsing16bitColorMatch() ? "yes" : "no");
debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
@@ -994,7 +1005,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) {
for (; resNumber <= resMax; resNumber++) {
script = _engine->getResMan()->findResource(ResourceId(restype, resNumber), 0);
if (script) {
- unsigned int seeker = 0, seekerold = 0;
+ uint32 seeker = 0, seekerold = 0;
uint32 comppos = 0;
int output_script_name = 0;
@@ -1500,7 +1511,7 @@ bool Console::cmdSaid(int argc, const char **argv) {
}
// TODO: Maybe turn this into a proper said spec compiler
- unsigned int len = 0;
+ uint32 len = 0;
for (p++; p < argc; p++) {
if (strcmp(argv[p], ",") == 0) {
spec[len++] = 0xf0;
@@ -1537,7 +1548,7 @@ bool Console::cmdSaid(int argc, const char **argv) {
spec[len++] = 0xfe;
spec[len++] = 0xf6;
} else {
- unsigned int s = strtol(argv[p], 0, 16);
+ uint32 s = strtol(argv[p], 0, 16);
if (s >= 0xf0 && s <= 0xff) {
spec[len++] = s;
} else {
@@ -1766,6 +1777,21 @@ bool Console::cmdPlaneList(int argc, const char **argv) {
return true;
}
+bool Console::cmdVisiblePlaneList(int argc, const char **argv) {
+#ifdef ENABLE_SCI32
+ if (_engine->_gfxFrameout) {
+ debugPrintf("Visible plane list:\n");
+ _engine->_gfxFrameout->printVisiblePlaneList(this);
+ } else {
+ debugPrintf("This SCI version does not have a list of planes\n");
+ }
+#else
+ debugPrintf("SCI32 isn't included in this compiled executable\n");
+#endif
+ return true;
+}
+
+
bool Console::cmdPlaneItemList(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Shows the list of items for a plane\n");
@@ -1794,6 +1820,34 @@ bool Console::cmdPlaneItemList(int argc, const char **argv) {
return true;
}
+bool Console::cmdVisiblePlaneItemList(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Shows the list of items for a plane\n");
+ debugPrintf("Usage: %s <plane address>\n", argv[0]);
+ return true;
+ }
+
+ reg_t planeObject = NULL_REG;
+
+ if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) {
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+#ifdef ENABLE_SCI32
+ if (_engine->_gfxFrameout) {
+ debugPrintf("Visible plane item list:\n");
+ _engine->_gfxFrameout->printVisiblePlaneItemList(this, planeObject);
+ } else {
+ debugPrintf("This SCI version does not have a list of plane items\n");
+ }
+#else
+ debugPrintf("SCI32 isn't included in this compiled executable\n");
+#endif
+ return true;
+}
+
bool Console::cmdSavedBits(int argc, const char **argv) {
SegManager *segman = _engine->_gamestate->_segMan;
SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
@@ -3901,6 +3955,55 @@ bool Console::cmdSfx01Track(int argc, const char **argv) {
return true;
}
+bool Console::cmdMapVocab994(int argc, const char **argv) {
+ EngineState *s = _engine->_gamestate; // for the several defines in this function
+ reg_t reg;
+
+ if (argc != 4) {
+ debugPrintf("Attempts to map a range of vocab.994 entries to a given class\n");
+ debugPrintf("Usage: %s <class addr> <first> <last>\n", argv[0]);
+ return true;
+ }
+
+ if (parse_reg_t(_engine->_gamestate, argv[1], &reg, false)) {
+ debugPrintf("Invalid address passed.\n");
+ debugPrintf("Check the \"addresses\" command on how to use addresses\n");
+ return true;
+ }
+
+ Resource *resource = _engine->_resMan->findResource(ResourceId(kResourceTypeVocab, 994), 0);
+ const Object *obj = s->_segMan->getObject(reg);
+ uint16 *data = (uint16 *) resource->data;
+ uint32 first = atoi(argv[2]);
+ uint32 last = atoi(argv[3]);
+ Common::Array<bool> markers;
+
+ markers.resize(_engine->getKernel()->getSelectorNamesSize());
+ if (!obj->isClass() && getSciVersion() != SCI_VERSION_3)
+ obj = s->_segMan->getObject(obj->getSuperClassSelector());
+
+ first = MIN(first, (uint32) (resource->size / 2 - 2));
+ last = MIN(last, (uint32) (resource->size / 2 - 2));
+
+ for (uint32 i = first; i <= last; ++i) {
+ uint16 ofs = data[i];
+
+ if (obj && ofs < obj->getVarCount()) {
+ uint16 varSelector = obj->getVarSelector(ofs);
+ debugPrintf("%d: property at index %04x of %s is %s %s\n", i, ofs,
+ s->_segMan->derefString(obj->getNameSelector()),
+ _engine->getKernel()->getSelectorName(varSelector).c_str(),
+ markers[varSelector] ? "(repeat!)" : "");
+ markers[varSelector] = true;
+ }
+ else {
+ debugPrintf("%d: property at index %04x doesn't match up with %s\n", i, ofs,
+ s->_segMan->derefString(obj->getNameSelector()));
+ }
+ }
+
+ return true;
+}
bool Console::cmdQuit(int argc, const char **argv) {
if (argc != 2) {
}
@@ -4339,7 +4442,8 @@ int Console::printObject(reg_t pos) {
debugPrintf(" ");
if (var_container && i < var_container->getVarCount()) {
uint16 varSelector = var_container->getVarSelector(i);
- debugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str());
+ // Times two commented out for now for easy parsing of vocab.994
+ debugPrintf("(%04x) [%03x] %s = ", i /* *2 */, varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str());
} else
debugPrintf("p#%x = ", i);
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 8b10912fbe..cf85def950 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -96,7 +96,9 @@ private:
bool cmdAnimateList(int argc, const char **argv);
bool cmdWindowList(int argc, const char **argv);
bool cmdPlaneList(int argc, const char **argv);
+ bool cmdVisiblePlaneList(int argc, const char **argv);
bool cmdPlaneItemList(int argc, const char **argv);
+ bool cmdVisiblePlaneItemList(int argc, const char **argv);
bool cmdSavedBits(int argc, const char **argv);
bool cmdShowSavedBits(int argc, const char **argv);
// Segments
@@ -137,6 +139,7 @@ private:
bool cmdSend(int argc, const char **argv);
bool cmdGo(int argc, const char **argv);
bool cmdLogKernel(int argc, const char **argv);
+ bool cmdMapVocab994(int argc, const char **argv);
// Breakpoints
bool cmdBreakpointList(int argc, const char **argv);
bool cmdBreakpointDelete(int argc, const char **argv);
diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp
index e65ff148de..ca2298e67e 100644
--- a/engines/sci/decompressor.cpp
+++ b/engines/sci/decompressor.cpp
@@ -257,7 +257,7 @@ int DecompressorLZW::unpackLZW1(Common::ReadStream *src, byte *dest, uint32 nPac
init(src, dest, nPacked, nUnpacked);
byte *stak = (byte *)malloc(0x1014);
- unsigned int tokensSize = 0x1004 * sizeof(Tokenlist);
+ uint32 tokensSize = 0x1004 * sizeof(Tokenlist);
Tokenlist *tokens = (Tokenlist *)malloc(tokensSize);
if (!stak || !tokens) {
free(stak);
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index f4f104010f..c920ef10e2 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -98,8 +98,11 @@ static const PlainGameDescriptor s_sciGameTitles[] = {
{"lsl6", "Leisure Suit Larry 6: Shape Up or Slip Out!"},
{"pepper", "Pepper's Adventure in Time"},
{"slater", "Slater & Charlie Go Camping"},
+ {"gk1demo", "Gabriel Knight: Sins of the Fathers"},
+ {"qfg4demo", "Quest for Glory IV: Shadows of Darkness"},
+ {"pq4demo", "Police Quest IV: Open Season"},
// === SCI2 games =========================================================
- {"gk1", "Gabriel Knight: Sins of the Fathers"}, // demo is SCI11, full version SCI32
+ {"gk1", "Gabriel Knight: Sins of the Fathers"},
{"pq4", "Police Quest IV: Open Season"}, // floppy is SCI2, CD SCI2.1
{"qfg4", "Quest for Glory IV: Shadows of Darkness"}, // floppy is SCI2, CD SCI2.1
// === SCI2.1 games ========================================================
@@ -146,6 +149,7 @@ static const GameIdStrToEnum s_gameIdStrToEnum[] = {
{ "fairytales", GID_FAIRYTALES },
{ "freddypharkas", GID_FREDDYPHARKAS },
{ "funseeker", GID_FUNSEEKER },
+ { "gk1demo", GID_GK1DEMO },
{ "gk1", GID_GK1 },
{ "gk2", GID_GK2 },
{ "hoyle1", GID_HOYLE1 },
@@ -183,12 +187,14 @@ static const GameIdStrToEnum s_gameIdStrToEnum[] = {
{ "pq2", GID_PQ2 },
{ "pq3", GID_PQ3 },
{ "pq4", GID_PQ4 },
+ { "pq4demo", GID_PQ4DEMO },
{ "pqswat", GID_PQSWAT },
{ "qfg1", GID_QFG1 },
{ "qfg1vga", GID_QFG1VGA },
{ "qfg2", GID_QFG2 },
{ "qfg3", GID_QFG3 },
{ "qfg4", GID_QFG4 },
+ { "qfg4demo", GID_QFG4DEMO },
{ "rama", GID_RAMA },
{ "sci-fanmade", GID_FANMADE }, // FIXME: Do we really need/want this?
{ "shivers", GID_SHIVERS },
@@ -356,7 +362,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
// qfg4 demo has less than 50 scripts
if (resources.size() < 50)
- return "qfg4";
+ return "qfg4demo";
// Otherwise it's qfg3
return "qfg3";
@@ -473,7 +479,7 @@ static char s_fallbackGameIdBuf[256];
class SciMetaEngine : public AdvancedMetaEngine {
public:
SciMetaEngine() : AdvancedMetaEngine(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles, optionsList) {
- _singleid = "sci";
+ _singleId = "sci";
}
virtual const char *getName() const {
@@ -526,8 +532,8 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
s_fallbackDesc.language = Common::EN_ANY;
s_fallbackDesc.flags = ADGF_NO_FLAGS;
s_fallbackDesc.platform = Common::kPlatformDOS; // default to PC platform
- s_fallbackDesc.gameid = "sci";
- s_fallbackDesc.guioptions = GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI);
+ s_fallbackDesc.gameId = "sci";
+ s_fallbackDesc.guiOptions = GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI);
if (allFiles.contains("resource.map") || allFiles.contains("Data1")
|| allFiles.contains("resmap.001") || allFiles.contains("resmap.001")) {
@@ -578,7 +584,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
ResourceManager resMan;
resMan.addAppropriateSourcesForDetection(fslist);
- resMan.initForDetection();
+ resMan.init();
// TODO: Add error handling.
#ifndef ENABLE_SCI32
@@ -610,7 +616,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan);
strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
s_fallbackGameIdBuf[sizeof(s_fallbackGameIdBuf) - 1] = 0; // Make sure string is NULL terminated
- s_fallbackDesc.gameid = s_fallbackGameIdBuf;
+ s_fallbackDesc.gameId = s_fallbackGameIdBuf;
// Try to determine the game language
// Load up text 0 and start looking for "#" characters
@@ -653,7 +659,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
const bool isCD = (s_fallbackDesc.flags & ADGF_CD);
if (!isCD)
- s_fallbackDesc.guioptions = GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI);
+ s_fallbackDesc.guiOptions = GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI);
if (gameId.hasSuffix("sci")) {
s_fallbackDesc.extra = "SCI";
@@ -686,7 +692,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const GameIdStrToEnum *g = s_gameIdStrToEnum;
for (; g->gameidStr; ++g) {
- if (0 == strcmp(desc->gameid, g->gameidStr)) {
+ if (0 == strcmp(desc->gameId, g->gameidStr)) {
*engine = new SciEngine(syst, desc, g->gameidEnum);
return true;
}
@@ -727,7 +733,6 @@ SaveStateList SciMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
int slotNr = 0;
@@ -760,6 +765,8 @@ SaveStateList SciMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 25623215ed..968eb784b1 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -684,21 +684,23 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
- // Gabriel Knight - English DOS CD Demo
+ // Gabriel Knight - English DOS Demo
// SCI interpreter version 1.001.092
- {"gk1", "CD Demo", {
+ // Note: we are not using ADGF_DEMO here, to avoid a game ID like gk1demo-demo
+ {"gk1demo", "Demo", {
{"resource.map", 0, "39645952ae0ed8072c7e838f31b75464", 2490},
{"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
- // Gabriel Knight - English DOS CD Demo (from DrMcCoy)
+ // Gabriel Knight - English DOS Demo (from DrMcCoy)
// SCI interpreter version 1.001.092
- {"gk1", "CD Demo", {
+ // Note: we are not using ADGF_DEMO here, to avoid a game ID like gk1demo-demo
+ {"gk1demo", "Demo", {
{"resource.map", 0, "8cad2a256f41463030cbb7ea1bfb2857", 2490},
{"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Gabriel Knight - English DOS Floppy
@@ -941,6 +943,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Hoyle 2 - English DOS (supplied by m_kiewitz)
+ // SCI interpreter version 0.000.668, Ver 1.000.014, 2x5.25"
+ {"hoyle2", "", {
+ {"resource.map", 0, "8cef06c93d17d96f44aacd5902d84b30", 2100},
+ {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98289},
+ {"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 197326},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Hoyle 2 - English DOS (supplied by misterhands in bug report #6598)
// Game v1.000.016, interpreter 0.000.668, INT #12.5.90
{"hoyle2", "", {
@@ -1531,13 +1542,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.000", 0, "71afd220d46bde1109c58e6acc0f3a01", 469094},
{"resource.001", 0, "72a569f46f1abf2d9d2b1526ad3799c3", 12808839},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO2(GUIO_NOASPECT, GUIO_MIDITOWNS) },
- {"kq5", "", {
- {"resource.map", 0, "20c7cd248ff1a349ed354568eebd972b", 12733},
- {"resource.000", 0, "71afd220d46bde1109c58e6acc0f3a01", 469094},
- {"resource.001", 0, "72a569f46f1abf2d9d2b1526ad3799c3", 12808839},
- AD_LISTEND},
- Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO2(GUIO_NOASPECT, GUIO_MIDITOWNS) },
+ Common::JA_JPN, Common::kPlatformFMTowns, ADGF_ADDENGLISH, GUIO3(GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD, GUIO_MIDITOWNS) },
// King's Quest 5 - Japanese PC-98 Floppy 0.000.015 (supplied by omer_mor in bug report #3073583)
{"kq5", "", {
@@ -1646,14 +1651,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#ifdef ENABLE_SCI32
- // King's Quest 7 - English Windows (from abevi)
- // VERSION 1.65c
- {"kq7", "", {
- {"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195},
- {"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925},
- AD_LISTEND},
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-
// King's Quest 7 - English Windows (from the King's Quest Collection)
// Executable scanning reports "2.100.002", VERSION file reports "1.4"
{"kq7", "", {
@@ -1662,6 +1659,33 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // King's Quest 7 - English Windows-interpreter-only (supplied by m_kiewitz)
+ // SCI interpreter version 2.100.002, VERSION file reports "1.51"
+ {"kq7", "", {
+ {"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
+ {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
+ {"resource.aud", 0, "c2a988a16053eb98c7b73a75139902a0", 217716879},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // King's Quest 7 - German Windows-interpreter-only (supplied by markcoolio in bug report #2727402)
+ // SCI interpreter version 2.100.002, VERSION file reports "1.51"
+ // same as English 1.51, only resource.aud/resource.sfx are different
+ {"kq7", "", {
+ {"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
+ {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
+ {"resource.aud", 0, "3f17bcaf8a9ff6a6c2d4de1a2078fdcc", 258119621},
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
+ // King's Quest 7 - English Windows (from abevi)
+ // VERSION 1.65c
+ {"kq7", "", {
+ {"resource.000", 0, "4948e4e1506f1e1c4e1d47abfa06b7f8", 204385195},
+ {"resource.map", 0, "40ccafb2195301504eba2e4f4f2c7f3d", 18925},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// King's Quest 7 - English DOS (from FRG)
// SCI interpreter version 2.100.002, VERSION file reports "2.00b"
{"kq7", "", {
@@ -1678,14 +1702,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
- // King's Quest 7 - German Windows (supplied by markcoolio in bug report #2727402)
- // SCI interpreter version 2.100.002
- {"kq7", "", {
- {"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697},
- {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576},
- AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-
// King's Quest 7 - Spanish DOS (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "2.00"
{"kq7", "", {
@@ -2286,6 +2302,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Larry 6 - French DOS Floppy - LOWRES (provided by theco33)
+ // SCI interpreter version 1.001.113
+ {"lsl6", "", {
+ {"resource.map", 0, "1e07144d3b06a3269236880170978acb", 6943},
+ {"resource.000", 0, "7884a8db9253e29e6b37a2651fd90ba3", 5749882},
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Larry 6 - English/German/French DOS CD - LOWRES
// SCI interpreter version 1.001.115
{"lsl6", "", {
@@ -2593,12 +2617,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
{"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
- {"mothergoose256", "", {
- {"resource.map", 0, "b11e971ccd2040bebba59dfb409a08ef", 5772},
- {"resource.001", 0, "d49625d9b8005ec01c852f8322a82867", 4330713},
- AD_LISTEND},
- Common::JA_JPN, Common::kPlatformFMTowns, 0, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformFMTowns, ADGF_ADDENGLISH, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810)
@@ -2627,6 +2646,28 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
+ // Phantasmagoria - English DOS/Windows (from csnover)
+ // Windows executable scanning reports "2.100.002" - "Aug 06 1995"
+ // DOS executable scanning reports "2.100.002" - "May 24 1995"
+ // VERSION file reports "1.000.000"
+ {"phantasmagoria", "", {
+ {"resmap.001", 0, "43c395f312a190e67b90b2c1e93a79e2", 11518},
+ {"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 65844612},
+ {"resmap.002", 0, "94f142cfe8ec4107b6a42876cb603ed0", 12058},
+ {"ressci.002", 0, "3aae6559aa1df273bc542d5ac6330d75", 71588691},
+ {"resmap.003", 0, "39e9abd4501b5b6168dd07379c0be753", 12334},
+ {"ressci.003", 0, "3aae6559aa1df273bc542d5ac6330d75", 73651084},
+ {"resmap.004", 0, "434f9704658229fef322c863d2422a9a", 12556},
+ {"ressci.004", 0, "3aae6559aa1df273bc542d5ac6330d75", 75811935},
+ {"resmap.005", 0, "3ff9b4f7301800825c0ed008e091205e", 12604},
+ {"ressci.005", 0, "3aae6559aa1df273bc542d5ac6330d75", 78814934},
+ {"resmap.006", 0, "27ad413313e2a3ec3c53250e7ff5b2d1", 12532},
+ {"ressci.006", 0, "3aae6559aa1df273bc542d5ac6330d75", 77901360},
+ {"resmap.007", 0, "aa8175cfc93242af6f5e65bdceaafc0d", 7972},
+ //{"ressci.007", 0, "3aae6559aa1df273bc542d5ac6330d75", 25859038},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Phantasmagoria - English DOS (from jvprat)
// Executable scanning reports "2.100.002", VERSION file reports "1.100.000UK"
{"phantasmagoria", "", {
@@ -2875,6 +2916,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 2 - Japanese PC-98 (also includes english language)
+ // Executable scanning reports "x.yyy.zzz"
// SCI interpreter version unknown
{"pq2", "", {
{"resource.map", 0, "883804c616dca1d82373bf9fda3a71d2", 4656},
@@ -2882,7 +2924,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.002", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 637662},
{"resource.003", 0, "05fdee43a228dd6ea4d1a92ccae3f788", 684395},
AD_LISTEND},
- Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::JA_JPN, Common::kPlatformPC98, ADGF_ADDENGLISH, GUIO6(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
// Police Quest 3 - English Amiga
// Executable scanning reports "1.004.024"
@@ -2969,11 +3011,12 @@ static const struct ADGameDescription SciGameDescriptions[] = {
// Police Quest 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.096
- {"pq4", "Demo", {
+ // Note: we are not using ADGF_DEMO here, to avoid a game ID like pq4demo-demo
+ {"pq4demo", "Demo", {
{"resource.map", 0, "be56f87a1c4a13062a30a362df860c2f", 1472},
{"resource.000", 0, "527d5684016e6816157cd15d9071b11b", 1121310},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Police Quest 4 - English DOS CD (from the Police Quest Collection)
@@ -3381,11 +3424,12 @@ static const struct ADGameDescription SciGameDescriptions[] = {
// Quest for Glory 4 - English DOS Non-Interactive Demo (from FRG)
// SCI interpreter version 1.001.069 (just a guess)
- {"qfg4", "Demo", {
+ // Note: we are not using ADGF_DEMO here, to avoid a game ID like qfg4demo-demo
+ {"qfg4demo", "Demo", {
{"resource.map", 0, "1ba7c7ae1efb315326d45cb931569b1b", 922},
{"resource.000", 0, "41ba03f0b188b029132daa3ece0d3e14", 623154},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
#ifdef ENABLE_SCI32
// Quest for Glory 4 1.1 Floppy - English DOS (supplied by markcool in bug report #2723852)
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 0df4701334..796dea2382 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -853,7 +853,7 @@ void Kernel::loadKernelNames(GameFeatures *features) {
_kernelNames[0x26] = "Portrait";
else if (g_sci->getPlatform() == Common::kPlatformMacintosh)
_kernelNames[0x84] = "ShowMovie";
- } else if (g_sci->getGameId() == GID_QFG4 && g_sci->isDemo()) {
+ } else if (g_sci->getGameId() == GID_QFG4DEMO) {
_kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit
}
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index f62c43840f..62566a74b2 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -75,6 +75,10 @@ struct SciWorkaroundEntry; // from workarounds.h
* vocab.997. This results in much more readable code. Thus, this vocabulary isn't
* used at all.
*
+ * 993.voc (unneeded) - Contains the SCI3 equivalent of vocab.994; like its predecessor,
+ * the raw selector numbers can be deduced and used instead. In fact, one version of this
+ * file has turned out to cover all versiona of SCI3.
+ *
* SCI0 parser vocabularies:
* - vocab.901 / 901.voc - suffix vocabulary
* - vocab.900 / 900.voc - parse tree branches
@@ -408,7 +412,7 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
reg_t kShow(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv);
reg_t kDummy(EngineState *s, int argc, reg_t *argv);
reg_t kEmpty(EngineState *s, int argc, reg_t *argv);
reg_t kStub(EngineState *s, int argc, reg_t *argv);
@@ -441,24 +445,54 @@ reg_t kStringLower(EngineState *s, int argc, reg_t *argv);
reg_t kStringTrn(EngineState *s, int argc, reg_t *argv);
reg_t kStringTrnExclude(EngineState *s, int argc, reg_t *argv);
+reg_t kScrollWindowCreate(EngineState *s, int argc, reg_t *argv);
+reg_t kScrollWindowAdd(EngineState *s, int argc, reg_t *argv);
+reg_t kScrollWindowWhere(EngineState *s, int argc, reg_t *argv);
+reg_t kScrollWindowShow(EngineState *s, int argc, reg_t *argv);
+reg_t kScrollWindowDestroy(EngineState *s, int argc, reg_t *argv);
+
reg_t kMulDiv(EngineState *s, int argc, reg_t *argv);
-reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv);
-reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv);
-// "Screen items" in SCI32 are views
+
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapOff(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv);
+reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv);
+
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv);
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv);
reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv);
-// Text
+
reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv);
-reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv);
-// "Planes" in SCI32 are pictures
+reg_t kBitmap(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapCreate(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDestroy(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDrawLine(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDrawColor(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapDrawBitmap(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapInvert(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapSetDisplace(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapCreateFromView(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapCopyPixels(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapClone(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapGetInfo(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapScale(EngineState *s, int argc, reg_t *argv);
+reg_t kBitmapCreateFromUnknown(EngineState *s, int argc, reg_t *argv);
+
reg_t kAddPlane(EngineState *s, int argc, reg_t *argv);
reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv);
reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv);
+reg_t kMovePlaneItems(EngineState *s, int argc, reg_t *argv);
reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv);
reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv);
reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv);
reg_t kFrameOut(EngineState *s, int argc, reg_t *argv);
+reg_t kCelHigh32(EngineState *s, int argc, reg_t *argv);
+reg_t kCelWide32(EngineState *s, int argc, reg_t *argv);
reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); // kOnMe for SCI2, kIsOnMe for SCI2.1
reg_t kInPolygon(EngineState *s, int argc, reg_t *argv);
@@ -473,6 +507,7 @@ reg_t kEditText(EngineState *s, int argc, reg_t *argv);
reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv);
reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv);
reg_t kSetScroll(EngineState *s, int argc, reg_t *argv);
+
reg_t kPalCycle(EngineState *s, int argc, reg_t *argv);
reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv);
reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv);
@@ -488,6 +523,8 @@ reg_t kPalVaryMergeStart(EngineState *s, int argc, reg_t *argv);
// SCI2.1 Kernel Functions
reg_t kMorphOn(EngineState *s, int argc, reg_t *argv);
reg_t kText(EngineState *s, int argc, reg_t *argv);
+reg_t kTextSize32(EngineState *s, int argc, reg_t *argv);
+reg_t kTextWidth(EngineState *s, int argc, reg_t *argv);
reg_t kSave(EngineState *s, int argc, reg_t *argv);
reg_t kAutoSave(EngineState *s, int argc, reg_t *argv);
reg_t kList(EngineState *s, int argc, reg_t *argv);
@@ -505,9 +542,9 @@ reg_t kGetSierraProfileInt(EngineState *s, int argc, reg_t *argv);
reg_t kCelInfo(EngineState *s, int argc, reg_t *argv);
reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv);
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv);
+reg_t kSetFontHeight(EngineState *s, int argc, reg_t *argv);
reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv);
reg_t kFont(EngineState *s, int argc, reg_t *argv);
-reg_t kBitmap(EngineState *s, int argc, reg_t *argv);
reg_t kAddLine(EngineState *s, int argc, reg_t *argv);
reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv);
reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index fce3230a18..3463d05e77 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -60,14 +60,19 @@ struct SciKernelMapSubEntry {
#define SCI_SUBOPENTRY_TERMINATOR { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, NULL, NULL, NULL, NULL }
-#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
-#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
-#define SIG_SCI1 SCI_VERSION_1_EGA_ONLY, SCI_VERSION_1_LATE
-#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
-#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
-#define SIG_SINCE_SCI21 SCI_VERSION_2_1_EARLY, SCI_VERSION_3
-#define SIG_UNTIL_SCI21MID SCI_VERSION_2, SCI_VERSION_2_1_MIDDLE
-#define SIG_SINCE_SCI21LATE SCI_VERSION_2_1_LATE, SCI_VERSION_3
+#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
+#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
+#define SIG_SCI1 SCI_VERSION_1_EGA_ONLY, SCI_VERSION_1_LATE
+#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
+#define SIG_SINCE_SCI11 SCI_VERSION_1_1, SCI_VERSION_NONE
+#define SIG_SCI2 SCI_VERSION_2, SCI_VERSION_2
+#define SIG_SCI21EARLY SCI_VERSION_2_1_EARLY, SCI_VERSION_2_1_EARLY
+#define SIG_UNTIL_SCI21EARLY SCI_VERSION_2, SCI_VERSION_2_1_EARLY
+#define SIG_UNTIL_SCI21MID SCI_VERSION_2, SCI_VERSION_2_1_MIDDLE
+#define SIG_SINCE_SCI21 SCI_VERSION_2_1_EARLY, SCI_VERSION_3
+#define SIG_SINCE_SCI21MID SCI_VERSION_2_1_MIDDLE, SCI_VERSION_3
+#define SIG_SINCE_SCI21LATE SCI_VERSION_2_1_LATE, SCI_VERSION_3
+#define SIG_SCI3 SCI_VERSION_3, SCI_VERSION_3
#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1
#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
@@ -210,7 +215,7 @@ static const SciKernelMapSubEntry kPalVary_subops[] = {
{ SIG_SCI16, 6, MAP_CALL(PalVaryPauseResume), "i", NULL },
#ifdef ENABLE_SCI32
{ SIG_SCI32, 0, MAP_CALL(PalVarySetVary), "i(i)(i)(ii)", NULL },
- { SIG_SCI32, 1, MAP_CALL(PalVarySetPercent), "(i)(i)", NULL },
+ { SIG_SCI32, 1, MAP_CALL(PalVarySetPercent), "(i)(i)", kPalVarySetPercent_workarounds },
{ SIG_SCI32, 2, MAP_CALL(PalVaryGetPercent), "", NULL },
{ SIG_SCI32, 3, MAP_CALL(PalVaryOff), "", NULL },
{ SIG_SCI32, 4, MAP_CALL(PalVaryMergeTarget), "i", NULL },
@@ -283,6 +288,42 @@ static const SciKernelMapSubEntry kSave_subops[] = {
};
// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kFont_subops[] = {
+ { SIG_SINCE_SCI21MID, 0, MAP_CALL(SetFontHeight), "i", NULL },
+ { SIG_SINCE_SCI21MID, 1, MAP_CALL(SetFontRes), "ii", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kText_subops[] = {
+ { SIG_SINCE_SCI21MID, 0, MAP_CALL(TextSize32), "r[r0]i(i)(i)", NULL },
+ { SIG_SINCE_SCI21MID, 1, MAP_CALL(TextWidth), "ri", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kBitmap_subops[] = {
+ { SIG_SINCE_SCI21, 0, MAP_CALL(BitmapCreate), "iiii(i)(i)(i)", NULL },
+ { SIG_SINCE_SCI21, 1, MAP_CALL(BitmapDestroy), "r", NULL },
+ { SIG_SINCE_SCI21, 2, MAP_CALL(BitmapDrawLine), "riiiii(i)(i)", NULL },
+ { SIG_SINCE_SCI21, 3, MAP_CALL(BitmapDrawView), "riii(i)(i)(0)(i)(i)", NULL },
+ { SIG_SINCE_SCI21, 4, MAP_CALL(BitmapDrawText), "rriiiiiiiiiii", NULL },
+ { SIG_SINCE_SCI21, 5, MAP_CALL(BitmapDrawColor), "riiiii", NULL },
+ { SIG_SINCE_SCI21, 6, MAP_CALL(BitmapDrawBitmap), "rr(i)(i)(i)", NULL },
+ { SIG_SINCE_SCI21, 7, MAP_CALL(BitmapInvert), "riiiiii", NULL },
+ { SIG_SINCE_SCI21MID, 8, MAP_CALL(BitmapSetDisplace), "rii", NULL },
+ { SIG_SINCE_SCI21MID, 9, MAP_CALL(BitmapCreateFromView), "iii(i)(i)(i)([r0])", NULL },
+ { SIG_SINCE_SCI21MID, 10, MAP_CALL(BitmapCopyPixels), "rr", NULL },
+ { SIG_SINCE_SCI21MID, 11, MAP_CALL(BitmapClone), "r", NULL },
+ { SIG_SINCE_SCI21LATE, 12, MAP_CALL(BitmapGetInfo), "r(i)(i)", NULL },
+ { SIG_SINCE_SCI21LATE, 13, MAP_CALL(BitmapScale), "r...ii", NULL },
+ { SIG_SCI3, 14, MAP_CALL(BitmapCreateFromUnknown), "......", NULL },
+ { SIG_SCI3, 15, MAP_EMPTY(Bitmap), "(.*)", NULL },
+ { SIG_SCI3, 16, MAP_EMPTY(Bitmap), "(.*)", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kList_subops[] = {
{ SIG_SINCE_SCI21, 0, MAP_CALL(NewList), "", NULL },
{ SIG_SINCE_SCI21, 1, MAP_CALL(DisposeList), "l", NULL },
@@ -311,6 +352,17 @@ static const SciKernelMapSubEntry kList_subops[] = {
};
// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kRemapColors_subops[] = {
+ { SIG_SCI32, 0, MAP_CALL(RemapOff), "(i)", NULL },
+ { SIG_SCI32, 1, MAP_CALL(RemapByRange), "iiii(i)", NULL },
+ { SIG_SCI32, 2, MAP_CALL(RemapByPercent), "ii(i)", NULL },
+ { SIG_SCI32, 3, MAP_CALL(RemapToGray), "ii(i)", NULL },
+ { SIG_SCI32, 4, MAP_CALL(RemapToPercentGray), "iii(i)", NULL },
+ { SIG_SCI32, 5, MAP_CALL(RemapSetNoMatchRange), "ii", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
+// version, subId, function-mapping, signature, workarounds
static const SciKernelMapSubEntry kString_subops[] = {
{ SIG_SCI32, 0, MAP_CALL(StringNew), "i(i)", NULL },
{ SIG_SCI32, 1, MAP_CALL(StringSize), "[or]", NULL },
@@ -352,6 +404,31 @@ static const SciKernelMapSubEntry kString_subops[] = {
SCI_SUBOPENTRY_TERMINATOR
};
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kScrollWindow_subops[] = {
+ { SIG_SCI32, 0, MAP_CALL(ScrollWindowCreate), "oi", NULL },
+ { SIG_SCI32, 1, MAP_CALL(ScrollWindowAdd), "o.ii.(.)", NULL },
+ { SIG_SCI32, 2, MAP_DUMMY(ScrollWindowClear), "o", NULL },
+ { SIG_SCI32, 3, MAP_DUMMY(ScrollWindowPageUp), "o", NULL },
+ { SIG_SCI32, 4, MAP_DUMMY(ScrollWindowPageDown), "o", NULL },
+ { SIG_SCI32, 5, MAP_DUMMY(ScrollWindowUpArrow), "o", NULL },
+ { SIG_SCI32, 6, MAP_DUMMY(ScrollWindowDownArrow), "o", NULL },
+ { SIG_SCI32, 7, MAP_DUMMY(ScrollWindowHome), "o", NULL },
+ { SIG_SCI32, 8, MAP_DUMMY(ScrollWindowEnd), "o", NULL },
+ { SIG_SCI32, 9, MAP_DUMMY(ScrollWindowResize), "o.", NULL },
+ { SIG_SCI32, 10, MAP_CALL(ScrollWindowWhere), "oi", NULL },
+ { SIG_SCI32, 11, MAP_DUMMY(ScrollWindowGo), "o..", NULL },
+ { SIG_SCI32, 12, MAP_DUMMY(ScrollWindowInsert), "o.....", NULL },
+ { SIG_SCI32, 13, MAP_DUMMY(ScrollWindowDelete), "o.", NULL },
+ { SIG_SCI32, 14, MAP_DUMMY(ScrollWindowModify), "o.....(.)", NULL },
+ { SIG_SCI32, 15, MAP_DUMMY(ScrollWindowHide), "o", NULL },
+ { SIG_SCI32, 16, MAP_CALL(ScrollWindowShow), "o", NULL },
+ { SIG_SCI32, 17, MAP_CALL(ScrollWindowDestroy), "o", NULL },
+ { SIG_SCI32, 18, MAP_DUMMY(ScrollWindowText), "o", NULL },
+ { SIG_SCI32, 19, MAP_DUMMY(ScrollWindowReconstruct), "o.", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
#endif
struct SciKernelMapEntry {
@@ -380,12 +457,16 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL },
{ MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+ { MAP_CALL(CantBeHere), SIG_SCI16, SIGFOR_ALL, "o(l)", NULL, NULL },
#ifdef ENABLE_SCI32
- { "CantBeHere", kCantBeHere32, SIG_SCI32, SIGFOR_ALL, "ol", NULL, NULL },
+ { MAP_CALL(CantBeHere), SIG_SCI32, SIGFOR_ALL, "ol", NULL, NULL },
+#endif
+ { MAP_CALL(CelHigh), SIG_SCI16, SIGFOR_ALL, "ii(i)", NULL, kCelHigh_workarounds },
+ { MAP_CALL(CelWide), SIG_SCI16, SIGFOR_ALL, "ii(i)", NULL, kCelWide_workarounds },
+#ifdef ENABLE_SCI32
+ { "CelHigh", kCelHigh32, SIG_SCI32, SIGFOR_ALL, "iii", NULL, NULL },
+ { "CelWide", kCelWide32, SIG_SCI32, SIGFOR_ALL, "iii", NULL, NULL },
#endif
- { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
- { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, kCelHigh_workarounds },
- { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, kCelWide_workarounds },
{ MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL },
{ MAP_CALL(CheckFreeSpace), SIG_SCI11, SIGFOR_ALL, "r(i)", NULL, NULL },
{ MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL },
@@ -484,9 +565,9 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL },
{ MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, kReadNumber_workarounds },
- { MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
+ { "RemapColors", kRemapColors16, SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL },
#ifdef ENABLE_SCI32
- { "RemapColors", kRemapColors32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(RemapColors), SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)(i)(i)", kRemapColors_subops, NULL },
#endif
{ MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL },
{ MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
@@ -502,7 +583,10 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL },
{ MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL },
{ MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
- { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
+ { MAP_CALL(SetNowSeen), SIG_SCI16, SIGFOR_ALL, "o(i)", NULL, NULL },
+#ifdef ENABLE_SCI32
+ { MAP_CALL(SetNowSeen), SIG_SCI32, SIGFOR_ALL, "o", NULL, NULL },
+#endif
{ MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iiiii)(i)", NULL, kSetPort_workarounds },
{ MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL },
@@ -520,10 +604,10 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, kStrLen_workarounds },
{ MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL },
- { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL },
- { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL },
- { MAP_CALL(TextSize), SIG_SCIALL, SIGFOR_MAC, "r[r0]i(i)(r0)(i)", NULL, NULL },
- { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL },
+ { MAP_CALL(TextColors), SIG_SCI16, SIGFOR_ALL, "(i*)", NULL, NULL },
+ { MAP_CALL(TextFonts), SIG_SCI16, SIGFOR_ALL, "(i*)", NULL, NULL },
+ { MAP_CALL(TextSize), SIG_SCI16, SIGFOR_MAC, "r[r0]i(i)(r0)(i)", NULL, NULL },
+ { MAP_CALL(TextSize), SIG_SCI16, SIGFOR_ALL, "r[r0]i(i)(r0)", NULL, NULL },
{ MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL },
{ "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL },
@@ -555,14 +639,18 @@ static SciKernelMapEntry s_kernelMap[] = {
#ifdef ENABLE_SCI32
// SCI2 Kernel Functions
// TODO: whoever knows his way through those calls, fix the signatures.
+ { "TextSize", kTextSize32, SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "r[r0]i(i)", NULL, NULL },
+ { MAP_DUMMY(TextColors), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "(.*)", NULL, NULL },
+ { MAP_DUMMY(TextFonts), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "(.*)", NULL, NULL },
+
{ MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
{ MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
- { MAP_CALL(DisposeTextBitmap), SIG_EVERYWHERE, "r", NULL, NULL },
- { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL },
+ { "DisposeTextBitmap", kBitmapDestroy, SIG_SCI2, SIGFOR_ALL, "r", NULL, NULL },
+ { MAP_CALL(FrameOut), SIG_EVERYWHERE, "(i)", NULL, NULL },
{ MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL },
{ MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL },
{ MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL },
@@ -623,9 +711,9 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_DUMMY(MarkMemory), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(GetHighItemPri), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(ShowStylePercent), SIG_EVERYWHERE, "(.*)", NULL, NULL },
- { MAP_DUMMY(InvertRect), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_DUMMY(InvertRect), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "(.*)", NULL, NULL },
{ MAP_DUMMY(InputText), SIG_EVERYWHERE, "(.*)", NULL, NULL },
- { MAP_DUMMY(TextWidth), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(TextWidth), SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "ri", NULL, NULL },
{ MAP_DUMMY(PointSize), SIG_EVERYWHERE, "(.*)", NULL, NULL },
// SCI2.1 Kernel Functions
@@ -636,18 +724,18 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(Save), SIG_EVERYWHERE, "i(.*)", kSave_subops, NULL },
- { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Text), SIG_SINCE_SCI21MID, SIGFOR_ALL, "i(.*)", kText_subops, NULL },
{ MAP_CALL(AddPicAt), SIG_EVERYWHERE, "oiii", NULL, NULL },
{ MAP_CALL(GetWindowsOption), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(WinHelp), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(GetConfig), SIG_EVERYWHERE, "ro", NULL, NULL },
{ MAP_CALL(GetSierraProfileInt), SIG_EVERYWHERE, "rri", NULL, NULL },
- { MAP_CALL(CelInfo), SIG_EVERYWHERE, "iiiiii", NULL, NULL },
- { MAP_CALL(SetLanguage), SIG_EVERYWHERE, "r", NULL, NULL },
- { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "io(.*)", NULL, NULL },
- { MAP_CALL(SetFontRes), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
- { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(CelInfo), SIG_SINCE_SCI21MID, SIGFOR_ALL, "iiiiii", NULL, NULL },
+ { MAP_CALL(SetLanguage), SIG_SINCE_SCI21MID, SIGFOR_ALL, "r", NULL, NULL },
+ { MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "i(.*)", kScrollWindow_subops, NULL },
+ { MAP_CALL(SetFontRes), SIG_SCI21EARLY, SIGFOR_ALL, "ii", NULL, NULL },
+ { MAP_CALL(Font), SIG_SINCE_SCI21MID, SIGFOR_ALL, "i(.*)", kFont_subops, NULL },
+ { MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", kBitmap_subops, NULL },
{ MAP_CALL(AddLine), SIG_EVERYWHERE, "oiiiiiiiii", NULL, NULL },
{ MAP_CALL(UpdateLine), SIG_EVERYWHERE, "[r0]oiiiiiiiii", NULL, NULL },
{ MAP_CALL(DeleteLine), SIG_EVERYWHERE, "[r0]o", NULL, NULL },
@@ -699,9 +787,9 @@ static SciKernelMapEntry s_kernelMap[] = {
// <lskovlun> The idea, if I understand correctly, is that the engine generates events
// of a special HotRect type continuously when the mouse is on that rectangle
- // MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons
- // SetPalStyleRange - 2 integer parameters, start and end. All styles from start-end
- // (inclusive) are set to 0
+ // Used by SQ6 to scroll through the inventory via the up/down buttons
+ { MAP_CALL(MovePlaneItems), SIG_SINCE_SCI21, SIGFOR_ALL, "oii(i)", NULL, NULL },
+
{ MAP_CALL(SetPalStyleRange), SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(MorphOn), SIG_EVERYWHERE, "", NULL, NULL },
@@ -1004,7 +1092,6 @@ static const char *const sci2_default_knames[] = {
/*0x89*/ "TextWidth", // for debugging(?), only in SCI2, not used in any SCI2 game
/*0x8a*/ "PointSize", // for debugging(?), only in SCI2, not used in any SCI2 game
- // GK2 Demo (and similar) only kernel functions
/*0x8b*/ "AddLine",
/*0x8c*/ "DeleteLine",
/*0x8d*/ "UpdateLine",
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index bb595e9960..534d9ce713 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -83,11 +83,12 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
}
// For a real event we use its associated mouse position
- mousePos = curEvent.mousePos;
#ifdef ENABLE_SCI32
- if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
- g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
+ if (getSciVersion() >= SCI_VERSION_2)
+ mousePos = curEvent.mousePosSci;
+ else
#endif
+ mousePos = curEvent.mousePos;
// Limit the mouse cursor position, if necessary
g_sci->_gfxCursor->refreshPosition();
@@ -101,7 +102,25 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// question. Check GfxCursor::setPosition(), for a more detailed
// explanation and a list of cursor position workarounds.
if (s->_cursorWorkaroundRect.contains(mousePos.x, mousePos.y)) {
- s->_cursorWorkaroundActive = false;
+ // For OpenPandora and possibly other platforms, that support analog-stick control + touch screen
+ // control at the same time: in case the cursor is currently at the coordinate set by the scripts,
+ // we will count down instead of immediately disabling the workaround.
+ // On OpenPandora the cursor position is set, but it's overwritten shortly afterwards by the
+ // touch screen. In this case we would sometimes disable the workaround, simply because the touch
+ // screen hasn't yet overwritten the position and thus the workaround would not work anymore.
+ // On OpenPandora it would sometimes work and sometimes not without this.
+ if (s->_cursorWorkaroundPoint == mousePos) {
+ // Cursor is still at the same spot as set by the scripts
+ if (s->_cursorWorkaroundPosCount > 0) {
+ s->_cursorWorkaroundPosCount--;
+ } else {
+ // Was for quite a bit of time at that spot, so disable workaround now
+ s->_cursorWorkaroundActive = false;
+ }
+ } else {
+ // Cursor has moved, but is within the rect -> disable workaround immediately
+ s->_cursorWorkaroundActive = false;
+ }
} else {
mousePos.x = s->_cursorWorkaroundPoint.x;
mousePos.y = s->_cursorWorkaroundPoint.y;
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 979fa95a42..335763a35f 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -37,7 +37,6 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/savegame.h"
-#include "sci/graphics/menu.h"
#include "sci/sound/audio.h"
#include "sci/console.h"
@@ -602,6 +601,16 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
bool exists = false;
+ if (g_sci->getGameId() == GID_PEPPER) {
+ // HACK: Special case for Pepper's Adventure in Time
+ // The game checks like crazy for the file CDAUDIO when entering the game menu.
+ // On at least Windows that makes the engine slow down to a crawl and takes at least 1 second.
+ // Should get solved properly by changing the code below. This here is basically for 1.8.0 release.
+ // TODO: Fix this properly.
+ if (name == "CDAUDIO")
+ return NULL_REG;
+ }
+
// Check for regular file
exists = Common::File::exists(name);
@@ -907,50 +916,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
gamestate_restore(s, in);
delete in;
- switch (g_sci->getGameId()) {
- case GID_MOTHERGOOSE:
- // WORKAROUND: Mother Goose SCI0
- // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the
- // current number of children plus 1.
- // We can't trust that global, that's why we set the actual savedgame id right here directly after
- // restoring a saved game.
- // If we didn't, the game would always save to a new slot
- s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
- break;
- case GID_MOTHERGOOSE256:
- // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for
- // saving a previously restored game.
- // We set the current savedgame-id directly and remove the script
- // code concerning this via script patch.
- s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
- break;
- case GID_JONES:
- // HACK: The code that enables certain menu items isn't called when a game is restored from the
- // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723.
- // These menu entries are disabled when the game is launched, and are enabled when a new game is
- // started. The code for enabling these entries is is all in script 1, room1::init, but that code
- // path is never followed in these two cases (restoring game from the menu, or restoring a game
- // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here.
- // These two are needed when restoring from the launcher
- // FIXME: The original interpreter saves and restores the menu state, so these attributes
- // are automatically reset there. We may want to do the same.
- g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones
- g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help
- // The rest are normally enabled from room1::init
- g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player
- g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
- g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game
- g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics
- g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals
- break;
- case GID_PQ2:
- // HACK: Same as above - enable the save game menu option when loading in PQ2 (bug #6875).
- // It gets disabled in the game's death screen.
- g_sci->_gfxMenu->kernelSetAttribute(2, 1, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
- break;
- default:
- break;
- }
+ gamestate_afterRestoreFixUp(s, savegameId);
+
} else {
s->r_acc = TRUE_REG;
warning("Savegame #%d not found", savegameId);
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 0b945c1eec..73236b98ed 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -45,6 +45,7 @@
#include "sci/graphics/paint16.h"
#include "sci/graphics/picture.h"
#include "sci/graphics/ports.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/text16.h"
#include "sci/graphics/view.h"
@@ -359,12 +360,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
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(splitText.c_str(), font_nr, maxwidth, &textWidth, &textHeight);
- else
-#endif
- g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, 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
@@ -445,8 +441,15 @@ reg_t kCantBeHere(EngineState *s, int argc, reg_t *argv) {
reg_t curObject = argv[0];
reg_t listReference = (argc > 1) ? argv[1] : NULL_REG;
- reg_t canBeHere = g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
- return canBeHere;
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ return g_sci->_gfxCompare->kernelCantBeHere32(curObject, listReference);
+ } else {
+#endif
+ return g_sci->_gfxCompare->kernelCanBeHere(curObject, listReference);
+#ifdef ENABLE_SCI32
+ }
+#endif
}
reg_t kIsItSkip(EngineState *s, int argc, reg_t *argv) {
@@ -492,7 +495,7 @@ reg_t kNumLoops(EngineState *s, int argc, reg_t *argv) {
loopCount = g_sci->_gfxCache->kernelViewGetLoopCount(viewId);
- debugC(kDebugLevelGraphics, "NumLoops(view.%d) = %d", viewId, loopCount);
+ debugC(9, kDebugLevelGraphics, "NumLoops(view.%d) = %d", viewId, loopCount);
return make_reg(0, loopCount);
}
@@ -505,7 +508,7 @@ reg_t kNumCels(EngineState *s, int argc, reg_t *argv) {
celCount = g_sci->_gfxCache->kernelViewGetCelCount(viewId, loopNo);
- debugC(kDebugLevelGraphics, "NumCels(view.%d, %d) = %d", viewId, loopNo, celCount);
+ debugC(9, kDebugLevelGraphics, "NumCels(view.%d, %d) = %d", viewId, loopNo, celCount);
return make_reg(0, celCount);
}
@@ -576,9 +579,17 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) {
}
reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxCompare->kernelSetNowSeen(argv[0]);
-
- return s->r_acc;
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ g_sci->_gfxFrameout->kernelSetNowSeen(argv[0]);
+ return NULL_REG;
+ } else {
+#endif
+ g_sci->_gfxCompare->kernelSetNowSeen(argv[0]);
+ return s->r_acc;
+#ifdef ENABLE_SCI32
+ }
+#endif
}
reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
@@ -1247,22 +1258,22 @@ reg_t kShow(EngineState *s, int argc, reg_t *argv) {
}
// Early variant of the SCI32 kRemapColors kernel function, used in the demo of QFG4
-reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
+reg_t kRemapColors16(EngineState *s, int argc, reg_t *argv) {
uint16 operation = argv[0].toUint16();
switch (operation) {
case 0: { // remap by percent
uint16 percent = argv[1].toUint16();
- g_sci->_gfxPalette16->resetRemapping();
- g_sci->_gfxPalette16->setRemappingPercent(254, percent);
+ g_sci->_gfxRemap16->resetRemapping();
+ g_sci->_gfxRemap16->setRemappingPercent(254, percent);
}
break;
case 1: { // remap by range
uint16 from = argv[1].toUint16();
uint16 to = argv[2].toUint16();
uint16 base = argv[3].toUint16();
- g_sci->_gfxPalette16->resetRemapping();
- g_sci->_gfxPalette16->setRemappingRange(254, from, to, base);
+ g_sci->_gfxRemap16->resetRemapping();
+ g_sci->_gfxRemap16->setRemappingRange(254, from, to, base);
}
break;
case 2: // turn remapping off (unused)
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 8d41393a9e..7850a10006 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -45,15 +45,17 @@
#include "sci/graphics/paint16.h"
#include "sci/graphics/picture.h"
#include "sci/graphics/ports.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/text16.h"
#include "sci/graphics/view.h"
#ifdef ENABLE_SCI32
-#include "sci/graphics/palette32.h"
+#include "sci/graphics/celobj32.h"
#include "sci/graphics/controls32.h"
#include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class
-#include "sci/graphics/text32.h"
#include "sci/graphics/frameout.h"
+#include "sci/graphics/palette32.h"
+#include "sci/graphics/text32.h"
#endif
namespace Sci {
@@ -62,63 +64,67 @@ namespace Sci {
extern void showScummVMDialog(const Common::String &message);
reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) {
- // Returns 0 if the screen width or height is less than 640 or 400,
- // respectively.
- if (g_system->getWidth() < 640 || g_system->getHeight() < 400)
+ const Buffer &buffer = g_sci->_gfxFrameout->getCurrentBuffer();
+ if (buffer.screenWidth < 640 || buffer.screenHeight < 400)
return make_reg(0, 0);
return make_reg(0, 1);
}
-// SCI32 variant, can't work like sci16 variants
-reg_t kCantBeHere32(EngineState *s, int argc, reg_t *argv) {
- // TODO
-// reg_t curObject = argv[0];
-// reg_t listReference = (argc > 1) ? argv[1] : NULL_REG;
-
- return NULL_REG;
-}
-
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
- if (g_sci->_gfxFrameout->findScreenItem(argv[0]) == NULL)
- g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
- else
- g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
+ debugC(6, kDebugLevelGraphics, "kAddScreenItem %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
+ g_sci->_gfxFrameout->kernelAddScreenItem(argv[0]);
return s->r_acc;
}
reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
+ debugC(7, kDebugLevelGraphics, "kUpdateScreenItem %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
g_sci->_gfxFrameout->kernelUpdateScreenItem(argv[0]);
return s->r_acc;
}
reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
+ debugC(6, kDebugLevelGraphics, "kDeleteScreenItem %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
g_sci->_gfxFrameout->kernelDeleteScreenItem(argv[0]);
return s->r_acc;
}
reg_t kAddPlane(EngineState *s, int argc, reg_t *argv) {
+ debugC(6, kDebugLevelGraphics, "kAddPlane %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
g_sci->_gfxFrameout->kernelAddPlane(argv[0]);
return s->r_acc;
}
+reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
+ debugC(7, kDebugLevelGraphics, "kUpdatePlane %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
+ g_sci->_gfxFrameout->kernelUpdatePlane(argv[0]);
+ return s->r_acc;
+}
+
reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv) {
+ debugC(6, kDebugLevelGraphics, "kDeletePlane %x:%x (%s)", PRINT_REG(argv[0]), s->_segMan->getObjectName(argv[0]));
g_sci->_gfxFrameout->kernelDeletePlane(argv[0]);
return s->r_acc;
}
-reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxFrameout->kernelUpdatePlane(argv[0]);
+reg_t kMovePlaneItems(EngineState *s, int argc, reg_t *argv) {
+ const reg_t plane = argv[0];
+ const int16 deltaX = argv[1].toSint16();
+ const int16 deltaY = argv[2].toSint16();
+ const bool scrollPics = argc > 3 ? argv[3].toUint16() : false;
+
+ g_sci->_gfxFrameout->kernelMovePlaneItems(plane, deltaX, deltaY, scrollPics);
return s->r_acc;
}
reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) {
reg_t planeObj = argv[0];
GuiResourceId pictureId = argv[1].toUint16();
- int16 pictureX = argv[2].toSint16();
- int16 pictureY = argv[3].toSint16();
+ int16 x = argv[2].toSint16();
+ int16 y = argv[3].toSint16();
+ bool mirrorX = argc > 4 ? argv[4].toSint16() : false;
- g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, pictureX, pictureY);
+ g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, x, y, mirrorX);
return s->r_acc;
}
@@ -127,44 +133,16 @@ reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv) {
}
reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) {
-/* TODO: Transcribed from SCI engine disassembly.
- GraphicsMgr &graphicsMgr = g_sci->_graphicsMgr;
- if (graphicsMgr.palMorphNeeded) {
- graphicsMgr.PalMorphFrameOut(&g_PalStyleRanges, false);
- }
- else {
- // TODO: Not sure if this is a pointer or not yet.
- if (g_ScrollState != nullptr) {
- kFrameOutDoScroll();
- }
-
- bool showBits = true;
- if (argc == 1) {
- showBits = (bool) argv[0].toUint16();
- }
-
- rect SOL_Rect = { .left = 0, .top = 0, .right = UINT32_MAX, .bottom = UINT32_MAX };
- graphicsMgr.FrameOut(showBits, &rect);
- }
-*/
- g_sci->_gfxFrameout->kernelFrameout();
- return NULL_REG;
+ bool showBits = argc > 0 ? argv[0].toUint16() : true;
+ g_sci->_gfxFrameout->kernelFrameOut(showBits);
+ s->speedThrottler(16);
+ s->_throttleTrigger = true;
+ return s->r_acc;
}
reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) {
-/* TODO: Transcribed from SCI engine disassembly.
- uint16 start = argv[0].toUint16();
- uint16 end = argv[1].toUint16();
- if (end <= start) {
- uint16 index = start;
- while (index <= end) {
- g_PalStyleRanges[index] = 0;
- }
- }
-*/
-
- kStub(s, argc, argv);
- return NULL_REG;
+ g_sci->_gfxFrameout->kernelSetPalStyleRange(argv[0].toUint16(), argv[1].toUint16());
+ return s->r_acc;
}
reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) {
@@ -173,81 +151,92 @@ reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, objRect1.intersects(objRect2));
}
-// Tests if the coordinate is on the passed object
reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) {
- uint16 x = argv[0].toUint16();
- uint16 y = argv[1].toUint16();
- reg_t targetObject = argv[2];
- uint16 illegalBits = argv[3].getOffset();
- Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(targetObject);
-
- uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x));
- uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y));
- // If top and left are negative, we need to adjust coordinates by the item's x and y
- if (nsRect.left < 0)
- nsRect.translate(itemX, 0);
- if (nsRect.top < 0)
- nsRect.translate(0, itemY);
-
- // we assume that x, y are local coordinates
-
- bool contained = nsRect.contains(x, y);
- if (contained && illegalBits) {
- // If illegalbits are set, we check the color of the pixel that got clicked on
- // for now, we return false if the pixel is transparent
- // although illegalBits may get differently set, don't know yet how this really works out
- uint16 viewId = readSelectorValue(s->_segMan, targetObject, SELECTOR(view));
- int16 loopNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(loop));
- int16 celNo = readSelectorValue(s->_segMan, targetObject, SELECTOR(cel));
- if (g_sci->_gfxCompare->kernelIsItSkip(viewId, loopNo, celNo, Common::Point(x - nsRect.left, y - nsRect.top)))
- contained = false;
- }
- return make_reg(0, contained);
+ int16 x = argv[0].toSint16();
+ int16 y = argv[1].toSint16();
+ reg_t object = argv[2];
+ bool checkPixel = argv[3].toSint16();
+
+ return g_sci->_gfxFrameout->kernelIsOnMe(object, Common::Point(x, y), checkPixel);
}
reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 0: {
- if (argc != 4) {
- warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc);
- return NULL_REG;
- }
- reg_t object = argv[3];
- Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
- debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)",
- PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3]));
- debugC(kDebugLevelStrings, "%s", text.c_str());
- int16 maxWidth = argv[1].toUint16();
- int16 maxHeight = argv[2].toUint16();
- g_sci->_gfxCoordAdjuster->fromScriptToDisplay(maxHeight, maxWidth);
- // These values can be larger than the screen in the SQ6 demo, room 100
- // TODO: Find out why. For now, don't show any text in that room.
- if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo() && s->currentRoomNumber() == 100)
- return NULL_REG;
- return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight);
- }
- case 1: {
- if (argc != 2) {
- warning("kCreateTextBitmap(1): expected 2 arguments, got %i", argc);
- return NULL_REG;
- }
- reg_t object = argv[1];
- Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
- debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1]));
- debugC(kDebugLevelStrings, "%s", text.c_str());
- return g_sci->_gfxText32->createTextBitmap(object);
- }
- default:
- warning("CreateTextBitmap(%d)", argv[0].toUint16());
+ SegManager *segMan = s->_segMan;
+
+ int16 subop = argv[0].toUint16();
+
+ int16 width = 0;
+ int16 height = 0;
+ reg_t object;
+
+ if (subop == 0) {
+ width = argv[1].toUint16();
+ height = argv[2].toUint16();
+ object = argv[3];
+ } else if (subop == 1) {
+ object = argv[1];
+ } else {
+ warning("Invalid kCreateTextBitmap subop %d", subop);
return NULL_REG;
}
+
+ Common::String text = segMan->getString(readSelector(segMan, object, SELECTOR(text)));
+ int16 foreColor = readSelectorValue(segMan, object, SELECTOR(fore));
+ int16 backColor = readSelectorValue(segMan, object, SELECTOR(back));
+ int16 skipColor = readSelectorValue(segMan, object, SELECTOR(skip));
+ GuiResourceId fontId = (GuiResourceId)readSelectorValue(segMan, object, SELECTOR(font));
+ int16 borderColor = readSelectorValue(segMan, object, SELECTOR(borderColor));
+ int16 dimmed = readSelectorValue(segMan, object, SELECTOR(dimmed));
+
+ Common::Rect rect(
+ readSelectorValue(segMan, object, SELECTOR(textLeft)),
+ readSelectorValue(segMan, object, SELECTOR(textTop)),
+ readSelectorValue(segMan, object, SELECTOR(textRight)) + 1,
+ readSelectorValue(segMan, object, SELECTOR(textBottom)) + 1
+ );
+
+ if (subop == 0) {
+ TextAlign alignment = (TextAlign)readSelectorValue(segMan, object, SELECTOR(mode));
+ return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, true);
+ } else {
+ CelInfo32 celInfo;
+ celInfo.type = kCelTypeView;
+ celInfo.resourceId = readSelectorValue(segMan, object, SELECTOR(view));
+ celInfo.loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
+ celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel));
+ return g_sci->_gfxText32->createFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed);
+ }
+}
+
+reg_t kText(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
}
-reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gfxText32->disposeTextBitmap(argv[0]);
+reg_t kTextSize32(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText32->setFont(argv[2].toUint16());
+
+ reg_t *rect = s->_segMan->derefRegPtr(argv[0], 4);
+
+ Common::String text = s->_segMan->getString(argv[1]);
+ int16 maxWidth = argc > 3 ? argv[3].toSint16() : 0;
+ bool doScaling = argc > 4 ? argv[4].toSint16() : true;
+
+ Common::Rect textRect = g_sci->_gfxText32->getTextSize(text, maxWidth, doScaling);
+ rect[0] = make_reg(0, textRect.left);
+ rect[1] = make_reg(0, textRect.top);
+ rect[2] = make_reg(0, textRect.right - 1);
+ rect[3] = make_reg(0, textRect.bottom - 1);
return s->r_acc;
}
+reg_t kTextWidth(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText32->setFont(argv[1].toUint16());
+ Common::String text = s->_segMan->getString(argv[0]);
+ return make_reg(0, g_sci->_gfxText32->getStringWidth(text));
+}
+
reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case 1:
@@ -266,98 +255,137 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) {
}
/**
- * Used for scene transitions, replacing (but reusing parts of) the old
- * transition code.
+ * Causes an immediate plane transition with an optional transition
+ * effect
*/
reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
- // Can be called with 7 or 8 parameters
- // The style defines which transition to perform. Related to the transition
- // tables inside graphics/transitions.cpp
- uint16 showStyle = argv[0].toUint16(); // 0 - 15
- reg_t planeObj = argv[1]; // the affected plane
- Common::String planeObjName = s->_segMan->getObjectName(planeObj);
- uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts
- uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff
- int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out
- uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts
- uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out
+ ShowStyleType type = (ShowStyleType)argv[0].toUint16();
+ reg_t planeObj = argv[1];
+ int16 seconds = argv[2].toSint16();
+ // NOTE: This value seems to indicate whether the transition is an
+ // “exit†transition (0) or an “enter†transition (-1) for fade
+ // transitions. For other types of transitions, it indicates a palette
+ // index value to use when filling the screen.
+ int16 back = argv[3].toSint16();
+ int16 priority = argv[4].toSint16();
+ int16 animate = argv[5].toSint16();
+ // TODO: Rename to frameOutNow?
+ int16 refFrame = argv[6].toSint16();
+ int16 blackScreen;
+ reg_t pFadeArray;
int16 divisions;
- // If the game has the pFadeArray selector, another parameter is used here,
- // before the optional last parameter
- bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0;
- if (hasFadeArray) {
- // argv[7]
- divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?)
- } else {
- divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?)
+ // SCI 2–2.1early
+ if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ blackScreen = 0;
+ pFadeArray = NULL_REG;
+ divisions = argc > 7 ? argv[7].toSint16() : -1;
}
-
- if (showStyle > 15) {
- warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj));
- return s->r_acc;
+ // SCI 2.1mid–2.1late
+ else if (getSciVersion() < SCI_VERSION_3) {
+ blackScreen = 0;
+ pFadeArray = argc > 7 ? argv[7] : NULL_REG;
+ divisions = argc > 8 ? argv[8].toSint16() : -1;
+ }
+ // SCI 3
+ else {
+ blackScreen = argv[7].toSint16();
+ pFadeArray = argc > 8 ? argv[8] : NULL_REG;
+ divisions = argc > 9 ? argv[9].toSint16() : -1;
}
- // GK1 calls fadeout (13) / fadein (14) with the following parameters:
- // seconds: 1
- // backColor: 0 / -1
- // fade: 200
- // animate: 0
- // refFrame: 0
- // divisions: 0 / 20
+// TODO: Reuse later for SCI2 and SCI3 implementation and then discard
+// warning("kSetShowStyle: effect %d, plane: %04x:%04x (%s), sec: %d, "
+// "dir: %d, prio: %d, animate: %d, ref frame: %d, black screen: %d, "
+// "pFadeArray: %04x:%04x (%s), divisions: %d",
+// type, PRINT_REG(planeObj), s->_segMan->getObjectName(planeObj), seconds,
+// back, priority, animate, refFrame, blackScreen,
+// PRINT_REG(pFadeArray), s->_segMan->getObjectName(pFadeArray), divisions);
- // TODO: Check if the plane is in the list of planes to draw
+ // NOTE: The order of planeObj and showStyle are reversed
+ // because this is how SCI3 called the corresponding method
+ // on the KernelMgr
+ g_sci->_gfxFrameout->kernelSetShowStyle(argc, planeObj, type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen);
- Common::String effectName = "unknown";
+ return s->r_acc;
+}
- switch (showStyle) {
- case 0: // no transition / show
- effectName = "show";
+reg_t kCelHigh32(EngineState *s, int argc, reg_t *argv) {
+ GuiResourceId resourceId = argv[0].toUint16();
+ int16 loopNo = argv[1].toSint16();
+ int16 celNo = argv[2].toSint16();
+ CelObjView celObj(resourceId, loopNo, celNo);
+ return make_reg(0, mulru(celObj._height, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, celObj._scaledHeight)));
+}
+
+reg_t kCelWide32(EngineState *s, int argc, reg_t *argv) {
+ GuiResourceId resourceId = argv[0].toUint16();
+ int16 loopNo = argv[1].toSint16();
+ int16 celNo = argv[2].toSint16();
+ CelObjView celObj(resourceId, loopNo, celNo);
+ return make_reg(0, mulru(celObj._width, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, celObj._scaledWidth)));
+}
+
+reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
+ // Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board
+ // are occupied by pieces already
+
+ CelObjView view(argv[1].toUint16(), argv[2].toSint16(), argv[3].toSint16());
+
+ int16 result = 0;
+
+ switch (argv[0].toUint16()) {
+ case 0:
+ result = view._displace.x;
break;
- case 13: // fade out
- effectName = "fade out";
- // TODO
+ case 1:
+ result = view._displace.y;
break;
- case 14: // fade in
- effectName = "fade in";
- // TODO
+ case 2:
+ case 3:
+ // null operation
break;
- default:
- // TODO
+ case 4:
+ result = view.readPixel(argv[4].toSint16(), argv[5].toSint16(), view._mirrorX);
break;
}
- warning("kSetShowStyle: effect %d (%s) - plane: %04x:%04x (%s), sec: %d, "
- "back: %d, prio: %d, animate: %d, ref frame: %d, divisions: %d",
- showStyle, effectName.c_str(), PRINT_REG(planeObj), planeObjName.c_str(),
- seconds, backColor, priority, animate, refFrame, divisions);
- return s->r_acc;
+ return make_reg(0, result);
}
-reg_t kCelInfo(EngineState *s, int argc, reg_t *argv) {
- // Used by Shivers 1, room 23601 to determine what blocks on the red door puzzle board
- // are occupied by pieces already
+reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- switch (argv[0].toUint16()) { // subops 0 - 4
- // 0 - return the view
- // 1 - return the loop
- // 2, 3 - nop
- case 4: {
- GuiResourceId viewId = argv[1].toSint16();
- int16 loopNo = argv[2].toSint16();
- int16 celNo = argv[3].toSint16();
- int16 x = argv[4].toUint16();
- int16 y = argv[5].toUint16();
- byte color = g_sci->_gfxCache->kernelViewGetColorAtCoordinate(viewId, loopNo, celNo, x, y);
- return make_reg(0, color);
- }
- default: {
- kStub(s, argc, argv);
- return s->r_acc;
- }
- }
+reg_t kScrollWindowCreate(EngineState *s, int argc, reg_t *argv) {
+ debug("kScrollWindowCreate");
+ kStub(s, argc, argv);
+ return argv[0];
+}
+
+reg_t kScrollWindowAdd(EngineState *s, int argc, reg_t *argv) {
+ debug("kScrollWindowAdd");
+ return kStubNull(s, argc, argv);
}
+reg_t kScrollWindowWhere(EngineState *s, int argc, reg_t *argv) {
+ debug("kScrollWindowWhere");
+ return kStubNull(s, argc, argv);
+}
+
+reg_t kScrollWindowShow(EngineState *s, int argc, reg_t *argv) {
+ debug("kScrollWindowShow");
+ return kStubNull(s, argc, argv);
+}
+
+reg_t kScrollWindowDestroy(EngineState *s, int argc, reg_t *argv) {
+ debug("kScrollWindowDestroy");
+ return kStubNull(s, argc, argv);
+}
+
+#if 0
reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
// Used by SQ6 and LSL6 hires for the text area in the bottom of the
// screen. The relevant scripts also exist in Phantasmagoria 1, but they're
@@ -465,226 +493,233 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+#endif
+
+reg_t kFont(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
+
+reg_t kSetFontHeight(EngineState *s, int argc, reg_t *argv) {
+ // TODO: Setting font may have just been for side effect
+ // of setting the fontHeight on the font manager, in
+ // which case we could just get the font directly ourselves.
+ g_sci->_gfxText32->setFont(argv[0].toUint16());
+ g_sci->_gfxText32->_scaledHeight = (g_sci->_gfxText32->_font->getHeight() * g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight + g_sci->_gfxText32->_scaledHeight - 1) / g_sci->_gfxText32->_scaledHeight;
+ return make_reg(0, g_sci->_gfxText32->_scaledHeight);
+}
reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) {
- // TODO: This defines the resolution that the fonts are supposed to be displayed
- // in. Currently, this is only used for showing high-res fonts in GK1 Mac, but
- // should be extended to handle other font resolutions such as those
+ g_sci->_gfxText32->_scaledWidth = argv[0].toUint16();
+ g_sci->_gfxText32->_scaledHeight = argv[1].toUint16();
+ return s->r_acc;
+}
- int xResolution = argv[0].toUint16();
- //int yResolution = argv[1].toUint16();
+reg_t kBitmap(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- g_sci->_gfxScreen->setFontIsUpscaled(xResolution == 640 &&
- g_sci->_gfxScreen->getUpscaledHires() != GFX_SCREEN_UPSCALED_DISABLED);
+reg_t kBitmapCreate(EngineState *s, int argc, reg_t *argv) {
+ int16 width = argv[0].toSint16();
+ int16 height = argv[1].toSint16();
+ int16 skipColor = argv[2].toSint16();
+ int16 backColor = argv[3].toSint16();
+ int16 scaledWidth = argc > 4 ? argv[4].toSint16() : g_sci->_gfxText32->_scaledWidth;
+ int16 scaledHeight = argc > 5 ? argv[5].toSint16() : g_sci->_gfxText32->_scaledHeight;
+ bool useRemap = argc > 6 ? argv[6].toSint16() : false;
- return s->r_acc;
+ BitmapResource bitmap(s->_segMan, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap);
+ memset(bitmap.getPixels(), backColor, width * height);
+ return bitmap.getObject();
}
-reg_t kFont(EngineState *s, int argc, reg_t *argv) {
- // Handle font settings for SCI2.1
+reg_t kBitmapDestroy(EngineState *s, int argc, reg_t *argv) {
+ s->_segMan->freeHunkEntry(argv[0]);
+ return s->r_acc;
+}
- switch (argv[0].toUint16()) {
- case 1:
- // Set font resolution
- return kSetFontRes(s, argc - 1, argv + 1);
- default:
- warning("kFont: unknown subop %d", argv[0].toUint16());
+reg_t kBitmapDrawLine(EngineState *s, int argc, reg_t *argv) {
+ // bitmapMemId, (x1, y1, x2, y2) OR (x2, y2, x1, y1), line color, unknown int, unknown int
+ return kStubNull(s, argc + 1, argv - 1);
+}
+
+reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv) {
+ // viewId, loopNo, celNo, displace x, displace y, unused, view x, view y
+
+ // called e.g. from TiledBitmap::resize() in Torin's Passage, script 64869
+ // The tiled view seems to always have 2 loops.
+ // These loops need to have 1 cel in loop 0 and 8 cels in loop 1.
+
+ return kStubNull(s, argc + 1, argv - 1);
+
+#if 0
+ // tiled surface
+ // 6 params, called e.g. from TiledBitmap::resize() in Torin's Passage,
+ // script 64869
+ reg_t hunkId = argv[1]; // obtained from kBitmap(0)
+ // The tiled view seems to always have 2 loops.
+ // These loops need to have 1 cel in loop 0 and 8 cels in loop 1.
+ uint16 viewNum = argv[2].toUint16(); // vTiles selector
+ uint16 loop = argv[3].toUint16();
+ uint16 cel = argv[4].toUint16();
+ uint16 x = argv[5].toUint16();
+ uint16 y = argv[6].toUint16();
+
+ byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
+ // Get totalWidth, totalHeight
+ uint16 totalWidth = READ_LE_UINT16(memoryPtr);
+ uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2);
+ byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
+
+ GfxView *view = g_sci->_gfxCache->getView(viewNum);
+ uint16 tileWidth = view->getWidth(loop, cel);
+ uint16 tileHeight = view->getHeight(loop, cel);
+ const byte *tileBitmap = view->getBitmap(loop, cel);
+ uint16 width = MIN<uint16>(totalWidth - x, tileWidth);
+ uint16 height = MIN<uint16>(totalHeight - y, tileHeight);
+
+ for (uint16 curY = 0; curY < height; curY++) {
+ for (uint16 curX = 0; curX < width; curX++) {
+ bitmap[(curY + y) * totalWidth + (curX + x)] = tileBitmap[curY * tileWidth + curX];
+ }
}
+#endif
+}
+
+reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) {
+ // called e.g. from TextButton::createBitmap() in Torin's Passage, script 64894
+
+ BitmapResource bitmap(argv[0]);
+ Common::String text = s->_segMan->getString(argv[1]);
+ Common::Rect textRect(
+ argv[2].toSint16(),
+ argv[3].toSint16(),
+ argv[4].toSint16() + 1,
+ argv[5].toSint16() + 1
+ );
+ int16 foreColor = argv[6].toSint16();
+ int16 backColor = argv[7].toSint16();
+ int16 skipColor = argv[8].toSint16();
+ GuiResourceId fontId = (GuiResourceId)argv[9].toUint16();
+ TextAlign alignment = (TextAlign)argv[10].toSint16();
+ int16 borderColor = argv[11].toSint16();
+ bool dimmed = argv[12].toUint16();
+
+ // NOTE: Technically the engine checks these things:
+ // textRect.bottom > 0
+ // textRect.right > 0
+ // textRect.left < bitmap.width
+ // textRect.top < bitmap.height
+ // Then clips. But this seems stupid.
+ textRect.clip(Common::Rect(bitmap.getWidth(), bitmap.getHeight()));
+
+ reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false);
+ Buffer bitmapBuffer(bitmap.getWidth(), bitmap.getHeight(), bitmap.getPixels());
+ CelObjMem textCel(textBitmapObject);
+ textCel.draw(bitmapBuffer, textRect, Common::Point(textRect.left, textRect.top), false);
+ s->_segMan->freeHunkEntry(textBitmapObject);
return s->r_acc;
}
-// TODO: Eventually, all of the kBitmap operations should be put
-// in a separate class
+reg_t kBitmapDrawColor(EngineState *s, int argc, reg_t *argv) {
+ // called e.g. from TextView::init() and TextView::draw() in Torin's Passage, script 64890
-#define BITMAP_HEADER_SIZE 46
+ BitmapResource bitmap(argv[0]);
+ Common::Rect fillRect(
+ argv[1].toSint16(),
+ argv[2].toSint16(),
+ argv[3].toSint16() + 1,
+ argv[4].toSint16() + 1
+ );
-reg_t kBitmap(EngineState *s, int argc, reg_t *argv) {
- // Used for bitmap operations in SCI2.1 and SCI3.
- // This is the SCI2.1 version, the functionality seems to have changed in SCI3.
+ Buffer buffer(bitmap.getWidth(), bitmap.getHeight(), bitmap.getPixels());
+ buffer.fillRect(fillRect, argv[5].toSint16());
+ return s->r_acc;
+}
- switch (argv[0].toUint16()) {
- case 0: // init bitmap surface
- {
- // 6 params, called e.g. from TextView::init() in Torin's Passage,
- // script 64890 and TransView::init() in script 64884
- uint16 width = argv[1].toUint16();
- uint16 height = argv[2].toUint16();
- //uint16 skip = argv[3].toUint16();
- uint16 back = argv[4].toUint16(); // usually equals skip
- //uint16 width2 = (argc >= 6) ? argv[5].toUint16() : 0;
- //uint16 height2 = (argc >= 7) ? argv[6].toUint16() : 0;
- //uint16 transparentFlag = (argc >= 8) ? argv[7].toUint16() : 0;
-
- // TODO: skip, width2, height2, transparentFlag
- // (used for transparent bitmaps)
- int entrySize = width * height + BITMAP_HEADER_SIZE;
- reg_t memoryId = s->_segMan->allocateHunkEntry("Bitmap()", entrySize);
- byte *memoryPtr = s->_segMan->getHunkPointer(memoryId);
- memset(memoryPtr, 0, BITMAP_HEADER_SIZE); // zero out the bitmap header
- memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height);
- // Save totalWidth, totalHeight
- // TODO: Save the whole bitmap header, like SSCI does
- WRITE_LE_UINT16(memoryPtr, width);
- WRITE_LE_UINT16(memoryPtr + 2, height);
- return memoryId;
- }
- break;
- case 1: // dispose text bitmap surface
- return kDisposeTextBitmap(s, argc - 1, argv + 1);
- case 2: // dispose bitmap surface, with extra param
- // 2 params, called e.g. from MenuItem::dispose in Torin's Passage,
- // script 64893
- warning("kBitmap(2), unk1 %d, bitmap ptr %04x:%04x", argv[1].toUint16(), PRINT_REG(argv[2]));
- break;
- case 3: // tiled surface
- {
- // 6 params, called e.g. from TiledBitmap::resize() in Torin's Passage,
- // script 64869
- reg_t hunkId = argv[1]; // obtained from kBitmap(0)
- // The tiled view seems to always have 2 loops.
- // These loops need to have 1 cel in loop 0 and 8 cels in loop 1.
- uint16 viewNum = argv[2].toUint16(); // vTiles selector
- uint16 loop = argv[3].toUint16();
- uint16 cel = argv[4].toUint16();
- uint16 x = argv[5].toUint16();
- uint16 y = argv[6].toUint16();
-
- byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
- // Get totalWidth, totalHeight
- uint16 totalWidth = READ_LE_UINT16(memoryPtr);
- uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2);
- byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
-
- GfxView *view = g_sci->_gfxCache->getView(viewNum);
- uint16 tileWidth = view->getWidth(loop, cel);
- uint16 tileHeight = view->getHeight(loop, cel);
- const byte *tileBitmap = view->getBitmap(loop, cel);
- uint16 width = MIN<uint16>(totalWidth - x, tileWidth);
- uint16 height = MIN<uint16>(totalHeight - y, tileHeight);
-
- for (uint16 curY = 0; curY < height; curY++) {
- for (uint16 curX = 0; curX < width; curX++) {
- bitmap[(curY + y) * totalWidth + (curX + x)] = tileBitmap[curY * tileWidth + curX];
- }
- }
+reg_t kBitmapDrawBitmap(EngineState *s, int argc, reg_t *argv) {
+ // target bitmap, source bitmap, x, y, unknown boolean
- }
- break;
- case 4: // add text to bitmap
- {
- // 13 params, called e.g. from TextButton::createBitmap() in Torin's Passage,
- // script 64894
- reg_t hunkId = argv[1]; // obtained from kBitmap(0)
- Common::String text = s->_segMan->getString(argv[2]);
- uint16 textX = argv[3].toUint16();
- uint16 textY = argv[4].toUint16();
- //reg_t unk5 = argv[5];
- //reg_t unk6 = argv[6];
- //reg_t unk7 = argv[7]; // skip?
- //reg_t unk8 = argv[8]; // back?
- //reg_t unk9 = argv[9];
- uint16 fontId = argv[10].toUint16();
- //uint16 mode = argv[11].toUint16();
- uint16 dimmed = argv[12].toUint16();
- //warning("kBitmap(4): bitmap ptr %04x:%04x, font %d, mode %d, dimmed %d - text: \"%s\"",
- // PRINT_REG(bitmapPtr), font, mode, dimmed, text.c_str());
- uint16 foreColor = 255; // TODO
-
- byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
- // Get totalWidth, totalHeight
- uint16 totalWidth = READ_LE_UINT16(memoryPtr);
- uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2);
- byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
-
- GfxFont *font = g_sci->_gfxCache->getFont(fontId);
-
- int16 charCount = 0;
- uint16 curX = textX, curY = textY;
- const char *txt = text.c_str();
-
- while (*txt) {
- charCount = g_sci->_gfxText32->GetLongest(txt, totalWidth, font);
- if (charCount == 0)
- break;
-
- for (int i = 0; i < charCount; i++) {
- unsigned char curChar = txt[i];
- font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, totalWidth, totalHeight);
- curX += font->getCharWidth(curChar);
- }
-
- curX = textX;
- curY += font->getHeight();
- txt += charCount;
- while (*txt == ' ')
- txt++; // skip over breaking spaces
- }
+ return kStubNull(s, argc + 1, argv - 1);
+}
- }
- break;
- case 5: // fill with color
- {
- // 6 params, called e.g. from TextView::init() and TextView::draw()
- // in Torin's Passage, script 64890
- reg_t hunkId = argv[1]; // obtained from kBitmap(0)
- uint16 x = argv[2].toUint16();
- uint16 y = argv[3].toUint16();
- uint16 fillWidth = argv[4].toUint16(); // width - 1
- uint16 fillHeight = argv[5].toUint16(); // height - 1
- uint16 back = argv[6].toUint16();
-
- byte *memoryPtr = s->_segMan->getHunkPointer(hunkId);
- // Get totalWidth, totalHeight
- uint16 totalWidth = READ_LE_UINT16(memoryPtr);
- uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2);
- uint16 width = MIN<uint16>(totalWidth - x, fillWidth);
- uint16 height = MIN<uint16>(totalHeight - y, fillHeight);
- byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
-
- for (uint16 curY = 0; curY < height; curY++) {
- for (uint16 curX = 0; curX < width; curX++) {
- bitmap[(curY + y) * totalWidth + (curX + x)] = back;
- }
- }
+reg_t kBitmapInvert(EngineState *s, int argc, reg_t *argv) {
+ // bitmap, left, top, right, bottom, foreColor, backColor
- }
- break;
- default:
- kStub(s, argc, argv);
- break;
- }
+ return kStubNull(s, argc + 1, argv - 1);
+}
+reg_t kBitmapSetDisplace(EngineState *s, int argc, reg_t *argv) {
+ BitmapResource bitmap(argv[0]);
+ bitmap.setDisplace(Common::Point(argv[1].toSint16(), argv[2].toSint16()));
return s->r_acc;
}
-// Used for edit boxes in save/load dialogs. It's a rewritten version of kEditControl,
-// but it handles events on its own, using an internal loop, instead of using SCI
-// scripts for event management like kEditControl does. Called by script 64914,
-// DEdit::hilite().
-reg_t kEditText(EngineState *s, int argc, reg_t *argv) {
- reg_t controlObject = argv[0];
+reg_t kBitmapCreateFromView(EngineState *s, int argc, reg_t *argv) {
+ // viewId, loopNo, celNo, skipColor, backColor, useRemap, source overlay bitmap
- if (!controlObject.isNull()) {
- g_sci->_gfxControls32->kernelTexteditChange(controlObject);
- }
+ return kStub(s, argc + 1, argv - 1);
+}
- return s->r_acc;
+reg_t kBitmapCopyPixels(EngineState *s, int argc, reg_t *argv) {
+ // target bitmap, source bitmap
+
+ return kStubNull(s, argc + 1, argv - 1);
+}
+
+reg_t kBitmapClone(EngineState *s, int argc, reg_t *argv) {
+ // bitmap
+
+ return kStub(s, argc + 1, argv - 1);
+}
+
+reg_t kBitmapGetInfo(EngineState *s, int argc, reg_t *argv) {
+ // bitmap
+
+ // argc 1 = get width
+ // argc 2 = pixel at row 0 col n
+ // argc 3 = pixel at row n col n
+ return kStub(s, argc + 1, argv - 1);
+}
+
+reg_t kBitmapScale(EngineState *s, int argc, reg_t *argv) {
+ // TODO: SCI3
+ return kStubNull(s, argc + 1, argv - 1);
+}
+
+reg_t kBitmapCreateFromUnknown(EngineState *s, int argc, reg_t *argv) {
+ // TODO: SCI3
+ return kStub(s, argc + 1, argv - 1);
+}
+
+reg_t kEditText(EngineState *s, int argc, reg_t *argv) {
+ return g_sci->_gfxControls32->kernelEditText(argv[0]);
}
reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
+ return kStubNull(s, argc, argv); // return 0:0 for now, so that follow up calls won't create signature mismatches
+#if 0
reg_t plane = argv[0];
Common::Point startPoint(argv[1].toUint16(), argv[2].toUint16());
Common::Point endPoint(argv[3].toUint16(), argv[4].toUint16());
- // argv[5] is unknown (a number, usually 200)
+ byte priority = (byte)argv[5].toUint16();
byte color = (byte)argv[6].toUint16();
- byte priority = (byte)argv[7].toUint16();
- byte control = (byte)argv[8].toUint16();
- // argv[9] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
- return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, control);
+ byte style = (byte)argv[7].toUint16(); // 0: solid, 1: dashed, 2: pattern
+ byte pattern = (byte)argv[8].toUint16();
+ byte thickness = (byte)argv[9].toUint16();
+// return g_sci->_gfxFrameout->addPlaneLine(plane, startPoint, endPoint, color, priority, 0);
+ return s->r_acc;
+#endif
}
reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+
+#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
Common::Point startPoint(argv[2].toUint16(), argv[3].toUint16());
@@ -694,14 +729,18 @@ reg_t kUpdateLine(EngineState *s, int argc, reg_t *argv) {
byte priority = (byte)argv[8].toUint16();
byte control = (byte)argv[9].toUint16();
// argv[10] is unknown (usually a small number, 1 or 2). Thickness, perhaps?
- g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
+// g_sci->_gfxFrameout->updatePlaneLine(plane, hunkId, startPoint, endPoint, color, priority, control);
return s->r_acc;
+#endif
}
reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+#if 0
reg_t hunkId = argv[0];
reg_t plane = argv[1];
- g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
+// g_sci->_gfxFrameout->deletePlaneLine(plane, hunkId);
return s->r_acc;
+#endif
}
reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
@@ -730,13 +769,8 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
// Used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270)
reg_t kMorphOn(EngineState *s, int argc, reg_t *argv) {
- // TODO: g_sci->_gfxManager->palMorphIsOn = true
- // This function sets the palMorphIsOn flag which causes kFrameOut to use
- // an alternative FrameOut function (GraphicsMgr::PalMorphFrameOut instead
- // of GraphicsMgr::FrameOut). At the end of the frame, kFrameOut sets the
- // palMorphIsOn flag back to false.
- kStub(s, argc, argv);
- return NULL_REG;
+ g_sci->_gfxFrameout->_palMorphIsOn = true;
+ return s->r_acc;
}
reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) {
@@ -744,7 +778,7 @@ reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) {
uint16 toColor = argv[1].toUint16();
uint16 percent = argv[2].toUint16();
g_sci->_gfxPalette32->setFade(percent, fromColor, toColor);
- return NULL_REG;
+ return s->r_acc;
}
reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv) {
@@ -762,14 +796,14 @@ reg_t kPalVarySetVary(EngineState *s, int argc, reg_t *argv) {
}
g_sci->_gfxPalette32->kernelPalVarySet(paletteId, percent, time, fromColor, toColor);
- return NULL_REG;
+ return s->r_acc;
}
reg_t kPalVarySetPercent(EngineState *s, int argc, reg_t *argv) {
int time = argc > 0 ? argv[0].toSint16() * 60 : 0;
int16 percent = argc > 1 ? argv[1].toSint16() : 0;
g_sci->_gfxPalette32->setVaryPercent(percent, time, -1, -1);
- return NULL_REG;
+ return s->r_acc;
}
reg_t kPalVaryGetPercent(EngineState *s, int argc, reg_t *argv) {
@@ -778,7 +812,7 @@ reg_t kPalVaryGetPercent(EngineState *s, int argc, reg_t *argv) {
reg_t kPalVaryOff(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxPalette32->varyOff();
- return NULL_REG;
+ return s->r_acc;
}
reg_t kPalVaryMergeTarget(EngineState *s, int argc, reg_t *argv) {
@@ -790,7 +824,7 @@ reg_t kPalVaryMergeTarget(EngineState *s, int argc, reg_t *argv) {
reg_t kPalVarySetTime(EngineState *s, int argc, reg_t *argv) {
int time = argv[0].toSint16() * 60;
g_sci->_gfxPalette32->setVaryTime(time);
- return NULL_REG;
+ return s->r_acc;
}
reg_t kPalVarySetTarget(EngineState *s, int argc, reg_t *argv) {
@@ -875,76 +909,57 @@ reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
-reg_t kRemapColors32(EngineState *s, int argc, reg_t *argv) {
- uint16 operation = argv[0].toUint16();
+reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- switch (operation) {
- case 0: { // turn remapping off
- // WORKAROUND: Game scripts in QFG4 erroneously turn remapping off in room
- // 140 (the character point allocation screen) and never turn it back on,
- // even if it's clearly used in that screen.
- if (g_sci->getGameId() == GID_QFG4 && s->currentRoomNumber() == 140)
- return s->r_acc;
+reg_t kRemapOff(EngineState *s, int argc, reg_t *argv) {
+ byte color = (argc >= 1) ? argv[0].toUint16() : 0;
+ g_sci->_gfxRemap32->remapOff(color);
+ return s->r_acc;
+}
- int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
- if (base > 0)
- warning("kRemapColors(0) called with base %d", base);
- g_sci->_gfxPalette32->resetRemapping();
- }
- break;
- case 1: { // remap by range
- uint16 color = argv[1].toUint16();
- uint16 from = argv[2].toUint16();
- uint16 to = argv[3].toUint16();
- uint16 base = argv[4].toUint16();
- uint16 unk5 = (argc >= 6) ? argv[5].toUint16() : 0;
- if (unk5 > 0)
- warning("kRemapColors(1) called with 6 parameters, unknown parameter is %d", unk5);
- g_sci->_gfxPalette32->setRemappingRange(color, from, to, base);
- }
- break;
- case 2: { // remap by percent
- uint16 color = argv[1].toUint16();
- uint16 percent = argv[2].toUint16(); // 0 - 100
- if (argc >= 4)
- warning("RemapByPercent called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
- g_sci->_gfxPalette32->setRemappingPercent(color, percent);
- }
- break;
- case 3: { // remap to gray
- // Example call: QFG4 room 490 (Baba Yaga's hut) - params are color 253, 75% and 0.
- // In this room, it's used for the cloud before Baba Yaga appears.
- int16 color = argv[1].toSint16();
- int16 percent = argv[2].toSint16(); // 0 - 100
- if (argc >= 4)
- warning("RemapToGray called with 4 parameters, unknown parameter is %d", argv[3].toUint16());
- g_sci->_gfxPalette32->setRemappingPercentGray(color, percent);
- }
- break;
- case 4: { // remap to percent gray
- // Example call: QFG4 rooms 530/535 (swamp) - params are 253, 100%, 200
- int16 color = argv[1].toSint16();
- int16 percent = argv[2].toSint16(); // 0 - 100
- // argv[3] is unknown (a number, e.g. 200) - start color, perhaps?
- if (argc >= 5)
- warning("RemapToGrayPercent called with 5 parameters, unknown parameter is %d", argv[4].toUint16());
- g_sci->_gfxPalette32->setRemappingPercentGray(color, percent);
- }
- break;
- case 5: { // don't map to range
- //int16 mapping = argv[1].toSint16();
- uint16 intensity = argv[2].toUint16();
- // HACK for PQ4
- if (g_sci->getGameId() == GID_PQ4)
- g_sci->_gfxPalette32->kernelSetIntensity(0, 255, intensity, true);
+reg_t kRemapByRange(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte from = argv[1].toUint16();
+ byte to = argv[2].toUint16();
+ byte base = argv[3].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingRange(color, from, to, base);
+ return s->r_acc;
+}
- kStub(s, argc, argv);
- }
- break;
- default:
- break;
- }
+reg_t kRemapByPercent(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte percent = argv[1].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingPercent(color, percent);
+ return s->r_acc;
+}
+
+reg_t kRemapToGray(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte gray = argv[1].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingToGray(color, gray);
+ return s->r_acc;
+}
+
+reg_t kRemapToPercentGray(EngineState *s, int argc, reg_t *argv) {
+ byte color = argv[0].toUint16();
+ byte gray = argv[1].toUint16();
+ byte percent = argv[2].toUint16();
+ // The last parameter, depth, is unused
+ g_sci->_gfxRemap32->setRemappingToPercentGray(color, gray, percent);
+ return s->r_acc;
+}
+reg_t kRemapSetNoMatchRange(EngineState *s, int argc, reg_t *argv) {
+ byte from = argv[0].toUint16();
+ byte count = argv[1].toUint16();
+ g_sci->_gfxRemap32->setNoMatchRange(from, count);
return s->r_acc;
}
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 9d47a37bca..f4bb4ff85b 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -268,7 +268,10 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case K_MEMORY_ALLOCATE_CRITICAL: {
int byteCount = argv[1].toUint16();
- // WORKAROUND:
+ // Sierra themselves allocated at least 2 bytes more than requested.
+ // Probably as a safety margin. And they also made size even.
+ //
+ // This behavior is required by at least these:
// - pq3 (multilingual) room 202
// when plotting crimes, allocates the returned bytes from kStrLen
// on "W" and "E" and wants to put a string in there, which doesn't
@@ -276,18 +279,22 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) {
// - lsl5 (multilingual) room 280
// allocates memory according to a previous kStrLen for the name of
// the airport ladies (bug #3093818), which isn't enough
-
- // We always allocate 1 byte more, because of this
- byteCount++;
+ byteCount += 2 + (byteCount & 1);
if (!s->_segMan->allocDynmem(byteCount, "kMemory() critical", &s->r_acc)) {
error("Critical heap allocation failed");
}
break;
}
- case K_MEMORY_ALLOCATE_NONCRITICAL:
- s->_segMan->allocDynmem(argv[1].toUint16(), "kMemory() non-critical", &s->r_acc);
+ case K_MEMORY_ALLOCATE_NONCRITICAL: {
+ int byteCount = argv[1].toUint16();
+
+ // See above
+ byteCount += 2 + (byteCount & 1);
+
+ s->_segMan->allocDynmem(byteCount, "kMemory() non-critical", &s->r_acc);
break;
+ }
case K_MEMORY_FREE :
if (!s->_segMan->freeDynmem(argv[1])) {
if (g_sci->getGameId() == GID_QFG1VGA) {
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 5b2245e84d..7ac744f584 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -1943,14 +1943,14 @@ static int liesBefore(const Vertex *v, const Common::Point &p1, const Common::Po
// indexp1/vertexp1 on the polygon being merged.
// It ends with the point intersection2, being the analogous intersection.
struct Patch {
- unsigned int indexw1;
- unsigned int indexp1;
+ uint32 indexw1;
+ uint32 indexp1;
const Vertex *vertexw1;
const Vertex *vertexp1;
Common::Point intersection1;
- unsigned int indexw2;
- unsigned int indexp2;
+ uint32 indexw2;
+ uint32 indexp2;
const Vertex *vertexw2;
const Vertex *vertexp2;
Common::Point intersection2;
@@ -1960,7 +1960,7 @@ struct Patch {
// Check if the given vertex on the work polygon is bypassed by this patch.
-static bool isVertexCovered(const Patch &p, unsigned int wi) {
+static bool isVertexCovered(const Patch &p, uint32 wi) {
// / v (outside)
// ---w1--1----p----w2--2----
@@ -2402,7 +2402,7 @@ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) {
// Copy work.vertices into arrayRef
Vertex *vertex;
- unsigned int n = 0;
+ uint32 n = 0;
CLIST_FOREACH(vertex, &work.vertices) {
if (vertex == work.vertices._head || vertex->v != vertex->_prev->v)
writePoint(arrayRef, n++, vertex->v);
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 032191e4c1..398a623286 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -206,8 +206,15 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
// athrxx: It seems from disasm that the original KQ5 FM-Towns loads a default language (Japanese) audio map at the beginning
// right after loading the video and audio drivers. The -1 language argument in here simply means that the original will stick
// with Japanese. Instead of doing that we switch to the language selected in the launcher.
- if (g_sci->getPlatform() == Common::kPlatformFMTowns && language == -1)
- language = (g_sci->getLanguage() == Common::JA_JPN) ? K_LANG_JAPANESE : K_LANG_ENGLISH;
+ if (g_sci->getPlatform() == Common::kPlatformFMTowns && language == -1) {
+ // FM-Towns calls us to get the current language / also set the default language
+ // This doesn't just happen right at the start, but also when the user clicks on the Sierra logo in the game menu
+ // It uses the result of this call to either show "English Voices" or "Japanese Voices".
+
+ // Language should have been set by setLauncherLanguage() already (or could have been modified by the scripts).
+ // Get this language setting, so that the chosen language will get set for resource manager.
+ language = g_sci->getSciLanguage();
+ }
debugC(kDebugLevelSound, "kDoAudio: set language to %d", language);
@@ -233,19 +240,38 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
#endif
}
- // 3 new subops in Pharkas. kDoAudio in Pharkas sits at seg026:038C
+ // 3 new subops in Pharkas CD (including CD demo). kDoAudio in Pharkas sits at seg026:038C
case 11:
// Not sure where this is used yet
warning("kDoAudio: Unhandled case 11, %d extra arguments passed", argc - 1);
break;
case 12:
- // Seems to be some sort of audio sync, used in Pharkas. Silenced the
- // warning due to the high level of spam it produces. (takes no params)
- //warning("kDoAudio: Unhandled case 12, %d extra arguments passed", argc - 1);
+ // SSCI calls this function with no parameters from
+ // the TalkRandCycle class and branches on the return
+ // value like a boolean. The conjectured purpose of
+ // this function is to ensure that the talker's mouth
+ // does not move if there is read jitter (slow CD
+ // drive, scratched CD). The old behavior here of not
+ // doing anything caused a nonzero value to be left in
+ // the accumulator by chance. This is equivalent, but
+ // more explicit.
+
+ return make_reg(0, 1);
break;
case 13:
- // Used in Pharkas whenever a speech sample starts (takes no params)
- //warning("kDoAudio: Unhandled case 13, %d extra arguments passed", argc - 1);
+ // SSCI returns a serial number for the played audio
+ // here, used in the PointsSound class. The reason is severalfold:
+
+ // 1. SSCI does not support multiple wave effects at once
+ // 2. FPFP may disable its icon bar during the points sound.
+ // 3. Each new sound preempts any sound already playing.
+ // 4. If the points sound is interrupted before completion,
+ // the icon bar could remain disabled.
+
+ // Since points (1) and (3) do not apply to us, we can simply
+ // return a constant here. This is equivalent to the
+ // old behavior, as above.
+ return make_reg(0, 1);
break;
case 17:
// Seems to be some sort of audio sync, used in SQ6. Silenced the
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 310e38dbd1..1c08bf597c 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -661,19 +661,6 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv) {
#ifdef ENABLE_SCI32
-reg_t kText(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 0:
- return kTextSize(s, argc - 1, argv + 1);
- default:
- // TODO: Other subops here too, perhaps kTextColors and kTextFonts
- warning("kText(%d)", argv[0].toUint16());
- break;
- }
-
- return s->r_acc;
-}
-
// TODO: there is an unused second argument, happens at least in LSL6 right during the intro
reg_t kStringNew(EngineState *s, int argc, reg_t *argv) {
reg_t stringHandle;
@@ -778,11 +765,14 @@ reg_t kStringCopy(EngineState *s, int argc, reg_t *argv) {
}
// The original engine ignores bad copies too
- if (index2 > string2Size)
+ if (index2 >= string2Size)
return NULL_REG;
// A count of -1 means fill the rest of the array
- uint32 count = argv[4].toSint16() == -1 ? string2Size - index2 + 1 : argv[4].toUint16();
+ uint32 count = string2Size - index2;
+ if (argv[4].toSint16() != -1) {
+ count = MIN(count, (uint32)argv[4].toUint16());
+ }
// reg_t strAddress = argv[0];
SciString *string1 = s->_segMan->lookupString(argv[0]);
diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp
index 0626c084c1..0566d6955f 100644
--- a/engines/sci/engine/object.cpp
+++ b/engines/sci/engine/object.cpp
@@ -255,6 +255,8 @@ void Object::initSelectorsSci3(const byte *buf) {
if (g_sci->getKernel()->getSelectorNamesSize() % 32)
++groups;
+ _mustSetViewVisible.resize(groups);
+
methods = properties = 0;
// Selectors are divided into groups of 32, of which the first
@@ -270,7 +272,9 @@ void Object::initSelectorsSci3(const byte *buf) {
// This object actually has selectors belonging to this group
int typeMask = READ_SCI11ENDIAN_UINT32(seeker);
- for (int bit = 2; bit < 32; ++bit) {
+ _mustSetViewVisible[groupNr] = (typeMask & 1);
+
+ for (int bit = 2; bit < 32; ++bit) {
int value = READ_SCI11ENDIAN_UINT16(seeker + bit * 2);
if (typeMask & (1 << bit)) { // Property
++properties;
@@ -281,7 +285,8 @@ void Object::initSelectorsSci3(const byte *buf) {
}
}
- }
+ } else
+ _mustSetViewVisible[groupNr] = false;
}
_variables.resize(properties);
diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h
index 0ae7ed2cab..a7be170f4f 100644
--- a/engines/sci/engine/object.h
+++ b/engines/sci/engine/object.h
@@ -41,8 +41,21 @@ enum {
};
enum infoSelectorFlags {
- kInfoFlagClone = 0x0001,
- kInfoFlagClass = 0x8000
+ kInfoFlagClone = 0x0001,
+#ifdef ENABLE_SCI32
+ /**
+ * When set, indicates to game scripts that a screen
+ * item can be updated.
+ */
+ kInfoFlagViewVisible = 0x0008, // TODO: "dirty" ?
+
+ /**
+ * When set, the object has an associated screen item in
+ * the rendering tree.
+ */
+ kInfoFlagViewInserted = 0x0010,
+#endif
+ kInfoFlagClass = 0x8000
};
enum ObjectOffsets {
@@ -120,7 +133,24 @@ public:
_infoSelectorSci3 = info;
}
- // No setter for the -info- selector
+#ifdef ENABLE_SCI32
+ void setInfoSelectorFlag(infoSelectorFlags flag) {
+ if (getSciVersion() < SCI_VERSION_3) {
+ _variables[_offset + 2] |= flag;
+ } else {
+ _infoSelectorSci3 |= flag;
+ }
+ }
+
+ // NOTE: In real engine, -info- is treated as byte size
+ void clearInfoSelectorFlag(infoSelectorFlags flag) {
+ if (getSciVersion() < SCI_VERSION_3) {
+ _variables[_offset + 2] &= ~flag;
+ } else {
+ _infoSelectorSci3 &= ~flag;
+ }
+ }
+#endif
reg_t getNameSelector() const {
if (getSciVersion() < SCI_VERSION_3)
@@ -232,6 +262,8 @@ public:
bool initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass = true);
void syncBaseObject(const byte *ptr) { _baseObj = ptr; }
+ bool mustSetViewVisibleSci3(int selector) const { return _mustSetViewVisible[selector/32]; }
+
private:
void initSelectorsSci3(const byte *buf);
@@ -248,6 +280,7 @@ private:
reg_t _superClassPosSci3; /**< reg_t pointing to superclass for SCI3 */
reg_t _speciesSelectorSci3; /**< reg_t containing species "selector" for SCI3 */
reg_t _infoSelectorSci3; /**< reg_t containing info "selector" for SCI3 */
+ Common::Array<bool> _mustSetViewVisible; /** cached bit of info to make lookup fast, SCI3 only */
};
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 165c147c1c..fcb65157d8 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -39,6 +39,7 @@
#include "sci/engine/vm_types.h"
#include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS
#include "sci/graphics/helpers.h"
+#include "sci/graphics/menu.h"
#include "sci/graphics/palette.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/screen.h"
@@ -957,7 +958,8 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin
extern void showScummVMDialog(const Common::String &message);
void gamestate_delayedrestore(EngineState *s) {
- Common::String fileName = g_sci->getSavegameName(s->_delayedRestoreGameId);
+ int savegameId = s->_delayedRestoreGameId; // delayedRestoreGameId gets destroyed within gamestate_restore()!
+ Common::String fileName = g_sci->getSavegameName(savegameId);
Common::SeekableReadStream *in = g_sci->getSaveFileManager()->openForLoading(fileName);
if (in) {
@@ -965,6 +967,7 @@ void gamestate_delayedrestore(EngineState *s) {
gamestate_restore(s, in);
delete in;
if (s->r_acc != make_reg(0, 1)) {
+ gamestate_afterRestoreFixUp(s, savegameId);
return;
}
}
@@ -972,6 +975,73 @@ void gamestate_delayedrestore(EngineState *s) {
error("Restoring gamestate '%s' failed", fileName.c_str());
}
+void gamestate_afterRestoreFixUp(EngineState *s, int savegameId) {
+ switch (g_sci->getGameId()) {
+ case GID_MOTHERGOOSE:
+ // WORKAROUND: Mother Goose SCI0
+ // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the
+ // current number of children plus 1.
+ // We can't trust that global, that's why we set the actual savedgame id right here directly after
+ // restoring a saved game.
+ // If we didn't, the game would always save to a new slot
+ s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
+ break;
+ case GID_MOTHERGOOSE256:
+ // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for
+ // saving a previously restored game.
+ // We set the current savedgame-id directly and remove the script
+ // code concerning this via script patch.
+ s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
+ break;
+ case GID_JONES:
+ // HACK: The code that enables certain menu items isn't called when a game is restored from the
+ // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723.
+ // These menu entries are disabled when the game is launched, and are enabled when a new game is
+ // started. The code for enabling these entries is is all in script 1, room1::init, but that code
+ // path is never followed in these two cases (restoring game from the menu, or restoring a game
+ // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here.
+ // These two are needed when restoring from the launcher
+ // FIXME: The original interpreter saves and restores the menu state, so these attributes
+ // are automatically reset there. We may want to do the same.
+ g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones
+ g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help
+ // The rest are normally enabled from room1::init
+ g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player
+ g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
+ g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game
+ g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics
+ g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals
+ break;
+ case GID_KQ6:
+ if (g_sci->isCD()) {
+ // WORKAROUND:
+ // For the CD version of King's Quest 6, set global depending on current hires/lowres state
+ // The game sets a global at the start depending on it and some things check that global
+ // instead of checking platform like for example the game action menu.
+ // This never happened in the original interpreter, because the original DOS interpreter
+ // was only capable of lowres graphics and the original Windows 3.11 interpreter was only capable
+ // of hires graphics. Saved games were not compatible between those two.
+ // Which means saving during lowres mode, then going into hires mode and restoring that saved game,
+ // will result in some graphics being incorrect (lowres).
+ // That's why we are setting the global after restoring a saved game depending on hires/lowres state.
+ // The CD demo of KQ6 does the same and uses the exact same global.
+ if ((g_sci->getPlatform() == Common::kPlatformWindows) || (g_sci->forceHiresGraphics())) {
+ s->variables[VAR_GLOBAL][0xA9].setOffset(1);
+ } else {
+ s->variables[VAR_GLOBAL][0xA9].setOffset(0);
+ }
+ }
+ break;
+ case GID_PQ2:
+ // HACK: Same as above - enable the save game menu option when loading in PQ2 (bug #6875).
+ // It gets disabled in the game's death screen.
+ g_sci->_gfxMenu->kernelSetAttribute(2, 1, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
+ break;
+ default:
+ break;
+ }
+}
+
void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
SavegameMetadata meta;
@@ -1013,13 +1083,31 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
if (g_sci->_gfxPorts)
g_sci->_gfxPorts->reset();
// clear screen
- if (g_sci->_gfxScreen)
- g_sci->_gfxScreen->clearForRestoreGame();
+ if (getSciVersion() <= SCI_VERSION_1_1) {
+ // Only do clearing the screen for SCI16
+ // Both SCI16 + SCI32 did not clear the screen.
+ // We basically do it for SCI16, because of KQ6.
+ // When hires portraits are shown and the user restores during that time, the portraits
+ // wouldn't get fully removed. In original SCI, the user wasn't able to restore during that time,
+ // so this is basically a workaround, so that ScummVM features work properly.
+ // For SCI32, behavior was verified in DOSBox, that SCI32 does not clear and also not redraw the screen.
+ // It only redraws elements that have changed in comparison to the state before the restore.
+ // If we cleared the screen for SCI32, we would have issues because of this behavior.
+ if (g_sci->_gfxScreen)
+ g_sci->_gfxScreen->clearForRestoreGame();
+ }
#ifdef ENABLE_SCI32
- // Also clear any SCI32 planes/screen items currently showing so they
- // don't show up after the load.
- if (getSciVersion() >= SCI_VERSION_2)
- g_sci->_gfxFrameout->clear();
+ // Delete current planes/elements of actively loaded VM, only when our ScummVM dialogs are patched in
+ // We MUST NOT delete all planes/screen items. At least Space Quest 6 has a few in memory like for example
+ // the options plane, which are not re-added and are in memory all the time right from the start of the
+ // game. Sierra SCI32 did not clear planes, only scripts cleared the ones inside planes::elements.
+ if (getSciVersion() >= SCI_VERSION_2) {
+ if (!s->_delayedRestoreFromLauncher) {
+ // Only do it, when we are restoring regulary and not from launcher
+ // As it could result in option planes etc. on the screen (happens in gk1)
+ g_sci->_gfxFrameout->syncWithScripts(false);
+ }
+ }
#endif
s->reset(true);
@@ -1044,6 +1132,13 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
if (g_sci->_gfxPorts)
g_sci->_gfxPorts->saveLoadWithSerializer(ser);
+ // SCI32:
+ // Current planes/screen elements of freshly loaded VM are re-added by scripts in [gameID]::replay
+ // We don't have to do that in here.
+ // But we may have to do it ourselves in case we ever implement some soft-error handling in case
+ // a saved game can't be restored. That way we can restore the game screen.
+ // see _gfxFrameout->syncWithScripts()
+
Vocabulary *voc = g_sci->getVocabulary();
if (ser.getVersion() >= 30 && voc)
voc->saveLoadWithSerializer(ser);
@@ -1061,6 +1156,8 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
// signal restored game to game scripts
s->gameIsRestarting = GAMEISRESTARTING_RESTORE;
+
+ s->_delayedRestoreFromLauncher = false;
}
bool get_savegame_metadata(Common::SeekableReadStream *stream, SavegameMetadata *meta) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index bb555434c9..459e992e24 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -87,6 +87,9 @@ bool gamestate_save(EngineState *s, Common::WriteStream *save, const Common::Str
// does a delayed saved game restore, used by ScummVM game menu - see detection.cpp / SciEngine::loadGameState()
void gamestate_delayedrestore(EngineState *s);
+// does a few fixups right after restoring a saved game
+void gamestate_afterRestoreFixUp(EngineState *s, int savegameId);
+
/**
* Restores a game state from a directory.
* @param s An older state from the same game
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 6915e12a0e..8039c5f282 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -101,6 +101,8 @@ static const char *const selectorNameTable[] = {
"startText", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
"startAudio", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
"modNum", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support
+ "cycler", // Space Quest 4 / system selector
+ "setLoop", // Laura Bow 1 Colonel's Bequest
NULL
};
@@ -127,7 +129,9 @@ enum ScriptPatcherSelectors {
SELECTOR_timesShownID,
SELECTOR_startText,
SELECTOR_startAudio,
- SELECTOR_modNum
+ SELECTOR_modNum,
+ SELECTOR_cycler,
+ SELECTOR_setLoop
};
// ===========================================================================
@@ -404,6 +408,59 @@ static const SciScriptPatcherEntry fanmadeSignatures[] = {
};
// ===========================================================================
+
+// WORKAROUND
+// Freddy Pharkas intro screen
+// Sierra used inner loops for the scaling of the 2 title views.
+// Those inner loops don't call kGameIsRestarting, which is why
+// we do not update the screen and we also do not throttle.
+//
+// This patch fixes this and makes it work.
+// Applies to at least: English PC-CD
+// Responsible method: sTownScript::changeState(1), sTownScript::changeState(3) (script 110)
+static const uint16 freddypharkasSignatureIntroScaling[] = {
+ 0x38, SIG_ADDTOOFFSET(+2), // pushi (setLoop) (009b for PC CD)
+ 0x78, // push1
+ PATCH_ADDTOOFFSET(1), // push0 for first code, push1 for second code
+ 0x38, SIG_ADDTOOFFSET(+2), // pushi (setStep) (0143 for PC CD)
+ 0x7a, // push2
+ 0x39, 0x05, // pushi 05
+ 0x3c, // dup
+ 0x72, SIG_ADDTOOFFSET(+2), // lofsa (view)
+ SIG_MAGICDWORD,
+ 0x4a, 0x1e, // send 1e
+ 0x35, 0x0a, // ldi 0a
+ 0xa3, 0x02, // sal local[2]
+ // start of inner loop
+ 0x8b, 0x02, // lsl local[2]
+ SIG_ADDTOOFFSET(+43), // skip almost all of inner loop
+ 0xa3, 0x02, // sal local[2]
+ 0x33, 0xcf, // jmp [inner loop start]
+ SIG_END
+};
+
+static const uint16 freddypharkasPatchIntroScaling[] = {
+ // remove setLoop(), objects in heap are already prepared, saves 5 bytes
+ 0x38,
+ PATCH_GETORIGINALBYTE(+6),
+ PATCH_GETORIGINALBYTE(+7), // pushi (setStep)
+ 0x7a, // push2
+ 0x39, 0x05, // pushi 05
+ 0x3c, // dup
+ 0x72,
+ PATCH_GETORIGINALBYTE(+13),
+ PATCH_GETORIGINALBYTE(+14), // lofsa (view)
+ 0x4a, 0x18, // send 18 - adjusted
+ 0x35, 0x0a, // ldi 0a
+ 0xa3, 0x02, // sal local[2]
+ // start of new inner loop
+ 0x39, 0x00, // pushi 00
+ 0x43, 0x2c, 0x00, // callk GameIsRestarting <-- add this so that our speed throttler is triggered
+ SIG_ADDTOOFFSET(+47), // skip almost all of inner loop
+ 0x33, 0xca, // jmp [inner loop start]
+ PATCH_END
+};
+
// script 0 of freddy pharkas/CD PointsSound::check waits for a signal and if
// no signal received will call kDoSound(0xD) which is a dummy in sierra sci
// and ScummVM and will use acc (which is not set by the dummy) to trigger
@@ -522,6 +579,7 @@ static const uint16 freddypharkasPatchMacInventory[] = {
static const SciScriptPatcherEntry freddypharkasSignatures[] = {
{ true, 0, "CD: score early disposal", 1, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
{ true, 15, "Mac: broken inventory", 1, freddypharkasSignatureMacInventory, freddypharkasPatchMacInventory },
+ { true, 110, "intro scaling workaround", 2, freddypharkasSignatureIntroScaling, freddypharkasPatchIntroScaling },
{ true, 235, "CD: canister pickup hang", 3, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
{ true, 320, "ladder event issue", 2, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent },
SCI_SIGNATUREENTRY_TERMINATOR
@@ -755,6 +813,32 @@ static const uint16 kq5PatchWitchCageInit[] = {
PATCH_END
};
+// The multilingual releases of KQ5 hang right at the end during the magic battle with Mordack.
+// It seems additional code was added to wait for signals, but the signals are never set and thus
+// the game hangs. We disable that code, so that the battle works again.
+// This also happened in the original interpreter.
+// We must not change similar code, that happens before.
+
+// Applies to at least: French PC floppy, German PC floppy, Spanish PC floppy
+// Responsible method: stingScript::changeState, dragonScript::changeState, snakeScript::changeState
+static const uint16 kq5SignatureMultilingualEndingGlitch[] = {
+ SIG_MAGICDWORD,
+ 0x89, 0x57, // lsg global[57h]
+ 0x35, 0x00, // ldi 0
+ 0x1a, // eq?
+ 0x18, // not
+ 0x30, SIG_UINT16(0x0011), // bnt [skip signal check]
+ SIG_ADDTOOFFSET(+8), // skip globalSound::prevSignal get code
+ 0x36, // push
+ 0x35, 0x0a, // ldi 0Ah
+ SIG_END
+};
+
+static const uint16 kq5PatchMultilingualEndingGlitch[] = {
+ PATCH_ADDTOOFFSET(+6),
+ 0x32, // change BNT into JMP
+ PATCH_END
+};
// In the final battle, the DOS version uses signals in the music to handle
// timing, while in the Windows version another method is used and the GM
@@ -785,9 +869,10 @@ static const uint16 kq5PatchWinGMSignals[] = {
// script, description, signature patch
static const SciScriptPatcherEntry kq5Signatures[] = {
- { true, 0, "CD: harpy volume change", 1, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
- { true, 200, "CD: witch cage init", 1, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
- { false, 124, "Win: GM Music signal checks", 4, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
+ { true, 0, "CD: harpy volume change", 1, kq5SignatureCdHarpyVolume, kq5PatchCdHarpyVolume },
+ { true, 200, "CD: witch cage init", 1, kq5SignatureWitchCageInit, kq5PatchWitchCageInit },
+ { true, 124, "Multilingual: Ending glitching out", 3, kq5SignatureMultilingualEndingGlitch, kq5PatchMultilingualEndingGlitch },
+ { false, 124, "Win: GM Music signal checks", 4, kq5SignatureWinGMSignals, kq5PatchWinGMSignals },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -1201,8 +1286,10 @@ static const uint16 kq6CDPatchAudioTextSupportJumpAlways[] = {
};
// Fixes "Girl In The Tower" to get played in dual mode as well
+// Also changes credits to use CD audio for dual mode.
+//
// Applies to at least: PC-CD
-// Patched method: rm740::cue
+// Patched method: rm740::cue (script 740), sCredits::init (script 52)
static const uint16 kq6CDSignatureAudioTextSupportGirlInTheTower[] = {
SIG_MAGICDWORD,
0x89, 0x5a, // lsg global[5a]
@@ -1329,6 +1416,7 @@ static const SciScriptPatcherEntry kq6Signatures[] = {
{ false, 928, "CD: audio + text support KQ6 4", 1, kq6CDSignatureAudioTextSupport4, kq6CDPatchAudioTextSupport4 },
{ false, 1009, "CD: audio + text support KQ6 Guards", 2, kq6CDSignatureAudioTextSupportGuards, kq6CDPatchAudioTextSupportGuards },
{ false, 1027, "CD: audio + text support KQ6 Stepmother", 1, kq6CDSignatureAudioTextSupportStepmother, kq6CDPatchAudioTextSupportJumpAlways },
+ { false, 52, "CD: audio + text support KQ6 Girl In The Tower", 1, kq6CDSignatureAudioTextSupportGirlInTheTower, kq6CDPatchAudioTextSupportGirlInTheTower },
{ false, 740, "CD: audio + text support KQ6 Girl In The Tower", 1, kq6CDSignatureAudioTextSupportGirlInTheTower, kq6CDPatchAudioTextSupportGirlInTheTower },
{ false, 370, "CD: audio + text support KQ6 Azure & Ariel", 6, kq6CDSignatureAudioTextSupportAzureAriel, kq6CDPatchAudioTextSupportAzureAriel },
{ false, 903, "CD: audio + text support KQ6 menu", 1, kq6CDSignatureAudioTextMenuSupport, kq6CDPatchAudioTextMenuSupport },
@@ -1536,6 +1624,43 @@ static const SciScriptPatcherEntry larry6Signatures[] = {
};
// ===========================================================================
+// Laura Bow 1 - Colonel's Bequest
+//
+// This is basically just a broken easter egg in Colonel's Bequest.
+// A plane can show up in room 4, but that only happens really rarely.
+// Anyway the Sierra developer seems to have just entered the wrong loop,
+// which is why the statue view is used instead (loop 0).
+// We fix it to use the correct loop.
+//
+// This is only broken in the PC version. It was fixed for Amiga + Atari ST.
+//
+// Credits to OmerMor, for finding it.
+
+// Applies to at least: English PC Floppy
+// Responsible method: room4::init
+static const uint16 laurabow1SignatureEasterEggViewFix[] = {
+ 0x78, // push1
+ 0x76, // push0
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16(setLoop), // pushi "setLoop"
+ 0x78, // push1
+ 0x39, 0x03, // pushi 3 (loop 3, view only has 3 loops)
+ SIG_END
+};
+
+static const uint16 laurabow1PatchEasterEggViewFix[] = {
+ PATCH_ADDTOOFFSET(+7),
+ 0x02, // change loop to 2
+ PATCH_END
+};
+
+// script, description, signature patch
+static const SciScriptPatcherEntry laurabow1Signatures[] = {
+ { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
// Laura Bow 2
//
// Moving away the painting in the room with the hidden safe is problematic
@@ -1840,15 +1965,103 @@ static const SciScriptPatcherEntry laurabow2Signatures[] = {
// MG::replay somewhat calculates the savedgame-id used when saving again
// this doesn't work right and we remove the code completely.
// We set the savedgame-id directly right after restoring in kRestoreGame.
+// We also draw the background picture in here instead.
+// This Mixed Up Mother Goose draws the background picture before restoring,
+// instead of doing it properly in MG::replay. This fixes graphic issues,
+// when restoring from GMM.
+//
+// Applies to at least: English SCI1 CD, English SCI1.1 floppy, Japanese FM-Towns
+// Responsible method: MG::replay (script 0)
static const uint16 mothergoose256SignatureReplay[] = {
+ 0x7a, // push2
+ 0x78, // push1
+ 0x5b, 0x00, 0xbe, // lea global[BEh]
+ 0x36, // push
+ 0x43, 0x70, 0x04, // callk MemorySegment
+ 0x7a, // push2
+ 0x5b, 0x00, 0xbe, // lea global[BEh]
+ 0x36, // push
+ 0x76, // push0
+ 0x43, 0x62, 0x04, // callk StrAt
+ 0xa1, 0xaa, // sag global[AAh]
+ 0x7a, // push2
+ 0x5b, 0x00, 0xbe, // lea global[BEh]
+ 0x36, // push
+ 0x78, // push1
+ 0x43, 0x62, 0x04, // callk StrAt
+ 0x36, // push
+ 0x35, 0x20, // ldi 20
+ 0x04, // sub
+ 0xa1, SIG_ADDTOOFFSET(+1), // sag global[57h] -> FM-Towns [9Dh]
+ // 35 bytes
+ 0x39, 0x03, // pushi 03
+ 0x89, SIG_ADDTOOFFSET(+1), // lsg global[1Dh] -> FM-Towns [1Eh]
+ 0x76, // push0
+ 0x7a, // push2
+ 0x5b, 0x00, 0xbe, // lea global[BEh]
+ 0x36, // push
+ 0x7a, // push2
+ 0x43, 0x62, 0x04, // callk StrAt
+ 0x36, // push
+ 0x35, 0x01, // ldi 01
+ 0x04, // sub
+ 0x36, // push
+ 0x43, 0x62, 0x06, // callk StrAt
+ // 22 bytes
+ 0x7a, // push2
+ 0x5b, 0x00, 0xbe, // lea global[BE]
+ 0x36, // push
+ 0x39, 0x03, // pushi 03
+ 0x43, 0x62, 0x04, // callk StrAt
+ // 10 bytes
0x36, // push
0x35, SIG_MAGICDWORD, 0x20, // ldi 20
0x04, // sub
0xa1, 0xb3, // sag global[b3]
+ // 6 bytes
SIG_END
};
static const uint16 mothergoose256PatchReplay[] = {
+ 0x39, 0x06, // pushi 06
+ 0x76, // push0
+ 0x76, // push0
+ 0x38, PATCH_UINT16(200), // pushi 200d
+ 0x38, PATCH_UINT16(320), // pushi 320d
+ 0x76, // push0
+ 0x76, // push0
+ 0x43, 0x15, 0x0c, // callk SetPort -> set picture port to full screen
+ // 15 bytes
+ 0x39, 0x04, // pushi 04
+ 0x3c, // dup
+ 0x76, // push0
+ 0x38, PATCH_UINT16(255), // pushi 255d
+ 0x76, // push0
+ 0x43, 0x6f, 0x08, // callk Palette -> set intensity to 0 for all colors
+ // 11 bytes
+ 0x7a, // push2
+ 0x38, PATCH_UINT16(800), // pushi 800
+ 0x76, // push0
+ 0x43, 0x08, 0x04, // callk DrawPic -> draw picture 800
+ // 8 bytes
+ 0x39, 0x06, // pushi 06
+ 0x39, 0x0c, // pushi 0Ch
+ 0x76, // push0
+ 0x76, // push0
+ 0x38, PATCH_UINT16(200), // push 200
+ 0x38, PATCH_UINT16(320), // push 320
+ 0x78, // push1
+ 0x43, 0x6c, 0x0c, // callk Graph -> send everything to screen
+ // 16 bytes
+ 0x39, 0x06, // pushi 06
+ 0x76, // push0
+ 0x76, // push0
+ 0x38, PATCH_UINT16(156), // pushi 156d
+ 0x38, PATCH_UINT16(258), // pushi 258d
+ 0x39, 0x03, // pushi 03
+ 0x39, 0x04, // pushi 04
+ 0x43, 0x15, 0x0c, // callk SetPort -> set picture port back
+ // 17 bytes
0x34, PATCH_UINT16(0x0000), // ldi 0000 (dummy)
0x34, PATCH_UINT16(0x0000), // ldi 0000 (dummy)
PATCH_END
@@ -1856,6 +2069,9 @@ static const uint16 mothergoose256PatchReplay[] = {
// when saving, it also checks if the savegame ID is below 13.
// we change this to check if below 113 instead
+//
+// Applies to at least: English SCI1 CD, English SCI1.1 floppy, Japanese FM-Towns
+// Responsible method: Game::save (script 994 for SCI1), MG::save (script 0 for SCI1.1)
static const uint16 mothergoose256SignatureSaveLimit[] = {
0x89, SIG_MAGICDWORD, 0xb3, // lsg global[b3]
0x35, 0x0d, // ldi 0d
@@ -1879,6 +2095,50 @@ static const SciScriptPatcherEntry mothergoose256Signatures[] = {
// ===========================================================================
// Police Quest 1 VGA
+
+// When briefing is about to start in room 15, other officers will get into the room too.
+// When one of those officers gets into the way of ego, they will tell the player to sit down.
+// But control will be disabled right at that point. Ego may then go to his seat by himself,
+// or more often than not will just stand there. The player is unable to do anything.
+//
+// Sergeant Dooley will then enter the room. Tell the player to sit down 3 times and after
+// that it's game over.
+//
+// Because the Sergeant is telling the player to sit down, one has to assume that the player
+// is meant to still be in control. Which is why this script patch removes disabling of player control.
+//
+// The script also tries to make ego walk to the chair, but it fails because it gets stuck with other
+// actors. So I guess the safest way is to remove all of that and let the player do it manually.
+//
+// The responsible method seems to use a few hardcoded texts, which is why I have to assume that it's
+// not used anywhere else. I also checked all scripts and couldn't find any other calls to it.
+//
+// This of course also happens when using the original interpreter.
+//
+// Scripts work like this: manX::doit (script 134) triggers gab::changeState, which then triggers rm015::notify
+//
+// Applies to at least: English floppy
+// Responsible method: gab::changeState (script 152)
+// Fixes bug: #5865
+static const uint16 pq1vgaSignatureBriefingGettingStuck[] = {
+ 0x76, // push0
+ 0x45, 0x02, 0x00, // call export 2 of script 0 (disable control)
+ 0x38, SIG_ADDTOOFFSET(+2), // pushi notify
+ 0x76, // push0
+ 0x81, 0x02, // lag global[2] (get current room)
+ 0x4a, 0x04, // send 04
+ SIG_MAGICDWORD,
+ 0x8b, 0x02, // lsl local[2]
+ 0x35, 0x01, // ldi 01
+ 0x02, // add
+ SIG_END
+};
+
+static const uint16 pq1vgaPatchBriefingGettingStuck[] = {
+ 0x33, 0x0a, // jmp to lsl local[2], skip over export 2 and ::notify
+ PATCH_END // rm015::notify would try to make ego walk to the chair
+};
+
// When at the police station, you can put or get your gun from your locker.
// The script, that handles this, is buggy. It disposes the gun as soon as
// you click, but then waits 2 seconds before it also closes the locker.
@@ -1966,10 +2226,11 @@ static const uint16 pq1vgaPatchMapSaveRestoreBug[] = {
PATCH_END
};
-// script, description, signature patch
+// script, description, signature patch
static const SciScriptPatcherEntry pq1vgaSignatures[] = {
- { true, 341, "put gun in locker bug", 1, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
- { true, 500, "map save/restore bug", 2, pq1vgaSignatureMapSaveRestoreBug, pq1vgaPatchMapSaveRestoreBug },
+ { true, 152, "getting stuck while briefing is about to start", 1, pq1vgaSignatureBriefingGettingStuck, pq1vgaPatchBriefingGettingStuck },
+ { true, 341, "put gun in locker bug", 1, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
+ { true, 500, "map save/restore bug", 2, pq1vgaSignatureMapSaveRestoreBug, pq1vgaPatchMapSaveRestoreBug },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -2673,14 +2934,75 @@ static const uint16 qfg3PatchChiefPriority[] = {
PATCH_END
};
+// Partly WORKAROUND:
+// During combat, the game is not properly throttled. That's because the game uses
+// an inner loop for combat and does not iterate through the main loop.
+// It also doesn't call kGameIsRestarting. This may get fixed properly at some point
+// by rewriting the speed throttler.
+//
+// Additionally Sierra set the cycle speed of the hero to 0. Which explains
+// why the actions of the hero are so incredibly fast. This issue also happened
+// in the original interpreter, when the computer was too powerful.
+//
+// Applies to at least: English, French, German, Italian, Spanish PC floppy
+// Responsible method: combatControls::dispatchEvent (script 550) + WarriorObj in heap
+// Fixes bug #6247
+static const uint16 qfg3SignatureCombatSpeedThrottling1[] = {
+ 0x31, 0x0d, // bnt [skip code]
+ SIG_MAGICDWORD,
+ 0x89, 0xd2, // lsg global[D2h]
+ 0x35, 0x00, // ldi 0
+ 0x1e, // gt?
+ 0x31, 0x06, // bnt [skip code]
+ 0xe1, 0xd2, // -ag global[D2h] (jump skips over this)
+ 0x81, 0x58, // lag global[58h]
+ 0xa3, 0x01, // sal local[01]
+ SIG_END
+};
+
+static const uint16 qfg3PatchCombatSpeedThrottling1[] = {
+ 0x80, 0xd2, // lsg global[D2h]
+ 0x14, // or
+ 0x31, 0x06, // bnt [skip code] - saves 4 bytes
+ 0xe1, 0xd2, // -ag global[D2h]
+ 0x81, 0x58, // lag global[58h]
+ 0xa3, 0x01, // sal local[01] (jump skips over this)
+ // our code
+ 0x76, // push0
+ 0x43, 0x2c, 0x00, // callk GameIsRestarting <-- add this so that our speed throttler is triggered
+ PATCH_END
+};
+
+static const uint16 qfg3SignatureCombatSpeedThrottling2[] = {
+ SIG_MAGICDWORD,
+ SIG_UINT16(12), // priority 12
+ SIG_UINT16(0), // underbits 0
+ SIG_UINT16(0x4010), // signal 4010h
+ SIG_ADDTOOFFSET(+18),
+ SIG_UINT16(0), // scaleSignal 0
+ SIG_UINT16(128), // scaleX
+ SIG_UINT16(128), // scaleY
+ SIG_UINT16(128), // maxScale
+ SIG_UINT16(0), // cycleSpeed
+ SIG_END
+};
+
+static const uint16 qfg3PatchCombatSpeedThrottling2[] = {
+ PATCH_ADDTOOFFSET(+32),
+ PATCH_UINT16(5), // set cycleSpeed to 5
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry qfg3Signatures[] = {
- { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
- { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog },
- { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt },
- { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar },
- { true, 54, "import character from QfG1 bug", 1, qfg3SignatureImportQfG1Char, qfg3PatchImportQfG1Char },
- { true, 640, "chief in hut priority fix", 1, qfg3SignatureChiefPriority, qfg3PatchChiefPriority },
+ { true, 944, "import dialog continuous calls", 1, qfg3SignatureImportDialog, qfg3PatchImportDialog },
+ { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialog, qfg3PatchWooDialog },
+ { true, 440, "dialog crash when asking about Woo", 1, qfg3SignatureWooDialogAlt, qfg3PatchWooDialogAlt },
+ { true, 52, "export character save bug", 2, qfg3SignatureExportChar, qfg3PatchExportChar },
+ { true, 54, "import character from QfG1 bug", 1, qfg3SignatureImportQfG1Char, qfg3PatchImportQfG1Char },
+ { true, 640, "chief in hut priority fix", 1, qfg3SignatureChiefPriority, qfg3PatchChiefPriority },
+ { true, 550, "combat speed throttling script", 1, qfg3SignatureCombatSpeedThrottling1, qfg3PatchCombatSpeedThrottling1 },
+ { true, 550, "combat speed throttling heap", 1, qfg3SignatureCombatSpeedThrottling2, qfg3PatchCombatSpeedThrottling2 },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -2836,6 +3158,66 @@ static const uint16 sq4CdPatchGetPointsForChangingBackClothes[] = {
PATCH_END
};
+
+// For Space Quest 4 CD, Sierra added a pick up animation for Roger, when he picks up the rope.
+//
+// When the player is detected by the zombie right at the start of the game, while picking up the rope,
+// scripts bomb out. This also happens, when using the original interpreter.
+//
+// This is caused by code, that's supposed to make Roger face the arriving drone.
+// We fix it, by checking if ego::cycler is actually set before calling that code.
+//
+// Applies to at least: English PC CD
+// Responsible method: droidShoots::changeState(3)
+// Fixes bug: #6076
+static const uint16 sq4CdSignatureGettingShotWhileGettingRope[] = {
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1a, // aTop cycles
+ 0x32, SIG_UINT16(0x02fa), // jmp [end]
+ SIG_MAGICDWORD,
+ 0x3c, // dup
+ 0x35, 0x02, // ldi 02
+ 0x1a, // eq?
+ 0x31, 0x0b, // bnt [state 3 check]
+ 0x76, // push0
+ 0x45, 0x02, 0x00, // call export 2 of script 0 -> disable controls
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1a, // aTop cycles
+ 0x32, SIG_UINT16(0x02e9), // jmp [end]
+ 0x3c, // dup
+ 0x35, 0x03, // ldi 03
+ 0x1a, // eq?
+ 0x31, 0x1e, // bnt [state 4 check]
+ 0x76, // push0
+ 0x45, 0x02, 0x00, // call export 2 of script 0 -> disable controls again??
+ 0x7a, // push2
+ 0x89, 0x00, // lsg global[0]
+ 0x72, SIG_UINT16(0x0242), // lofsa deathDroid
+ 0x36, // push
+ 0x45, 0x0d, 0x04, // call export 13 of script 0 -> set heading of ego to face droid
+ SIG_END
+};
+
+static const uint16 sq4CdPatchGettingShotWhileGettingRope[] = {
+ PATCH_ADDTOOFFSET(+11),
+ // this makes state 2 only do the 2 cycles wait, controls should always be disabled already at this point
+ 0x2f, 0xf3, // bt [previous state aTop cycles code]
+ // Now we check for state 3, this change saves us 11 bytes
+ 0x3c, // dup
+ 0x35, 0x03, // ldi 03
+ 0x1a, // eq?
+ 0x31, 0x29, // bnt [state 4 check]
+ // new state 3 code
+ 0x76, // push0
+ 0x45, 0x02, 0x00, // call export 2 of script 0 (disable controls, actually not needed)
+ 0x38, PATCH_SELECTOR16(cycler), // pushi cycler
+ 0x76, // push0
+ 0x81, 0x00, // lag global[0]
+ 0x4a, 0x04, // send 04 (get ego::cycler)
+ 0x30, PATCH_UINT16(10), // bnt [jump over heading call]
+ PATCH_END
+};
+
// The scripts in SQ4CD support simultaneous playing of speech and subtitles,
// but this was not available as an option. The following two patches enable
// this functionality in the game's GUI options dialog.
@@ -2932,6 +3314,7 @@ static const SciScriptPatcherEntry sq4Signatures[] = {
{ true, 700, "Floppy: throw stuff at sequel police bug", 1, sq4FloppySignatureThrowStuffAtSequelPoliceBug, sq4FloppyPatchThrowStuffAtSequelPoliceBug },
{ true, 45, "CD: walk in from below for room 45 fix", 1, sq4CdSignatureWalkInFromBelowRoom45, sq4CdPatchWalkInFromBelowRoom45 },
{ true, 396, "CD: get points for changing back clothes fix",1, sq4CdSignatureGetPointsForChangingBackClothes, sq4CdPatchGetPointsForChangingBackClothes },
+ { true, 701, "CD: getting shot, while getting rope", 1, sq4CdSignatureGettingShotWhileGettingRope, sq4CdPatchGettingShotWhileGettingRope },
{ true, 0, "CD: Babble icon speech and subtitles fix", 1, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon },
{ true, 818, "CD: Speech and subtitles option", 1, sq4CdSignatureTextOptions, sq4CdPatchTextOptions },
{ true, 818, "CD: Speech and subtitles option button", 1, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton },
@@ -3374,20 +3757,20 @@ bool ScriptPatcher::verifySignature(uint32 byteOffset, const uint16 *signatureDa
}
// will return -1 if no match was found, otherwise an offset to the start of the signature match
-int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize) {
+int32 ScriptPatcher::findSignature(uint32 magicDWord, int magicOffset, const uint16 *signatureData, const char *patchDescription, const byte *scriptData, const uint32 scriptSize) {
if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay
return -1;
- const uint32 magicDWord = runtimeEntry->magicDWord; // is platform-specific BE/LE form, so that the later match will work
+ // magicDWord is in platform-specific BE/LE form, so that the later match will work, this was done for performance
const uint32 searchLimit = scriptSize - 3;
uint32 DWordOffset = 0;
// first search for the magic DWORD
while (DWordOffset < searchLimit) {
if (magicDWord == READ_UINT32(scriptData + DWordOffset)) {
// magic DWORD found, check if actual signature matches
- uint32 offset = DWordOffset + runtimeEntry->magicOffset;
+ uint32 offset = DWordOffset + magicOffset;
- if (verifySignature(offset, patchEntry->signatureData, patchEntry->description, scriptData, scriptSize))
+ if (verifySignature(offset, signatureData, patchDescription, scriptData, scriptSize))
return offset;
}
DWordOffset++;
@@ -3396,22 +3779,146 @@ int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, SciS
return -1;
}
-// This method calculates the magic DWORD for each entry in the signature table
-// and it also initializes the selector table for selectors used in the signatures/patches of the current game
-void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) {
- const SciScriptPatcherEntry *curEntry = patchTable;
- SciScriptPatcherRuntimeEntry *curRuntimeEntry;
+int32 ScriptPatcher::findSignature(const SciScriptPatcherEntry *patchEntry, const SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize) {
+ return findSignature(runtimeEntry->magicDWord, runtimeEntry->magicOffset, patchEntry->signatureData, patchEntry->description, scriptData, scriptSize);
+}
+
+// Attention: Magic DWord is returns using platform specific byte order. This is done on purpose for performance.
+void ScriptPatcher::calculateMagicDWordAndVerify(const char *signatureDescription, const uint16 *signatureData, bool magicDWordIncluded, uint32 &calculatedMagicDWord, int &calculatedMagicDWordOffset) {
Selector curSelector = -1;
- int step;
int magicOffset;
byte magicDWord[4];
int magicDWordLeft = 0;
- const uint16 *curData;
uint16 curWord;
uint16 curCommand;
uint32 curValue;
byte byte1 = 0;
byte byte2 = 0;
+
+ memset(magicDWord, 0, sizeof(magicDWord));
+
+ curWord = *signatureData;
+ magicOffset = 0;
+ while (curWord != SIG_END) {
+ curCommand = curWord & SIG_COMMANDMASK;
+ curValue = curWord & SIG_VALUEMASK;
+ switch (curCommand) {
+ case SIG_MAGICDWORD: {
+ if (magicDWordIncluded) {
+ if ((calculatedMagicDWord) || (magicDWordLeft))
+ error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", signatureDescription);
+ magicDWordLeft = 4;
+ calculatedMagicDWordOffset = magicOffset;
+ } else {
+ error("Script-Patcher: Magic-DWORD sequence found in patch data\nFaulty patch: '%s'", signatureDescription);
+ }
+ break;
+ }
+ case SIG_CODE_ADDTOOFFSET: {
+ magicOffset -= curValue;
+ if (magicDWordLeft)
+ error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", signatureDescription);
+ break;
+ }
+ case SIG_CODE_UINT16:
+ case SIG_CODE_SELECTOR16: {
+ // UINT16 or 1
+ switch (curCommand) {
+ case SIG_CODE_UINT16: {
+ signatureData++; curWord = *signatureData;
+ if (curWord & SIG_COMMANDMASK)
+ error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", signatureDescription);
+ if (!_isMacSci11) {
+ byte1 = curValue;
+ byte2 = curWord & SIG_BYTEMASK;
+ } else {
+ byte1 = curWord & SIG_BYTEMASK;
+ byte2 = curValue;
+ }
+ break;
+ }
+ case SIG_CODE_SELECTOR16: {
+ curSelector = _selectorIdTable[curValue];
+ if (curSelector == -1) {
+ curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]);
+ _selectorIdTable[curValue] = curSelector;
+ }
+ if (!_isMacSci11) {
+ byte1 = curSelector & 0x00FF;
+ byte2 = curSelector >> 8;
+ } else {
+ byte1 = curSelector >> 8;
+ byte2 = curSelector & 0x00FF;
+ }
+ break;
+ }
+ }
+ magicOffset -= 2;
+ if (magicDWordLeft) {
+ // Remember current word for Magic DWORD
+ magicDWord[4 - magicDWordLeft] = byte1;
+ magicDWordLeft--;
+ if (magicDWordLeft) {
+ magicDWord[4 - magicDWordLeft] = byte2;
+ magicDWordLeft--;
+ }
+ if (!magicDWordLeft) {
+ // Magic DWORD is now known, convert to platform specific byte order
+ calculatedMagicDWord = READ_LE_UINT32(magicDWord);
+ }
+ }
+ break;
+ }
+ case SIG_CODE_BYTE:
+ case SIG_CODE_SELECTOR8: {
+ if (curCommand == SIG_CODE_SELECTOR8) {
+ curSelector = _selectorIdTable[curValue];
+ if (curSelector == -1) {
+ curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]);
+ _selectorIdTable[curValue] = curSelector;
+ if (curSelector != -1) {
+ if (curSelector & 0xFF00)
+ error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", signatureDescription);
+ }
+ }
+ curValue = curSelector;
+ }
+ magicOffset--;
+ if (magicDWordLeft) {
+ // Remember current byte for Magic DWORD
+ magicDWord[4 - magicDWordLeft] = (byte)curValue;
+ magicDWordLeft--;
+ if (!magicDWordLeft) {
+ calculatedMagicDWord = READ_LE_UINT32(magicDWord);
+ }
+ }
+ break;
+ }
+ case PATCH_CODE_GETORIGINALBYTEADJUST: {
+ signatureData++; // skip over extra uint16
+ break;
+ }
+ default:
+ break;
+ }
+ signatureData++;
+ curWord = *signatureData;
+ }
+
+ if (magicDWordLeft)
+ error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", signatureDescription);
+ if (magicDWordIncluded) {
+ if (!calculatedMagicDWord) {
+ error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", signatureDescription);
+ }
+ }
+}
+
+// This method calculates the magic DWORD for each entry in the signature table
+// and it also initializes the selector table for selectors used in the signatures/patches of the current game
+void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) {
+ const SciScriptPatcherEntry *curEntry = patchTable;
+ SciScriptPatcherRuntimeEntry *curRuntimeEntry;
int patchEntryCount = 0;
// Count entries and allocate runtime data
@@ -3425,120 +3932,14 @@ void ScriptPatcher::initSignature(const SciScriptPatcherEntry *patchTable) {
curRuntimeEntry = _runtimeTable;
while (curEntry->signatureData) {
// process signature
- memset(magicDWord, 0, sizeof(magicDWord));
-
curRuntimeEntry->active = curEntry->defaultActive;
curRuntimeEntry->magicDWord = 0;
curRuntimeEntry->magicOffset = 0;
- for (step = 0; step < 2; step++) {
- switch (step) {
- case 0: curData = curEntry->signatureData; break;
- case 1: curData = curEntry->patchData; break;
- }
-
- curWord = *curData;
- magicOffset = 0;
- while (curWord != SIG_END) {
- curCommand = curWord & SIG_COMMANDMASK;
- curValue = curWord & SIG_VALUEMASK;
- switch (curCommand) {
- case SIG_MAGICDWORD: {
- if (step == 0) {
- if ((curRuntimeEntry->magicDWord) || (magicDWordLeft))
- error("Script-Patcher: Magic-DWORD specified multiple times in signature\nFaulty patch: '%s'", curEntry->description);
- magicDWordLeft = 4;
- curRuntimeEntry->magicOffset = magicOffset;
- }
- break;
- }
- case SIG_CODE_ADDTOOFFSET: {
- magicOffset -= curValue;
- if (magicDWordLeft)
- error("Script-Patcher: Magic-DWORD contains AddToOffset command\nFaulty patch: '%s'", curEntry->description);
- break;
- }
- case SIG_CODE_UINT16:
- case SIG_CODE_SELECTOR16: {
- // UINT16 or 1
- switch (curCommand) {
- case SIG_CODE_UINT16: {
- curData++; curWord = *curData;
- if (curWord & SIG_COMMANDMASK)
- error("Script-Patcher: signature entry inconsistent\nFaulty patch: '%s'", curEntry->description);
- if (!_isMacSci11) {
- byte1 = curValue;
- byte2 = curWord & SIG_BYTEMASK;
- } else {
- byte1 = curWord & SIG_BYTEMASK;
- byte2 = curValue;
- }
- break;
- }
- case SIG_CODE_SELECTOR16: {
- curSelector = _selectorIdTable[curValue];
- if (curSelector == -1) {
- curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]);
- _selectorIdTable[curValue] = curSelector;
- }
- if (!_isMacSci11) {
- byte1 = curSelector & 0x00FF;
- byte2 = curSelector >> 8;
- } else {
- byte1 = curSelector >> 8;
- byte2 = curSelector & 0x00FF;
- }
- break;
- }
- }
- magicOffset -= 2;
- if (magicDWordLeft) {
- // Remember current word for Magic DWORD
- magicDWord[4 - magicDWordLeft] = byte1;
- magicDWordLeft--;
- if (magicDWordLeft) {
- magicDWord[4 - magicDWordLeft] = byte2;
- magicDWordLeft--;
- }
- if (!magicDWordLeft) {
- curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord);
- }
- }
- break;
- }
- case SIG_CODE_BYTE:
- case SIG_CODE_SELECTOR8: {
- if (curCommand == SIG_CODE_SELECTOR8) {
- curSelector = _selectorIdTable[curValue];
- if (curSelector == -1) {
- curSelector = g_sci->getKernel()->findSelector(selectorNameTable[curValue]);
- _selectorIdTable[curValue] = curSelector;
- if (curSelector != -1) {
- if (curSelector & 0xFF00)
- error("Script-Patcher: 8 bit selector required, game uses 16 bit selector\nFaulty patch: '%s'", curEntry->description);
- }
- }
- curValue = curSelector;
- }
- magicOffset--;
- if (magicDWordLeft) {
- // Remember current byte for Magic DWORD
- magicDWord[4 - magicDWordLeft] = (byte)curValue;
- magicDWordLeft--;
- if (!magicDWordLeft) {
- curRuntimeEntry->magicDWord = READ_LE_UINT32(magicDWord);
- }
- }
- }
- }
- curData++;
- curWord = *curData;
- }
- }
- if (magicDWordLeft)
- error("Script-Patcher: Magic-DWORD beyond End-Of-Signature\nFaulty patch: '%s'", curEntry->description);
- if (!curRuntimeEntry->magicDWord)
- error("Script-Patcher: Magic-DWORD not specified in signature\nFaulty patch: '%s'", curEntry->description);
+ // We verify the signature data and remember the calculated magic DWord from the signature data
+ calculateMagicDWordAndVerify(curEntry->description, curEntry->signatureData, true, curRuntimeEntry->magicDWord, curRuntimeEntry->magicOffset);
+ // We verify the patch data
+ calculateMagicDWordAndVerify(curEntry->description, curEntry->patchData, false, curRuntimeEntry->magicDWord, curRuntimeEntry->magicOffset);
curEntry++; curRuntimeEntry++;
}
@@ -3596,6 +3997,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3
case GID_KQ6:
signatureTable = kq6Signatures;
break;
+ case GID_LAURABOW:
+ signatureTable = laurabow1Signatures;
+ break;
case GID_LAURABOW2:
signatureTable = laurabow2Signatures;
break;
diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h
index d15fce321b..645e0946b3 100644
--- a/engines/sci/engine/script_patches.h
+++ b/engines/sci/engine/script_patches.h
@@ -90,13 +90,32 @@ public:
ScriptPatcher();
~ScriptPatcher();
+ // Calculates the magic DWord for fast search and verifies signature/patch data
+ // Returns the magic DWord in platform-specific byte-order. This is done on purpose for performance.
+ void calculateMagicDWordAndVerify(const char *signatureDescription, const uint16 *signatureData, bool magicDWordIncluded, uint32 &calculatedMagicDWord, int &calculatedMagicDWordOffset);
+
+ // Called when a script is loaded to check for signature matches and apply patches in such cases
void processScript(uint16 scriptNr, byte *scriptData, const uint32 scriptSize);
+
+ // Verifies, if a given signature matches the given script data (pointed to by additional byte offset)
bool verifySignature(uint32 byteOffset, const uint16 *signatureData, const char *signatureDescription, const byte *scriptData, const uint32 scriptSize);
+ // searches for a given signature inside script data
+ // returns -1 in case it was not found or an offset to the matching data
+ int32 findSignature(uint32 magicDWord, int magicOffset, const uint16 *signatureData, const char *patchDescription, const byte *scriptData, const uint32 scriptSize);
+
private:
+ // Initializes a patch table and creates run time information for it (for enabling/disabling), also calculates magic DWORD)
void initSignature(const SciScriptPatcherEntry *patchTable);
+
+ // Enables a patch inside the patch table (used for optional patches like CD+Text support for KQ6 & LB2)
void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription);
- int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize);
+
+ // Searches for a given signature entry inside script data
+ // returns -1 in case it was not found or an offset to the matching data
+ int32 findSignature(const SciScriptPatcherEntry *patchEntry, const SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize);
+
+ // Applies a patch to a given script + offset (overwrites parts)
void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset);
Selector *_selectorIdTable;
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index f0157a6569..7d70f30d55 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -499,7 +499,7 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) {
void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- unsigned int _seeker = 0;
+ uint32 _seeker = 0;
Resource *script = _resMan->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0);
if (!script) {
@@ -510,7 +510,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
while (_seeker < script->size) {
int objType = (int16)READ_SCI11ENDIAN_UINT16(script->data + _seeker);
int objsize;
- unsigned int seeker = _seeker + 4;
+ uint32 seeker = _seeker + 4;
if (!objType) {
debugN("End of script object (#0) encountered.\n");
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 23b1fdae23..8090b1861d 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -837,10 +837,13 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) {
d._size = size;
- if (size == 0)
+ // Original SCI only zeroed out heap memory on initialize
+ // They didn't do it again for every allocation
+ if (size) {
+ d._buf = (byte *)calloc(size, 1);
+ } else {
d._buf = NULL;
- else
- d._buf = (byte *)malloc(size);
+ }
d._description = descr;
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index de7f60ac16..2699bc2e5b 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -203,7 +203,7 @@ struct List {
struct Hunk {
void *mem;
- unsigned int size;
+ uint32 size;
const char *type;
};
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index 910f1f885f..ac621f58ae 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -179,6 +179,8 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(fore);
FIND_SELECTOR(back);
FIND_SELECTOR(skip);
+ FIND_SELECTOR(borderColor);
+ FIND_SELECTOR(width);
FIND_SELECTOR(fixPriority);
FIND_SELECTOR(mirrored);
FIND_SELECTOR(visible);
@@ -187,6 +189,17 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(inLeft);
FIND_SELECTOR(inBottom);
FIND_SELECTOR(inRight);
+ FIND_SELECTOR(textTop);
+ FIND_SELECTOR(textLeft);
+ FIND_SELECTOR(textBottom);
+ FIND_SELECTOR(textRight);
+ FIND_SELECTOR(title);
+ FIND_SELECTOR(titleFont);
+ FIND_SELECTOR(titleFore);
+ FIND_SELECTOR(titleBack);
+ FIND_SELECTOR(magnifier);
+ FIND_SELECTOR(frameOut);
+ FIND_SELECTOR(casts);
#endif
}
@@ -199,6 +212,16 @@ reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId) {
return *address.getPointer(segMan);
}
+#ifdef ENABLE_SCI32
+void updateInfoFlagViewVisible(Object *obj, int index) {
+ // TODO: Make this correct for all SCI versions
+ // Selectors 26 through 44 are selectors for View script objects in SQ6
+ if (index >= 26 && index <= 44 && getSciVersion() >= SCI_VERSION_2) {
+ obj->setInfoSelectorFlag(kInfoFlagViewVisible);
+ }
+}
+#endif
+
void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value) {
ObjVarRef address;
@@ -211,8 +234,12 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t
if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
error("Selector '%s' of object at %04x:%04x could not be"
" written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
- else
+ else {
*address.getPointer(segMan) = value;
+#ifdef ENABLE_SCI32
+ updateInfoFlagViewVisible(segMan->getObject(object), selectorId);
+#endif
+ }
}
void invokeSelector(EngineState *s, reg_t object, int selectorId,
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index b3dd393708..f2d06d1cf4 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -146,6 +146,8 @@ struct SelectorCache {
Selector back;
Selector skip;
Selector dimmed;
+ Selector borderColor;
+ Selector width;
Selector fixPriority;
Selector mirrored;
@@ -153,6 +155,12 @@ struct SelectorCache {
Selector useInsetRect;
Selector inTop, inLeft, inBottom, inRight;
+ Selector textTop, textLeft, textBottom, textRight;
+ Selector title, titleFont, titleFore, titleBack;
+
+ Selector magnifier;
+ Selector frameOut;
+ Selector casts; // needed for sync'ing screen items/planes with scripts, when our save/restore code is patched in (see GfxFrameout::syncWithScripts)
#endif
};
@@ -191,6 +199,16 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t
void invokeSelector(EngineState *s, reg_t object, int selectorId,
int k_argc, StackPtr k_argp, int argc = 0, const reg_t *argv = 0);
+#ifdef ENABLE_SCI32
+/**
+ * SCI32 set kInfoFlagViewVisible in the -info- selector if a certain
+ * range of properties was written to.
+ * This function checks if index is in the right range, and sets the flag
+ * on obj.-info- if it is.
+ */
+void updateInfoFlagViewVisible(Object *obj, int index);
+#endif
+
} // End of namespace Sci
#endif // SCI_ENGINE_KERNEL_H
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index d53e6b48c8..fda78317b5 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -95,6 +95,7 @@ void EngineState::reset(bool isRestoring) {
// reset delayed restore game functionality
_delayedRestoreGame = false;
_delayedRestoreGameId = 0;
+ _delayedRestoreFromLauncher = false;
executionStackBase = 0;
_executionStackPosChanged = false;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 0f04e32fe5..cf9a753f5c 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -138,10 +138,12 @@ public:
// see detection.cpp / SciEngine::loadGameState()
bool _delayedRestoreGame; // boolean, that triggers delayed restore (triggered by ScummVM menu)
int _delayedRestoreGameId; // the saved game id, that it supposed to get restored (triggered by ScummVM menu)
+ bool _delayedRestoreFromLauncher; // is set, when the the delayed restore game was triggered from launcher
uint _chosenQfGImportItem; // Remembers the item selected in QfG import rooms
bool _cursorWorkaroundActive; // Refer to GfxCursor::setPosition()
+ int16 _cursorWorkaroundPosCount; // When the cursor is reported to be at the previously set coordinate, we won't disable the workaround unless it happened for this many times
Common::Point _cursorWorkaroundPoint;
Common::Rect _cursorWorkaroundRect;
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 3729fc5236..64e6c045db 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -258,6 +258,10 @@ static void _exec_varselectors(EngineState *s) {
if (xs.argc) { // write?
*var = xs.variables_argp[1];
+#ifdef ENABLE_SCI32
+ updateInfoFlagViewVisible(s->_segMan->getObject(xs.addr.varp.obj), xs.addr.varp.varindex);
+#endif
+
} else // No, read
s->r_acc = *var;
}
@@ -1095,6 +1099,9 @@ void run_vm(EngineState *s) {
case op_aTop: // 0x32 (50)
// Accumulator To Property
validate_property(s, obj, opparams[0]) = s->r_acc;
+#ifdef ENABLE_SCI32
+ updateInfoFlagViewVisible(obj, opparams[0]>>1);
+#endif
break;
case op_pTos: // 0x33 (51)
@@ -1105,6 +1112,9 @@ void run_vm(EngineState *s) {
case op_sTop: // 0x34 (52)
// Stack To Property
validate_property(s, obj, opparams[0]) = POP32();
+#ifdef ENABLE_SCI32
+ updateInfoFlagViewVisible(obj, opparams[0]>>1);
+#endif
break;
case op_ipToa: // 0x35 (53)
@@ -1119,7 +1129,9 @@ void run_vm(EngineState *s) {
opProperty += 1;
else
opProperty -= 1;
-
+#ifdef ENABLE_SCI32
+ updateInfoFlagViewVisible(obj, opparams[0]>>1);
+#endif
if (opcode == op_ipToa || opcode == op_dpToa)
s->r_acc = opProperty;
else
diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp
index cf008c45e1..d74e2b194c 100644
--- a/engines/sci/engine/vm_types.cpp
+++ b/engines/sci/engine/vm_types.cpp
@@ -210,12 +210,30 @@ reg_t reg_t::operator^(const reg_t right) const {
return lookForWorkaround(right, "bitwise XOR");
}
+#ifdef ENABLE_SCI32
+reg_t reg_t::operator&(int16 right) const {
+ return *this & make_reg(0, right);
+}
+
+reg_t reg_t::operator|(int16 right) const {
+ return *this | make_reg(0, right);
+}
+
+reg_t reg_t::operator^(int16 right) const {
+ return *this ^ make_reg(0, right);
+}
+#endif
+
int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
if (getSegment() == right.getSegment()) { // can compare things in the same segment
if (treatAsUnsigned || !isNumber())
return toUint16() - right.toUint16();
else
return toSint16() - right.toSint16();
+#ifdef ENABLE_SCI32
+ } else if (getSciVersion() >= SCI_VERSION_2) {
+ return sci32Comparison(right);
+#endif
} else if (pointerComparisonWithInteger(right)) {
return 1;
} else if (right.pointerComparisonWithInteger(*this)) {
@@ -224,6 +242,26 @@ int reg_t::cmp(const reg_t right, bool treatAsUnsigned) const {
return lookForWorkaround(right, "comparison").toSint16();
}
+#ifdef ENABLE_SCI32
+int reg_t::sci32Comparison(const reg_t right) const {
+ // In SCI32, MemIDs are normally indexes into the memory manager's handle
+ // list, but the engine reserves indexes at and above 20000 for objects
+ // that were created inside the engine (as opposed to inside the VM). The
+ // engine compares these as a tiebreaker for graphics objects that are at
+ // the same priority, and it is necessary to at least minimally handle
+ // this situation.
+ // This is obviously a bogus comparision, but then, this entire thing is
+ // bogus. For the moment, it just needs to be deterministic.
+ if (isNumber() && !right.isNumber()) {
+ return 1;
+ } else if (right.isNumber() && !isNumber()) {
+ return -1;
+ }
+
+ return getOffset() - right.getOffset();
+}
+#endif
+
bool reg_t::pointerComparisonWithInteger(const reg_t right) const {
// This function handles the case where a script tries to compare a pointer
// to a number. Normally, we would not want to allow that. However, SCI0 -
diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h
index af78bd0b84..e60f52e85c 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -136,6 +136,19 @@ struct reg_t {
reg_t operator|(const reg_t right) const;
reg_t operator^(const reg_t right) const;
+#ifdef ENABLE_SCI32
+ reg_t operator&(int16 right) const;
+ reg_t operator|(int16 right) const;
+ reg_t operator^(int16 right) const;
+
+ void operator&=(const reg_t &right) { *this = *this & right; }
+ void operator|=(const reg_t &right) { *this = *this | right; }
+ void operator^=(const reg_t &right) { *this = *this ^ right; }
+ void operator&=(int16 right) { *this = *this & right; }
+ void operator|=(int16 right) { *this = *this | right; }
+ void operator^=(int16 right) { *this = *this ^ right; }
+#endif
+
private:
/**
* Compares two reg_t's.
@@ -147,6 +160,10 @@ private:
int cmp(const reg_t right, bool treatAsUnsigned) const;
reg_t lookForWorkaround(const reg_t right, const char *operation) const;
bool pointerComparisonWithInteger(const reg_t right) const;
+
+#ifdef ENABLE_SCI32
+ int sci32Comparison(const reg_t right) const;
+#endif
};
static inline reg_t make_reg(SegmentId segment, uint16 offset) {
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index aab32032f7..3832f4cf04 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -378,6 +378,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places
{ GID_SQ6, -1, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game
{ GID_TORIN, -1, 64017, 0, "oFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version
+ { GID_TORIN, 10000, 64029, 0, "oMessager", "nextMsg", NULL, 3, { WORKAROUND_FAKE, 0 } }, // start of chapter one
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -630,7 +631,7 @@ const SciWorkaroundEntry kGraphUpdateBox_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
const SciWorkaroundEntry kIsObject_workarounds[] = {
- { GID_GK1, 50, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950
+ { GID_GK1DEMO, 50, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // GK1 demo, when asking Grace for messages it gets called with an invalid parameter (type "error") - bug #4950
{ GID_ISLANDBRAIN, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when going to the game options, choosing "Info" and selecting anything from the list, gets called with an invalid parameter (type "error") - bug #4989
{ GID_QFG3, -1, 999, 0, "List", "eachElementDo", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when asking for something, gets called with type error parameter
SCI_WORKAROUNDENTRY_TERMINATOR
@@ -656,6 +657,12 @@ const SciWorkaroundEntry kNewWindow_workarounds[] = {
};
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
+const SciWorkaroundEntry kPalVarySetPercent_workarounds[] = {
+ { GID_GK1, 370, 370, 0, "graceComeOut", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // there's an extra parameter in GK1, when changing chapters. This extra parameter seems to be a bug or just unimplemented functionality, as there's no visible change from the original in the chapter change room
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
const SciWorkaroundEntry kReadNumber_workarounds[] = {
{ GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425
{ GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425
@@ -664,7 +671,7 @@ const SciWorkaroundEntry kReadNumber_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = {
- { GID_QFG4, 100, 100, 0, "doMovie", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947
+ { GID_QFG4DEMO, 100, 100, 0, "doMovie", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #4947
SCI_WORKAROUNDENTRY_TERMINATOR
};
diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h
index 46059a175c..8f519a8c9c 100644
--- a/engines/sci/engine/workarounds.h
+++ b/engines/sci/engine/workarounds.h
@@ -89,6 +89,7 @@ extern const SciWorkaroundEntry kIsObject_workarounds[];
extern const SciWorkaroundEntry kMemory_workarounds[];
extern const SciWorkaroundEntry kMoveCursor_workarounds[];
extern const SciWorkaroundEntry kNewWindow_workarounds[];
+extern const SciWorkaroundEntry kPalVarySetPercent_workarounds[];
extern const SciWorkaroundEntry kReadNumber_workarounds[];
extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[];
extern const SciWorkaroundEntry kSetCursor_workarounds[];
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index f8285c26f2..34f1618514 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -29,6 +29,9 @@
#include "sci/console.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
+#ifdef ENABLE_SCI32
+#include "sci/graphics/frameout.h"
+#endif
#include "sci/graphics/screen.h"
namespace Sci {
@@ -44,7 +47,7 @@ static const ScancodeRow scancodeAltifyRows[] = {
{ 0x2c, "ZXCVBNM,./" }
};
-static const byte codepagemap_88591toDOS[0x80] = {
+static const byte codePageMap88591ToDOS[0x80] = {
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x9x
'?', 0xad, 0x9b, 0x9c, '?', 0x9d, '?', 0x9e, '?', '?', 0xa6, 0xae, 0xaa, '?', '?', '?', // 0xAx
@@ -133,8 +136,13 @@ static int altify(int ch) {
}
SciEvent EventManager::getScummVMEvent() {
- SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) };
- SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) };
+#ifdef ENABLE_SCI32
+ SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
+ SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
+#else
+ SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() };
+ SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() };
+#endif
Common::EventManager *em = g_system->getEventManager();
Common::Event ev;
@@ -155,7 +163,20 @@ SciEvent EventManager::getScummVMEvent() {
// via pollEvent.
// We also adjust the position based on the scaling of the screen.
Common::Point mousePos = em->getMousePos();
- g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
+
+#if ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer();
+
+ Common::Point mousePosSci = mousePos;
+ mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight));
+ noEvent.mousePosSci = input.mousePosSci = mousePosSci;
+ } else {
+#endif
+ g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
+#if ENABLE_SCI32
+ }
+#endif
noEvent.mousePos = input.mousePos = mousePos;
@@ -173,7 +194,7 @@ SciEvent EventManager::getScummVMEvent() {
return input;
}
- int scummVMKeyFlags;
+ int scummVMKeyFlags;
switch (ev.type) {
case Common::EVENT_KEYDOWN:
@@ -265,7 +286,7 @@ SciEvent EventManager::getScummVMEvent() {
return noEvent;
// Convert 8859-1 characters to DOS (cp850/437) for
// multilingual SCI01 games
- input.character = codepagemap_88591toDOS[input.character & 0x7f];
+ input.character = codePageMap88591ToDOS[input.character & 0x7f];
}
if (scummVMKeycode == Common::KEYCODE_TAB) {
input.character = SCI_KEY_TAB;
@@ -302,6 +323,11 @@ SciEvent EventManager::getScummVMEvent() {
input.character = altify(input.character);
if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (scummVMKeyFlags & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
input.character += 96; // 0x01 -> 'a'
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2 && (scummVMKeyFlags & Common::KBD_CTRL) && input.character == 'c') {
+ input.character = SCI_KEY_ETX;
+ }
+#endif
// If no actual key was pressed (e.g. if only a modifier key was pressed),
// ignore the event
@@ -328,8 +354,12 @@ void EventManager::updateScreen() {
}
}
-SciEvent EventManager::getSciEvent(unsigned int mask) {
- SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) };
+SciEvent EventManager::getSciEvent(uint32 mask) {
+#ifdef ENABLE_SCI32
+ SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
+#else
+ SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point() };
+#endif
EventManager::updateScreen();
@@ -342,7 +372,7 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
// Search for matching event in queue
Common::List<SciEvent>::iterator iter = _events.begin();
- while (iter != _events.end() && !((*iter).type & mask))
+ while (iter != _events.end() && !(iter->type & mask))
++iter;
if (iter != _events.end()) {
@@ -364,17 +394,17 @@ SciEvent EventManager::getSciEvent(unsigned int mask) {
void SciEngine::sleep(uint32 msecs) {
uint32 time;
- const uint32 wakeup_time = g_system->getMillis() + msecs;
+ const uint32 wakeUpTime = g_system->getMillis() + msecs;
while (true) {
// let backend process events and update the screen
_eventMan->getSciEvent(SCI_EVENT_PEEK);
time = g_system->getMillis();
- if (time + 10 < wakeup_time) {
+ if (time + 10 < wakeUpTime) {
g_system->delayMillis(10);
} else {
- if (time < wakeup_time)
- g_system->delayMillis(wakeup_time - time);
+ if (time < wakeUpTime)
+ g_system->delayMillis(wakeUpTime - time);
break;
}
diff --git a/engines/sci/event.h b/engines/sci/event.h
index 76c884aba4..15a94b3e73 100644
--- a/engines/sci/event.h
+++ b/engines/sci/event.h
@@ -39,11 +39,18 @@ struct SciEvent {
uint16 character;
/**
- * The mouse position at the time the event was created.
- *
- * These are display coordinates!
+ * The mouse position at the time the event was created,
+ * in display coordinates.
*/
Common::Point mousePos;
+
+#ifdef ENABLE_SCI32
+ /**
+ * The mouse position at the time the event was created,
+ * in script coordinates.
+ */
+ Common::Point mousePosSci;
+#endif
};
/*Values for type*/
@@ -59,6 +66,9 @@ struct SciEvent {
#define SCI_EVENT_ANY 0x7fff
/* Keycodes of special keys: */
+#ifdef ENABLE_SCI32
+#define SCI_KEY_ETX 3
+#endif
#define SCI_KEY_ESC 27
#define SCI_KEY_BACKSPACE 8
#define SCI_KEY_ENTER 13
@@ -121,7 +131,7 @@ public:
~EventManager();
void updateScreen();
- SciEvent getSciEvent(unsigned int mask);
+ SciEvent getSciEvent(uint32 mask);
private:
SciEvent getScummVMEvent();
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 7957ed6a55..98278397b7 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -28,6 +28,7 @@
#include "sci/sci.h"
#include "sci/event.h"
#include "sci/engine/kernel.h"
+#include "sci/engine/script_patches.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
@@ -44,8 +45,8 @@
namespace Sci {
-GfxAnimate::GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions)
- : _s(state), _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _palette(palette), _cursor(cursor), _transitions(transitions) {
+GfxAnimate::GfxAnimate(EngineState *state, ScriptPatcher *scriptPatcher, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions)
+ : _s(state), _scriptPatcher(scriptPatcher), _cache(cache), _ports(ports), _paint16(paint16), _screen(screen), _palette(palette), _cursor(cursor), _transitions(transitions) {
init();
}
@@ -55,16 +56,77 @@ GfxAnimate::~GfxAnimate() {
void GfxAnimate::init() {
_lastCastData.clear();
- _ignoreFastCast = false;
- // fastCast object is not found in any SCI games prior SCI1
- if (getSciVersion() <= SCI_VERSION_01)
- _ignoreFastCast = true;
- // Also if fastCast object exists at gamestartup, we can assume that the interpreter doesnt do kAnimate aborts
- // (found in Larry 1)
- if (getSciVersion() > SCI_VERSION_0_EARLY) {
- if (!_s->_segMan->findObjectByName("fastCast").isNull())
- _ignoreFastCast = true;
+ _fastCastEnabled = false;
+ if (getSciVersion() == SCI_VERSION_1_1) {
+ // Seems to have been available for all SCI1.1 games
+ _fastCastEnabled = true;
+ } else if (getSciVersion() >= SCI_VERSION_1_EARLY) {
+ // fastCast only exists for some games between SCI1 early and SCI1 late
+ // Try to detect it by code signature
+ // It's extremely important, that we only enable it for games that actually need it
+ if (detectFastCast()) {
+ _fastCastEnabled = true;
+ }
+ }
+}
+
+// Signature for fastCast detection
+static const uint16 fastCastSignature[] = {
+ SIG_MAGICDWORD,
+ 0x35, 0x00, // ldi 00
+ 0xa1, 84, // sag global[84d]
+ SIG_END
+};
+
+// Fast cast in games:
+
+// SCI1 Early:
+// KQ5 - no fastcast, LSL1 (demo) - no fastcast, Mixed Up Fairy Tales - *has fastcast*, XMas Card 1990 - no fastcast,
+// SQ4Floppy - no fastcast, Mixed Up Mother Goose - no fastcast
+//
+// SCI1 Middle:
+// LSL5 demo - no fastfast, Conquest of the Longbow demo - no fastcast, LSL1 - no fastcast,
+// Astro Chicken II - no fastcast
+//
+// SCI1 Late:
+// Castle of Dr. Brain demo - has fastcast, Castle of Dr. Brain - has fastcast,
+// Conquests of the Longbow - has fastcast, Space Quest 1 EGA - has fastcast,
+// King's Quest 5 multilingual - *NO* fastcast, Police Quest 3 demo - *NO* fastcast,
+// LSL5 multilingual - has fastcast, Police Quest 3 - has fastcast,
+// EcoQuest 1 - has fastcast, Mixed Up Fairy Tales demo - has fastcast,
+// Space Quest 4 multilingual - *NO* fastcast
+//
+// SCI1.1
+// Quest for Glory 3 demo - has fastcast, Police Quest 1 - hast fastcast, Quest for Glory 1 - has fastcast
+// Laura Bow 2 Floppy - has fastcast, Mixed Up Mother Goose - has fastcast, Quest for Glory 3 - has fastcast
+// Island of Dr. Brain - has fastcast, King's Quest 6 - has fastcast, Space Quest 5 - has fastcast
+// Hoyle 4 - has fastcast, Laura Bow 2 CD - has fastcast, Freddy Pharkas CD - has fastcast
+bool GfxAnimate::detectFastCast() {
+ SegManager *segMan = _s->_segMan;
+ const reg_t gameVMObject = g_sci->getGameObject();
+ reg_t gameSuperVMObject = segMan->getObject(gameVMObject)->getSuperClassSelector();
+ uint32 magicDWord = 0; // platform-specific BE/LE for performance
+ int magicDWordOffset = 0;
+
+ if (gameSuperVMObject.isNull()) {
+ gameSuperVMObject = gameVMObject; // Just in case. According to sci.cpp this may happen in KQ5CD, when loading saved games before r54510
+ }
+
+ Script *objectScript = segMan->getScript(gameSuperVMObject.getSegment());
+ byte *scriptData = const_cast<byte *>(objectScript->getBuf(0));
+ uint32 scriptSize = objectScript->getBufSize();
+
+ _scriptPatcher->calculateMagicDWordAndVerify("fast cast detection", fastCastSignature, true, magicDWord, magicDWordOffset);
+
+ // Signature is found for multilingual King's Quest 5 too, but it looks as if the fast cast global is never set
+ // within that game. Which means even though we detect it as having the capability, it's never actually used.
+ // The original multilingual KQ5 interpreter did have this feature disabled.
+ // Sierra probably used latest system scripts and that's why we detect it.
+ if (_scriptPatcher->findSignature(magicDWord, magicDWordOffset, fastCastSignature, "fast cast detection", scriptData, scriptSize) >= 0) {
+ // Signature found, game seems to use fast cast for kAnimate
+ return true;
}
+ return false;
}
void GfxAnimate::disposeLastCast() {
@@ -80,12 +142,14 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
while (curNode) {
curObject = curNode->value;
- if (!_ignoreFastCast) {
+ if (_fastCastEnabled) {
// Check if the game has a fastCast object set
// if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes.
if (!_s->variables[VAR_GLOBAL][84].isNull()) {
- if (!strcmp(_s->_segMan->getObjectName(_s->variables[VAR_GLOBAL][84]), "fastCast"))
- return false;
+ // This normally points to an object called "fastCast",
+ // but for example in Eco Quest 1 it may also point to an object called "EventHandler" (see bug #5170)
+ // Original SCI only checked, if this global was not 0.
+ return false;
}
}
diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h
index 6c1822c903..ac7078093c 100644
--- a/engines/sci/graphics/animate.h
+++ b/engines/sci/graphics/animate.h
@@ -87,9 +87,13 @@ class GfxView;
*/
class GfxAnimate {
public:
- GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions);
+ GfxAnimate(EngineState *state, ScriptPatcher *scriptPatcher, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions);
virtual ~GfxAnimate();
+ bool isFastCastEnabled() {
+ return _fastCastEnabled;
+ }
+
void disposeLastCast();
bool invoke(List *list, int argc, reg_t *argv);
void makeSortedList(List *list);
@@ -110,6 +114,7 @@ public:
private:
void init();
+ bool detectFastCast();
void addToPicSetPicNotValid();
void animateShowPic();
@@ -119,6 +124,7 @@ private:
void setNsRect(GfxView *view, AnimateList::iterator it);
EngineState *_s;
+ ScriptPatcher *_scriptPatcher;
GfxCache *_cache;
GfxPorts *_ports;
GfxPaint16 *_paint16;
@@ -130,7 +136,7 @@ private:
AnimateList _list;
AnimateArray _lastCastData;
- bool _ignoreFastCast;
+ bool _fastCastEnabled;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp
index 59af8334eb..fb1f557ad6 100644
--- a/engines/sci/graphics/cache.cpp
+++ b/engines/sci/graphics/cache.cpp
@@ -102,8 +102,4 @@ int16 GfxCache::kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo) {
return getView(viewId)->getCelCount(loopNo);
}
-byte GfxCache::kernelViewGetColorAtCoordinate(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 x, int16 y) {
- return getView(viewId)->getColorAtCoordinate(loopNo, celNo, x, y);
-}
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/cache.h b/engines/sci/graphics/cache.h
index 33fa4fe399..61952718a9 100644
--- a/engines/sci/graphics/cache.h
+++ b/engines/sci/graphics/cache.h
@@ -49,8 +49,6 @@ public:
int16 kernelViewGetLoopCount(GuiResourceId viewId);
int16 kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo);
- byte kernelViewGetColorAtCoordinate(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 x, int16 y);
-
private:
void purgeFontCache();
void purgeViewCache();
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
new file mode 100644
index 0000000000..693bc5f196
--- /dev/null
+++ b/engines/sci/graphics/celobj32.cpp
@@ -0,0 +1,1050 @@
+/* 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 "sci/resource.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/state.h"
+#include "sci/graphics/celobj32.h"
+#include "sci/graphics/frameout.h"
+#include "sci/graphics/palette32.h"
+#include "sci/graphics/picture.h"
+#include "sci/graphics/remap.h"
+#include "sci/graphics/text32.h"
+#include "sci/graphics/view.h"
+
+namespace Sci {
+#pragma mark CelScaler
+CelScaler *CelObj::_scaler = nullptr;
+
+void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) {
+ const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
+ const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+
+ for (int i = 0; i < ARRAYSIZE(_scaleTables); ++i) {
+ if (_scaleTables[i].scaleX == scaleX && _scaleTables[i].scaleY == scaleY) {
+ _activeIndex = i;
+ return;
+ }
+ }
+
+ int i = 1 - _activeIndex;
+ _activeIndex = i;
+ CelScalerTable &table = _scaleTables[i];
+
+ if (table.scaleX != scaleX) {
+ assert(screenWidth <= ARRAYSIZE(table.valuesX));
+ buildLookupTable(table.valuesX, scaleX, screenWidth);
+ table.scaleX = scaleX;
+ }
+
+ if (table.scaleY != scaleY) {
+ assert(screenHeight <= ARRAYSIZE(table.valuesY));
+ buildLookupTable(table.valuesY, scaleY, screenHeight);
+ table.scaleY = scaleY;
+ }
+}
+
+void CelScaler::buildLookupTable(int *table, const Ratio &ratio, const int size) {
+ int value = 0;
+ int remainder = 0;
+ int num = ratio.getNumerator();
+ for (int i = 0; i < size; ++i) {
+ *table++ = value;
+ remainder += ratio.getDenominator();
+ if (remainder >= num) {
+ value += remainder / num;
+ remainder %= num;
+ }
+ }
+}
+
+const CelScalerTable *CelScaler::getScalerTable(const Ratio &scaleX, const Ratio &scaleY) {
+ activateScaleTables(scaleX, scaleY);
+ return &_scaleTables[_activeIndex];
+}
+
+#pragma mark -
+#pragma mark CelObj
+
+void CelObj::init() {
+ CelObj::deinit();
+ _nextCacheId = 1;
+ _scaler = new CelScaler();
+ _cache = new CelCache;
+ _cache->resize(100);
+}
+
+void CelObj::deinit() {
+ delete _scaler;
+ _scaler = nullptr;
+ if (_cache != nullptr) {
+ for (CelCache::iterator it = _cache->begin(); it != _cache->end(); ++it) {
+ delete it->celObj;
+ }
+ }
+ delete _cache;
+ _cache = nullptr;
+}
+
+#pragma mark -
+#pragma mark CelObj - Scalers
+
+template<bool FLIP, typename READER>
+struct SCALER_NoScale {
+#ifndef NDEBUG
+ const byte *_rowEdge;
+#endif
+ const byte *_row;
+ READER _reader;
+ const int16 _lastIndex;
+ const int16 _sourceX;
+ const int16 _sourceY;
+
+ SCALER_NoScale(const CelObj &celObj, const int16 maxWidth, const Common::Point &scaledPosition) :
+ _reader(celObj, FLIP ? celObj._width : maxWidth),
+ _lastIndex(celObj._width - 1),
+ _sourceX(scaledPosition.x),
+ _sourceY(scaledPosition.y) {}
+
+ inline void setTarget(const int16 x, const int16 y) {
+ _row = _reader.getRow(y - _sourceY);
+
+ if (FLIP) {
+#ifndef NDEBUG
+ _rowEdge = _row - 1;
+#endif
+ _row += _lastIndex - (x - _sourceX);
+ assert(_row > _rowEdge);
+ } else {
+#ifndef NDEBUG
+ _rowEdge = _row + _lastIndex + 1;
+#endif
+ _row += x - _sourceX;
+ assert(_row < _rowEdge);
+ }
+ }
+
+ inline byte read() {
+ assert(_row != _rowEdge);
+
+ if (FLIP) {
+ return *_row--;
+ } else {
+ return *_row++;
+ }
+ }
+};
+
+template<bool FLIP, typename READER>
+struct SCALER_Scale {
+#ifndef NDEBUG
+ int16 _maxX;
+#endif
+ const byte *_row;
+ READER _reader;
+ int16 _x;
+ static int16 _valuesX[1024];
+ static int16 _valuesY[1024];
+
+ SCALER_Scale(const CelObj &celObj, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio scaleX, const Ratio scaleY) :
+#ifndef NDEBUG
+ _maxX(targetRect.right - 1),
+#endif
+ // The maximum width of the scaled object may not be as
+ // wide as the source data it requires if downscaling,
+ // so just always make the reader decompress an entire
+ // line of source data when scaling
+ _reader(celObj, celObj._width) {
+ // In order for scaling ratios to apply equally across objects that
+ // start at different positions on the screen, the pixels that are
+ // read from the source bitmap must all use the same pattern of
+ // division. In other words, cels must follow the same scaling pattern
+ // as if they were drawn starting at an even multiple of the scaling
+ // ratio, even if they were not.
+ //
+ // To get the correct source pixel when reading out through the scaler,
+ // the engine creates a lookup table for each axis that translates
+ // directly from target positions to the indexes of source pixels using
+ // the global cadence for the given scaling ratio.
+
+ const CelScalerTable *table = CelObj::_scaler->getScalerTable(scaleX, scaleY);
+
+ const int16 unscaledX = (scaledPosition.x / scaleX).toInt();
+ if (FLIP) {
+ int lastIndex = celObj._width - 1;
+ for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+ _valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX);
+ }
+ } else {
+ for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+ _valuesX[x] = table->valuesX[x] - unscaledX;
+ }
+ }
+
+ const int16 unscaledY = (scaledPosition.y / scaleY).toInt();
+ for (int16 y = targetRect.top; y < targetRect.bottom; ++y) {
+ _valuesY[y] = table->valuesY[y] - unscaledY;
+ }
+ }
+
+ inline void setTarget(const int16 x, const int16 y) {
+ _row = _reader.getRow(_valuesY[y]);
+ _x = x;
+ assert(_x >= 0 && _x <= _maxX);
+ }
+
+ inline byte read() {
+ assert(_x >= 0 && _x <= _maxX);
+ return _row[_valuesX[_x++]];
+ }
+};
+
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesX[1024];
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesY[1024];
+
+#pragma mark -
+#pragma mark CelObj - Resource readers
+
+struct READER_Uncompressed {
+private:
+#ifndef NDEBUG
+ const int16 _sourceHeight;
+#endif
+ byte *_pixels;
+ const int16 _sourceWidth;
+
+public:
+ READER_Uncompressed(const CelObj &celObj, const int16) :
+#ifndef NDEBUG
+ _sourceHeight(celObj._height),
+#endif
+ _sourceWidth(celObj._width) {
+ byte *resource = celObj.getResPointer();
+ _pixels = resource + READ_SCI11ENDIAN_UINT32(resource + celObj._celHeaderOffset + 24);
+ }
+
+ inline const byte *getRow(const int16 y) const {
+ assert(y >= 0 && y < _sourceHeight);
+ return _pixels + y * _sourceWidth;
+ }
+};
+
+struct READER_Compressed {
+private:
+ byte *_resource;
+ byte _buffer[1024];
+ uint32 _controlOffset;
+ uint32 _dataOffset;
+ uint32 _uncompressedDataOffset;
+ int16 _y;
+ const int16 _sourceHeight;
+ const uint8 _transparentColor;
+ const int16 _maxWidth;
+
+public:
+ READER_Compressed(const CelObj &celObj, const int16 maxWidth) :
+ _resource(celObj.getResPointer()),
+ _y(-1),
+ _sourceHeight(celObj._height),
+ _transparentColor(celObj._transparentColor),
+ _maxWidth(maxWidth) {
+ assert(maxWidth <= celObj._width);
+
+ byte *celHeader = _resource + celObj._celHeaderOffset;
+ _dataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 24);
+ _uncompressedDataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 28);
+ _controlOffset = READ_SCI11ENDIAN_UINT32(celHeader + 32);
+ }
+
+ inline const byte *getRow(const int16 y) {
+ assert(y >= 0 && y < _sourceHeight);
+ if (y != _y) {
+ // compressed data segment for row
+ byte *row = _resource + _dataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + y * 4);
+
+ // uncompressed data segment for row
+ byte *literal = _resource + _uncompressedDataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + _sourceHeight * 4 + y * 4);
+
+ uint8 length;
+ for (int16 i = 0; i < _maxWidth; i += length) {
+ byte controlByte = *row++;
+ length = controlByte;
+
+ // Run-length encoded
+ if (controlByte & 0x80) {
+ length &= 0x3F;
+ assert(i + length < (int)sizeof(_buffer));
+
+ // Fill with skip color
+ if (controlByte & 0x40) {
+ memset(_buffer + i, _transparentColor, length);
+ // Next value is fill color
+ } else {
+ memset(_buffer + i, *literal, length);
+ ++literal;
+ }
+ // Uncompressed
+ } else {
+ assert(i + length < (int)sizeof(_buffer));
+ memcpy(_buffer + i, literal, length);
+ literal += length;
+ }
+ }
+ _y = y;
+ }
+
+ return _buffer;
+ }
+};
+
+#pragma mark -
+#pragma mark CelObj - Remappers
+
+struct MAPPER_NoMD {
+ inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
+ if (pixel != skipColor) {
+ *target = pixel;
+ }
+ }
+};
+struct MAPPER_NoMDNoSkip {
+ inline void draw(byte *target, const byte pixel, const uint8) const {
+ *target = pixel;
+ }
+};
+
+struct MAPPER_Map {
+ inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
+ if (pixel != skipColor) {
+ if (pixel < g_sci->_gfxRemap32->getStartColor()) {
+ *target = pixel;
+ } else {
+ if (g_sci->_gfxRemap32->remapEnabled(pixel))
+ *target = g_sci->_gfxRemap32->remapColor(pixel, *target);
+ }
+ }
+ }
+};
+
+void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect) const {
+ const Common::Point &scaledPosition = screenItem._scaledPosition;
+ const Ratio &scaleX = screenItem._ratioX;
+ const Ratio &scaleY = screenItem._ratioY;
+
+ if (_remap) {
+ // NOTE: In the original code this check was `g_Remap_numActiveRemaps && _remap`,
+ // but since we are already in a `_remap` branch, there is no reason to check it
+ // again
+ if (g_sci->_gfxRemap32->getRemapCount()) {
+ if (scaleX.isOne() && scaleY.isOne()) {
+ if (_compressionType == kCelCompressionNone) {
+ if (_drawMirrored) {
+ drawUncompHzFlipMap(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlipMap(target, targetRect, scaledPosition);
+ }
+ } else {
+ if (_drawMirrored) {
+ drawHzFlipMap(target, targetRect, scaledPosition);
+ } else {
+ drawNoFlipMap(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_compressionType == kCelCompressionNone) {
+ scaleDrawUncompMap(target, scaleX, scaleY, targetRect, scaledPosition);
+ } else {
+ scaleDrawMap(target, scaleX, scaleY, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (scaleX.isOne() && scaleY.isOne()) {
+ if (_compressionType == kCelCompressionNone) {
+ if (_drawMirrored) {
+ drawUncompHzFlip(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlip(target, targetRect, scaledPosition);
+ }
+ } else {
+ if (_drawMirrored) {
+ drawHzFlip(target, targetRect, scaledPosition);
+ } else {
+ drawNoFlip(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_compressionType == kCelCompressionNone) {
+ scaleDrawUncomp(target, scaleX, scaleY, targetRect, scaledPosition);
+ } else {
+ scaleDraw(target, scaleX, scaleY, targetRect, scaledPosition);
+ }
+ }
+ }
+ } else {
+ if (scaleX.isOne() && scaleY.isOne()) {
+ if (_compressionType == kCelCompressionNone) {
+ if (_transparent) {
+ if (_drawMirrored) {
+ drawUncompHzFlipNoMD(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlipNoMD(target, targetRect, scaledPosition);
+ }
+ } else {
+ if (_drawMirrored) {
+ drawUncompHzFlipNoMDNoSkip(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlipNoMDNoSkip(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_drawMirrored) {
+ drawHzFlipNoMD(target, targetRect, scaledPosition);
+ } else {
+ drawNoFlipNoMD(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_compressionType == kCelCompressionNone) {
+ scaleDrawUncompNoMD(target, scaleX, scaleY, targetRect, scaledPosition);
+ } else {
+ scaleDrawNoMD(target, scaleX, scaleY, targetRect, scaledPosition);
+ }
+ }
+ }
+}
+
+void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, bool mirrorX) {
+ _drawMirrored = mirrorX;
+ draw(target, screenItem, targetRect);
+}
+
+void CelObj::draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX) {
+ _drawMirrored = mirrorX;
+ Ratio square;
+ drawTo(target, targetRect, scaledPosition, square, square);
+}
+
+void CelObj::drawTo(Buffer &target, Common::Rect const &targetRect, Common::Point const &scaledPosition, Ratio const &scaleX, Ratio const &scaleY) const {
+ if (_remap) {
+ if (scaleX.isOne() && scaleY.isOne()) {
+ if (_compressionType == kCelCompressionNone) {
+ if (_drawMirrored) {
+ drawUncompHzFlipMap(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlipMap(target, targetRect, scaledPosition);
+ }
+ } else {
+ if (_drawMirrored) {
+ drawHzFlipMap(target, targetRect, scaledPosition);
+ } else {
+ drawNoFlipMap(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_compressionType == kCelCompressionNone) {
+ scaleDrawUncompMap(target, scaleX, scaleY, targetRect, scaledPosition);
+ } else {
+ scaleDrawMap(target, scaleX, scaleY, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (scaleX.isOne() && scaleY.isOne()) {
+ if (_compressionType == kCelCompressionNone) {
+ if (_drawMirrored) {
+ drawUncompHzFlipNoMD(target, targetRect, scaledPosition);
+ } else {
+ drawUncompNoFlipNoMD(target, targetRect, scaledPosition);
+ }
+ } else {
+ if (_drawMirrored) {
+ drawHzFlipNoMD(target, targetRect, scaledPosition);
+ } else {
+ drawNoFlipNoMD(target, targetRect, scaledPosition);
+ }
+ }
+ } else {
+ if (_compressionType == kCelCompressionNone) {
+ scaleDrawUncompNoMD(target, scaleX, scaleY, targetRect, scaledPosition);
+ } else {
+ scaleDrawNoMD(target, scaleX, scaleY, targetRect, scaledPosition);
+ }
+ }
+ }
+}
+
+uint8 CelObj::readPixel(uint16 x, const uint16 y, bool mirrorX) const {
+ if (mirrorX) {
+ x = _width - x - 1;
+ }
+
+ if (_compressionType == kCelCompressionNone) {
+ READER_Uncompressed reader(*this, x + 1);
+ return reader.getRow(y)[x];
+ } else {
+ READER_Compressed reader(*this, x + 1);
+ return reader.getRow(y)[x];
+ }
+}
+
+void CelObj::submitPalette() const {
+ if (_hunkPaletteOffset) {
+ Palette palette;
+
+ byte *res = getResPointer();
+ // NOTE: In SCI engine this uses HunkPalette::Init.
+ // TODO: Use a better size value
+ g_sci->_gfxPalette32->createFromData(res + _hunkPaletteOffset, 999999, &palette);
+ g_sci->_gfxPalette32->submit(palette);
+ }
+}
+
+#pragma mark -
+#pragma mark CelObj - Caching
+int CelObj::_nextCacheId = 1;
+CelCache *CelObj::_cache = nullptr;
+
+int CelObj::searchCache(const CelInfo32 &celInfo, int *nextInsertIndex) const {
+ int oldestId = _nextCacheId + 1;
+ int oldestIndex = -1;
+
+ for (int i = 0, len = _cache->size(); i < len; ++i) {
+ CelCacheEntry &entry = (*_cache)[i];
+
+ if (entry.celObj != nullptr) {
+ if (entry.celObj->_info == celInfo) {
+ entry.id = ++_nextCacheId;
+ return i;
+ }
+
+ if (oldestId > entry.id) {
+ oldestId = entry.id;
+ oldestIndex = i;
+ }
+ } else if (oldestIndex == -1) {
+ oldestIndex = i;
+ }
+ }
+
+ // NOTE: Unlike the original SCI engine code, the out-param
+ // here is only updated if there was not a cache hit.
+ *nextInsertIndex = oldestIndex;
+ return -1;
+}
+
+void CelObj::putCopyInCache(const int cacheIndex) const {
+ if (cacheIndex == -1) {
+ error("Invalid cache index");
+ }
+
+ CelCacheEntry &entry = (*_cache)[cacheIndex];
+
+ if (entry.celObj != nullptr) {
+ delete entry.celObj;
+ }
+
+ entry.celObj = duplicate();
+ entry.id = ++_nextCacheId;
+}
+
+#pragma mark -
+#pragma mark CelObj - Drawing
+
+template<typename MAPPER, typename SCALER>
+struct RENDERER {
+ MAPPER &_mapper;
+ SCALER &_scaler;
+ const uint8 _skipColor;
+
+ RENDERER(MAPPER &mapper, SCALER &scaler, const uint8 skipColor) :
+ _mapper(mapper),
+ _scaler(scaler),
+ _skipColor(skipColor) {}
+
+ inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left;
+
+ const int16 skipStride = target.screenWidth - targetRect.width();
+ const int16 targetWidth = targetRect.width();
+ const int16 targetHeight = targetRect.height();
+ for (int16 y = 0; y < targetHeight; ++y) {
+ _scaler.setTarget(targetRect.left, targetRect.top + y);
+
+ for (int16 x = 0; x < targetWidth; ++x) {
+ _mapper.draw(targetPixel++, _scaler.read(), _skipColor);
+ }
+
+ targetPixel += skipStride;
+ }
+ }
+};
+
+template<typename MAPPER, typename SCALER>
+void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+
+ MAPPER mapper;
+ SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width(), scaledPosition);
+ RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
+ renderer.draw(target, targetRect, scaledPosition);
+}
+
+template<typename MAPPER, typename SCALER>
+void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const {
+
+ MAPPER mapper;
+ SCALER scaler(*this, targetRect, scaledPosition, scaleX, scaleY);
+ RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
+ renderer.draw(target, targetRect, scaledPosition);
+}
+
+void dummyFill(Buffer &target, const Common::Rect &targetRect) {
+ target.fillRect(targetRect, 250);
+}
+
+void CelObj::drawHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("drawHzFlip");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::drawNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("drawNoFlip");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::drawUncompNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("drawUncompNoFlip");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::drawUncompHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("drawUncompHzFlip");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::scaleDraw(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("scaleDraw");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::scaleDrawUncomp(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ debug("scaleDrawUncomp");
+ dummyFill(target, targetRect);
+}
+
+void CelObj::drawHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_Map, SCALER_NoScale<true, READER_Compressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawNoFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_Map, SCALER_NoScale<false, READER_Compressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompNoFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_Map, SCALER_NoScale<false, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_Map, SCALER_NoScale<true, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::scaleDrawMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ if (_drawMirrored)
+ render<MAPPER_Map, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ else
+ render<MAPPER_Map, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+}
+
+void CelObj::scaleDrawUncompMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ if (_drawMirrored)
+ render<MAPPER_Map, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ else
+ render<MAPPER_Map, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+}
+
+void CelObj::drawNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMD, SCALER_NoScale<false, READER_Compressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawHzFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMD, SCALER_NoScale<true, READER_Compressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMD, SCALER_NoScale<false, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompNoFlipNoMDNoSkip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMDNoSkip, SCALER_NoScale<false, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompHzFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMD, SCALER_NoScale<true, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::drawUncompHzFlipNoMDNoSkip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ render<MAPPER_NoMDNoSkip, SCALER_NoScale<true, READER_Uncompressed> >(target, targetRect, scaledPosition);
+}
+
+void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ if (_drawMirrored)
+ render<MAPPER_NoMD, SCALER_Scale<true, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ else
+ render<MAPPER_NoMD, SCALER_Scale<false, READER_Compressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+}
+
+void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
+ if (_drawMirrored)
+ render<MAPPER_NoMD, SCALER_Scale<true, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+ else
+ render<MAPPER_NoMD, SCALER_Scale<false, READER_Uncompressed> >(target, targetRect, scaledPosition, scaleX, scaleY);
+}
+
+#pragma mark -
+#pragma mark CelObjView
+CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) {
+ _info.type = kCelTypeView;
+ _info.resourceId = viewId;
+ _info.loopNo = loopNo;
+ _info.celNo = celNo;
+ _mirrorX = false;
+ _compressionType = kCelCompressionInvalid;
+ _transparent = true;
+
+ int cacheInsertIndex;
+ int cacheIndex = searchCache(_info, &cacheInsertIndex);
+ if (cacheIndex != -1) {
+ CelCacheEntry &entry = (*_cache)[cacheIndex];
+ *this = *dynamic_cast<CelObjView *>(entry.celObj);
+ entry.id = ++_nextCacheId;
+ return;
+ }
+
+ // TODO: The next code should be moved to a common file that
+ // generates view resource metadata for both SCI16 and SCI32
+ // implementations
+
+ Resource *resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false);
+
+ // NOTE: SCI2.1/SQ6 just silently returns here.
+ if (!resource) {
+ warning("View resource %d not loaded", viewId);
+ return;
+ }
+
+ byte *data = resource->data;
+
+ _scaledWidth = READ_SCI11ENDIAN_UINT16(data + 14);
+ _scaledHeight = READ_SCI11ENDIAN_UINT16(data + 16);
+
+ if (_scaledWidth == 0 || _scaledHeight == 0) {
+ byte sizeFlag = data[5];
+ if (sizeFlag == 0) {
+ _scaledWidth = 320;
+ _scaledHeight = 200;
+ } else if (sizeFlag == 1) {
+ _scaledWidth = 640;
+ _scaledHeight = 480;
+ } else if (sizeFlag == 2) {
+ _scaledWidth = 640;
+ _scaledHeight = 400;
+ }
+ }
+
+ uint16 loopCount = data[2];
+ if (_info.loopNo >= loopCount) {
+ _info.loopNo = loopCount - 1;
+ }
+
+ // NOTE: This is the actual check, in the actual location,
+ // from SCI engine.
+ if (loopNo < 0) {
+ error("Loop is less than 0!");
+ }
+
+ const uint16 viewHeaderSize = READ_SCI11ENDIAN_UINT16(data);
+ const uint8 loopHeaderSize = data[12];
+ const uint8 viewHeaderFieldSize = 2;
+
+ byte *loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * _info.loopNo);
+
+ if ((int8)loopHeader[0] != -1) {
+ if (loopHeader[1] == 1) {
+ _mirrorX = true;
+ }
+
+ loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * (int8)loopHeader[0]);
+ }
+
+ uint8 celCount = loopHeader[2];
+ if (_info.celNo >= celCount) {
+ _info.celNo = celCount - 1;
+ }
+
+ _hunkPaletteOffset = READ_SCI11ENDIAN_UINT32(data + 8);
+ _celHeaderOffset = READ_SCI11ENDIAN_UINT32(loopHeader + 12) + (data[13] * _info.celNo);
+
+ byte *celHeader = data + _celHeaderOffset;
+
+ _width = READ_SCI11ENDIAN_UINT16(celHeader);
+ _height = READ_SCI11ENDIAN_UINT16(celHeader + 2);
+ _displace.x = _width / 2 - (int16)READ_SCI11ENDIAN_UINT16(celHeader + 4);
+ _displace.y = _height - (int16)READ_SCI11ENDIAN_UINT16(celHeader + 6) - 1;
+ _transparentColor = celHeader[8];
+ _compressionType = (CelCompressionType)celHeader[9];
+
+ if (_compressionType != kCelCompressionNone && _compressionType != kCelCompressionRLE) {
+ error("Compression type not supported - V: %d L: %d C: %d", _info.resourceId, _info.loopNo, _info.celNo);
+ }
+
+ if (celHeader[10] & 128) {
+ // NOTE: This is correct according to SCI2.1/SQ6/DOS;
+ // the engine re-reads the byte value as a word value
+ uint16 flags = READ_SCI11ENDIAN_UINT16(celHeader + 10);
+ _transparent = flags & 1 ? true : false;
+ _remap = flags & 2 ? true : false;
+ } else if (_compressionType == kCelCompressionNone) {
+ _remap = analyzeUncompressedForRemap();
+ } else {
+ _remap = analyzeForRemap();
+ }
+
+ putCopyInCache(cacheInsertIndex);
+}
+
+bool CelObjView::analyzeUncompressedForRemap() const {
+ byte *pixels = getResPointer() + READ_SCI11ENDIAN_UINT32(getResPointer() + _celHeaderOffset + 24);
+ for (int i = 0; i < _width * _height; ++i) {
+ byte pixel = pixels[i];
+ if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CelObjView::analyzeForRemap() const {
+ READER_Compressed reader(*this, _width);
+ for (int y = 0; y < _height; y++) {
+ const byte *curRow = reader.getRow(y);
+ for (int x = 0; x < _width; x++) {
+ byte pixel = curRow[x];
+ if (pixel >= g_sci->_gfxRemap32->getStartColor() && pixel <= g_sci->_gfxRemap32->getEndColor() && pixel != _transparentColor) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void CelObjView::draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, bool mirrorX, const Ratio &scaleX, const Ratio &scaleY) {
+ _drawMirrored = mirrorX;
+ drawTo(target, targetRect, scaledPosition, scaleX, scaleY);
+}
+
+CelObjView *CelObjView::duplicate() const {
+ return new CelObjView(*this);
+}
+
+byte *CelObjView::getResPointer() const {
+ return g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, _info.resourceId), false)->data;
+}
+
+#pragma mark -
+#pragma mark CelObjPic
+CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
+ _info.type = kCelTypePic;
+ _info.resourceId = picId;
+ _info.loopNo = 0;
+ _info.celNo = celNo;
+ _mirrorX = false;
+ _compressionType = kCelCompressionInvalid;
+ _transparent = true;
+ _remap = false;
+
+ int cacheInsertIndex;
+ int cacheIndex = searchCache(_info, &cacheInsertIndex);
+ if (cacheIndex != -1) {
+ CelCacheEntry &entry = (*_cache)[cacheIndex];
+ *this = *dynamic_cast<CelObjPic *>(entry.celObj);
+ entry.id = ++_nextCacheId;
+ return;
+ }
+
+ Resource *resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, picId), false);
+
+ // NOTE: SCI2.1/SQ6 just silently returns here.
+ if (!resource) {
+ warning("Pic resource %d not loaded", picId);
+ return;
+ }
+
+ byte *data = resource->data;
+
+ _celCount = data[2];
+
+ if (_info.celNo >= _celCount) {
+ error("Cel number %d greater than cel count %d", _info.celNo, _celCount);
+ }
+
+ _celHeaderOffset = READ_SCI11ENDIAN_UINT16(data) + (READ_SCI11ENDIAN_UINT16(data + 4) * _info.celNo);
+ _hunkPaletteOffset = READ_SCI11ENDIAN_UINT32(data + 6);
+
+ byte *celHeader = data + _celHeaderOffset;
+
+ _width = READ_SCI11ENDIAN_UINT16(celHeader);
+ _height = READ_SCI11ENDIAN_UINT16(celHeader + 2);
+ _displace.x = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 4);
+ _displace.y = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 6);
+ _transparentColor = celHeader[8];
+ _compressionType = (CelCompressionType)celHeader[9];
+ _priority = READ_SCI11ENDIAN_UINT16(celHeader + 36);
+ _relativePosition.x = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 38);
+ _relativePosition.y = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 40);
+
+ uint16 sizeFlag1 = READ_SCI11ENDIAN_UINT16(data + 10);
+ uint16 sizeFlag2 = READ_SCI11ENDIAN_UINT16(data + 12);
+
+ if (sizeFlag2) {
+ _scaledWidth = sizeFlag1;
+ _scaledHeight = sizeFlag2;
+ } else if (sizeFlag1 == 0) {
+ _scaledWidth = 320;
+ _scaledHeight = 200;
+ } else if (sizeFlag1 == 1) {
+ _scaledWidth = 640;
+ _scaledHeight = 480;
+ } else if (sizeFlag1 == 2) {
+ _scaledWidth = 640;
+ _scaledHeight = 400;
+ }
+
+ if (celHeader[10] & 128) {
+ // NOTE: This is correct according to SCI2.1/SQ6/DOS;
+ // the engine re-reads the byte value as a word value
+ uint16 flags = READ_SCI11ENDIAN_UINT16(celHeader + 10);
+ _transparent = flags & 1 ? true : false;
+ _remap = flags & 2 ? true : false;
+ } else {
+ _transparent = _compressionType != kCelCompressionNone ? true : analyzeUncompressedForSkip();
+
+ if (_compressionType != kCelCompressionNone && _compressionType != kCelCompressionRLE) {
+ error("Compression type not supported - P: %d C: %d", picId, celNo);
+ }
+ }
+
+ putCopyInCache(cacheInsertIndex);
+}
+
+bool CelObjPic::analyzeUncompressedForSkip() const {
+ byte *resource = getResPointer();
+ byte *pixels = resource + READ_SCI11ENDIAN_UINT32(resource + _celHeaderOffset + 24);
+ for (int i = 0; i < _width * _height; ++i) {
+ uint8 pixel = pixels[i];
+ if (pixel == _transparentColor) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CelObjPic::draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX) {
+ Ratio square;
+ _drawMirrored = mirrorX;
+ drawTo(target, targetRect, scaledPosition, square, square);
+}
+
+CelObjPic *CelObjPic::duplicate() const {
+ return new CelObjPic(*this);
+}
+
+byte *CelObjPic::getResPointer() const {
+ return g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, _info.resourceId), false)->data;
+}
+
+#pragma mark -
+#pragma mark CelObjMem
+CelObjMem::CelObjMem(const reg_t bitmapObject) {
+ _info.type = kCelTypeMem;
+ _info.bitmap = bitmapObject;
+ _mirrorX = false;
+ _compressionType = kCelCompressionNone;
+ _celHeaderOffset = 0;
+ _transparent = true;
+
+ BitmapResource bitmap(bitmapObject);
+ _width = bitmap.getWidth();
+ _height = bitmap.getHeight();
+ _displace = bitmap.getDisplace();
+ _transparentColor = bitmap.getSkipColor();
+ _scaledWidth = bitmap.getScaledWidth();
+ _scaledHeight = bitmap.getScaledHeight();
+ _hunkPaletteOffset = bitmap.getHunkPaletteOffset();
+ _remap = bitmap.getRemap();
+}
+
+CelObjMem *CelObjMem::duplicate() const {
+ return new CelObjMem(*this);
+}
+
+byte *CelObjMem::getResPointer() const {
+ return g_sci->getEngineState()->_segMan->getHunkPointer(_info.bitmap);
+}
+
+#pragma mark -
+#pragma mark CelObjColor
+CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 height) {
+ _info.type = kCelTypeColor;
+ _info.color = color;
+ _displace.x = 0;
+ _displace.y = 0;
+ _scaledWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ _scaledHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ _hunkPaletteOffset = 0;
+ _mirrorX = false;
+ _remap = false;
+ _width = width;
+ _height = height;
+}
+
+void CelObjColor::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX) {
+ // TODO: The original engine sets this flag but why? One cannot
+ // draw a solid color mirrored.
+ _drawMirrored = mirrorX;
+ draw(target, targetRect);
+}
+void CelObjColor::draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, bool mirrorX) {
+ error("Unsupported method");
+}
+void CelObjColor::draw(Buffer &target, const Common::Rect &targetRect) const {
+ target.fillRect(targetRect, _info.color);
+}
+
+CelObjColor *CelObjColor::duplicate() const {
+ return new CelObjColor(*this);
+}
+
+byte *CelObjColor::getResPointer() const {
+ error("Unsupported method");
+}
+} // End of namespace Sci
diff --git a/engines/sci/graphics/celobj32.h b/engines/sci/graphics/celobj32.h
new file mode 100644
index 0000000000..0bb4b03ae2
--- /dev/null
+++ b/engines/sci/graphics/celobj32.h
@@ -0,0 +1,581 @@
+/* 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 SCI_GRAPHICS_CELOBJ32_H
+#define SCI_GRAPHICS_CELOBJ32_H
+
+#include "common/rational.h"
+#include "common/rect.h"
+#include "sci/resource.h"
+#include "sci/engine/vm_types.h"
+
+namespace Sci {
+typedef Common::Rational Ratio;
+
+enum CelType {
+ kCelTypeView = 0,
+ kCelTypePic = 1,
+ kCelTypeMem = 2,
+ kCelTypeColor = 3
+};
+
+enum CelCompressionType {
+ kCelCompressionNone = 0,
+ kCelCompressionRLE = 138,
+ kCelCompressionInvalid = 1000
+};
+
+/**
+ * A CelInfo32 object describes the basic properties of a
+ * cel object.
+ */
+struct CelInfo32 {
+ /**
+ * The type of the cel object.
+ */
+ CelType type;
+
+ /**
+ * For cel objects that draw from resources, the ID of
+ * the resource to load.
+ */
+ GuiResourceId resourceId;
+
+ /**
+ * For CelObjView, the loop number to draw from the
+ * view resource.
+ */
+ int16 loopNo;
+
+ /**
+ * For CelObjView and CelObjPic, the cel number to draw
+ * from the view or pic resource.
+ */
+ int16 celNo;
+
+ /**
+ * For CelObjMem, a segment register pointing to a heap
+ * resource containing headered bitmap data.
+ */
+ reg_t bitmap;
+
+ /**
+ * For CelObjColor, the fill color.
+ */
+ uint8 color;
+
+ // NOTE: In at least SCI2.1/SQ6, color is left
+ // uninitialised.
+ CelInfo32() :
+ type(kCelTypeMem),
+ resourceId(0),
+ loopNo(0),
+ celNo(0),
+ bitmap(NULL_REG) {}
+
+ // NOTE: This is the equivalence criteria used by
+ // CelObj::searchCache in at least SCI2.1/SQ6. Notably,
+ // it does not check the color field.
+ inline bool operator==(const CelInfo32 &other) {
+ return (
+ type == other.type &&
+ resourceId == other.resourceId &&
+ loopNo == other.loopNo &&
+ celNo == other.celNo &&
+ bitmap == other.bitmap
+ );
+ }
+
+ inline bool operator!=(const CelInfo32 &other) {
+ return !(*this == other);
+ }
+};
+
+class CelObj;
+struct CelCacheEntry {
+ /**
+ * A monotonically increasing cache ID used to identify
+ * the least recently used item in the cache for
+ * replacement.
+ */
+ int id;
+ CelObj *celObj;
+ CelCacheEntry() : id(0), celObj(nullptr) {}
+};
+
+typedef Common::Array<CelCacheEntry> CelCache;
+
+#pragma mark -
+#pragma mark CelScaler
+
+struct CelScalerTable {
+ /**
+ * A lookup table of indexes that should be used to find
+ * the correct column to read from the source bitmap
+ * when drawing a scaled version of the source bitmap.
+ */
+ int valuesX[1024];
+
+ /**
+ * The ratio used to generate the x-values.
+ */
+ Ratio scaleX;
+
+ /**
+ * A lookup table of indexes that should be used to find
+ * the correct row to read from a source bitmap when
+ * drawing a scaled version of the source bitmap.
+ */
+ int valuesY[1024];
+
+ /**
+ * The ratio used to generate the y-values.
+ */
+ Ratio scaleY;
+};
+
+class CelScaler {
+ /**
+ * Cached scale tables.
+ */
+ CelScalerTable _scaleTables[2];
+
+ /**
+ * The index of the most recently used scale table.
+ */
+ int _activeIndex;
+
+ /**
+ * Activates a scale table for the given X and Y ratios.
+ * If there is no table that matches the given ratios,
+ * the least most recently used table will be replaced
+ * and activated.
+ */
+ void activateScaleTables(const Ratio &scaleX, const Ratio &scaleY);
+
+ /**
+ * Builds a pixel lookup table in `table` for the given
+ * ratio. The table will be filled up to the specified
+ * size, which should be large enough to draw across the
+ * entire target buffer.
+ */
+ void buildLookupTable(int *table, const Ratio &ratio, const int size);
+
+public:
+ CelScaler() :
+ _scaleTables(),
+ _activeIndex(0) {
+ CelScalerTable &table = _scaleTables[0];
+ table.scaleX = Ratio();
+ table.scaleY = Ratio();
+ for (int i = 0; i < ARRAYSIZE(table.valuesX); ++i) {
+ table.valuesX[i] = i;
+ table.valuesY[i] = i;
+ }
+ for (int i = 1; i < ARRAYSIZE(_scaleTables); ++i) {
+ _scaleTables[i] = _scaleTables[0];
+ }
+ }
+
+ /**
+ * Retrieves scaler tables for the given X and Y ratios.
+ */
+ const CelScalerTable *getScalerTable(const Ratio &scaleX, const Ratio &scaleY);
+};
+
+#pragma mark -
+#pragma mark CelObj
+
+class ScreenItem;
+/**
+ * A cel object is the lowest-level rendering primitive in
+ * the SCI engine and draws itself directly to a target
+ * pixel buffer.
+ */
+class CelObj {
+protected:
+ /**
+ * When true, this cel will be horizontally mirrored
+ * when it is drawn. This is an internal flag that is
+ * set by draw methods based on the combination of the
+ * cel's `_mirrorX` property and the owner screen item's
+ * `_mirrorX` property.
+ */
+ bool _drawMirrored;
+
+public:
+ static CelScaler *_scaler;
+
+ /**
+ * The basic identifying information for this cel. This
+ * information effectively acts as a composite key for
+ * a cel object, and any cel object can be recreated
+ * from this data alone.
+ */
+ CelInfo32 _info;
+
+ /**
+ * The offset to the cel header for this cel within the
+ * raw resource data.
+ */
+ uint32 _celHeaderOffset;
+
+ /**
+ * The offset to the embedded palette for this cel
+ * within the raw resource data.
+ */
+ uint32 _hunkPaletteOffset;
+
+ /**
+ * The natural dimensions of the cel.
+ */
+ uint16 _width, _height;
+
+ /**
+ * TODO: Documentation
+ */
+ Common::Point _displace;
+
+ /**
+ * The dimensions of the original coordinate system for
+ * the cel. Used to scale cels from their native size
+ * to the correct size on screen.
+ *
+ * @note This is set to scriptWidth/Height for
+ * CelObjColor. For other cel objects, the value comes
+ * from the raw resource data. For text bitmaps, this is
+ * the width/height of the coordinate system used to
+ * generate the text, which also defaults to
+ * scriptWidth/Height but seems to typically be changed
+ * to more closely match the native screen resolution.
+ */
+ uint16 _scaledWidth, _scaledHeight;
+
+ /**
+ * The skip (transparent) color for the cel. When
+ * compositing, any pixels matching this color will not
+ * be copied to the buffer.
+ */
+ uint8 _transparentColor;
+
+ /**
+ * Whether or not this cel has any transparent regions.
+ * This is used for optimised drawing of non-transparent
+ * cels.
+ */
+ bool _transparent; // TODO: probably "skip"?
+
+ /**
+ * The compression type for the pixel data for this cel.
+ */
+ CelCompressionType _compressionType;
+
+ /**
+ * Whether or not this cel should be palette-remapped?
+ */
+ bool _remap;
+
+ /**
+ * If true, the cel contains pre-mirrored picture data.
+ * This value comes directly from the resource data and
+ * is XORed with the `_mirrorX` property of the owner
+ * screen item when rendering.
+ */
+ bool _mirrorX;
+
+ /**
+ * Initialises static CelObj members.
+ */
+ static void init();
+
+ /**
+ * Frees static CelObj members.
+ */
+ static void deinit();
+
+ virtual ~CelObj() {};
+
+ /**
+ * Draws the cel to the target buffer using the priority
+ * and positioning information from the given screen
+ * item. The mirroring of the cel will be unchanged from
+ * any previous call to draw.
+ */
+ void draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect) const;
+
+ /**
+ * Draws the cel to the target buffer using the priority
+ * and positioning information from the given screen
+ * item and the given mirror flag.
+ *
+ * @note In SCI engine, this function was a virtual
+ * function, but CelObjView, CelObjPic, and CelObjMem
+ * all used the same function and the compiler
+ * deduplicated the copies; we deduplicate the source by
+ * putting the implementation on CelObj instead of
+ * copying it to 3/4 of the subclasses.
+ */
+ virtual void draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX);
+
+ /**
+ * Draws the cel to the target buffer using the
+ * positioning and mirroring information from the
+ * provided arguments.
+ *
+ * @note In SCI engine, this function was a virtual
+ * function, but CelObjView, CelObjPic, and CelObjMem
+ * all used the same function and the compiler
+ * deduplicated the copies; we deduplicate the source by
+ * putting the implementation on CelObj instead of
+ * copying it to 3/4 of the subclasses.
+ */
+ virtual void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX);
+
+ /**
+ * Draws the cel to the target buffer using the given
+ * position and scaling parameters. The mirroring of the
+ * cel will be unchanged from any previous call to draw.
+ */
+ void drawTo(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const;
+
+ /**
+ * Creates a copy of this cel on the free store and
+ * returns a pointer to the new object. The new cel will
+ * point to a shared copy of bitmap/resource data.
+ */
+ virtual CelObj *duplicate() const = 0;
+
+ /**
+ * Retrieves a pointer to the raw resource data for this
+ * cel. This method cannot be used with a CelObjColor.
+ */
+ virtual byte *getResPointer() const = 0;
+
+ /**
+ * Reads the pixel at the given coordinates. This method
+ * is valid only for CelObjView and CelObjPic.
+ */
+ virtual uint8 readPixel(uint16 x, uint16 y, bool mirrorX) const;
+
+ /**
+ * Submits the palette from this cel to the palette
+ * manager for integration into the master screen
+ * palette.
+ */
+ void submitPalette() const;
+
+#pragma mark -
+#pragma mark CelObj - Drawing
+private:
+ template<typename MAPPER, typename SCALER>
+ void render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+
+ template<typename MAPPER, typename SCALER>
+ void render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const;
+
+ void drawHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompNoFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDraw(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDrawUncomp(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+
+ void drawHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawNoFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompNoFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDrawMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDrawUncompMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ // NOTE: The original includes versions of the above functions with priority parameters, which were not actually used in SCI32
+
+ void drawHzFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompNoFlipNoMDNoSkip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompHzFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void drawUncompHzFlipNoMDNoSkip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ void scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
+ // NOTE: The original includes versions of the above functions with priority parameters, which were not actually used in SCI32
+
+#pragma mark -
+#pragma mark CelObj - Caching
+protected:
+ /**
+ * A monotonically increasing cache ID used to identify
+ * the least recently used item in the cache for
+ * replacement.
+ */
+ static int _nextCacheId;
+
+ /**
+ * A cache of cel objects used to avoid reinitialisation
+ * overhead for cels with the same CelInfo32.
+ */
+ // NOTE: At least SQ6 uses a fixed cache size of 100.
+ static CelCache *_cache;
+
+ /**
+ * Searches the cel cache for a CelObj matching the
+ * provided CelInfo32. If not found, -1 is returned.
+ * nextInsertIndex will receive the index of the oldest
+ * item in the cache, which can be used to replace
+ * the oldest item with a newer item.
+ */
+ int searchCache(const CelInfo32 &celInfo, int *nextInsertIndex) const;
+
+ /**
+ * Puts a copy of this CelObj into the cache at the
+ * given cache index.
+ */
+ void putCopyInCache(int index) const;
+};
+
+#pragma mark -
+#pragma mark CelObjView
+
+/**
+ * A CelObjView is the drawing primitive for a View type
+ * resource. Each CelObjView corresponds to a single cel
+ * within a single loop of a view.
+ */
+class CelObjView : public CelObj {
+private:
+ /**
+ * Analyses resources without baked-in remap flags
+ * to determine whether or not they should be remapped.
+ */
+ bool analyzeUncompressedForRemap() const;
+
+ /**
+ * Analyses compressed resources without baked-in remap
+ * flags to determine whether or not they should be
+ * remapped.
+ */
+ bool analyzeForRemap() const;
+
+public:
+ CelObjView(GuiResourceId viewId, int16 loopNo, int16 celNo);
+ virtual ~CelObjView() override {};
+
+ using CelObj::draw;
+
+ /**
+ * Draws the cel to the target buffer using the
+ * positioning, mirroring, and scaling information from
+ * the provided arguments.
+ */
+ void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, bool mirrorX, const Ratio &scaleX, const Ratio &scaleY);
+
+ virtual CelObjView *duplicate() const override;
+ virtual byte *getResPointer() const override;
+};
+
+#pragma mark -
+#pragma mark CelObjPic
+
+/**
+ * A CelObjPic is the drawing primitive for a Picture type
+ * resource. Each CelObjPic corresponds to a single cel
+ * within a picture.
+ */
+class CelObjPic : public CelObj {
+private:
+ /**
+ * Analyses uncompressed resources without baked-in skip
+ * flags to determine whether or not they can use fast
+ * blitting.
+ */
+ bool analyzeUncompressedForSkip() const;
+
+public:
+ /**
+ * The number of cels in the original picture resource.
+ */
+ uint8 _celCount;
+
+ /**
+ * The position of this cel relative to the top-left
+ * corner of the picture.
+ */
+ Common::Point _relativePosition;
+
+ /**
+ * The z-buffer priority for this cel. Higher prorities
+ * are drawn on top of lower priorities.
+ */
+ int16 _priority;
+
+ CelObjPic(GuiResourceId pictureId, int16 celNo);
+ virtual ~CelObjPic() override {};
+
+ using CelObj::draw;
+ virtual void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX) override;
+
+ virtual CelObjPic *duplicate() const override;
+ virtual byte *getResPointer() const override;
+};
+
+#pragma mark -
+#pragma mark CelObjMem
+
+/**
+ * A CelObjMem is the drawing primitive for arbitrary
+ * bitmaps generated in memory. Generated bitmaps in SCI32
+ * include text & vector drawings and per-pixel screen
+ * transitions like dissolves.
+ */
+class CelObjMem : public CelObj {
+public:
+ CelObjMem(reg_t bitmap);
+ virtual ~CelObjMem() override {};
+
+ virtual CelObjMem *duplicate() const override;
+ virtual byte *getResPointer() const override;
+};
+
+#pragma mark -
+#pragma mark CelObjColor
+
+/**
+ * A CelObjColor is the drawing primitive for fast,
+ * low-memory, flat color fills.
+ */
+class CelObjColor : public CelObj {
+public:
+ CelObjColor(uint8 color, int16 width, int16 height);
+ virtual ~CelObjColor() override {};
+
+ using CelObj::draw;
+ /**
+ * Block fills the target buffer with the cel color.
+ */
+ void draw(Buffer &target, const Common::Rect &targetRect) const;
+ virtual void draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX) override;
+ virtual void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX) override;
+
+ virtual CelObjColor *duplicate() const override;
+ virtual byte *getResPointer() const override;
+};
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp
index 716a366b7c..729eeeaf81 100644
--- a/engines/sci/graphics/compare.cpp
+++ b/engines/sci/graphics/compare.cpp
@@ -67,7 +67,7 @@ uint16 GfxCompare::isOnControl(uint16 screenMask, const Common::Rect &rect) {
return result;
}
-reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list) {
+reg_t GfxCompare::canBeHereCheckRectList(const reg_t checkObject, const Common::Rect &checkRect, const List *list, const uint16 signalFlags) const {
reg_t curAddress = list->first;
Node *curNode = _segMan->lookupNode(curAddress);
reg_t curObject;
@@ -78,7 +78,7 @@ reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect &
curObject = curNode->value;
if (curObject != checkObject) {
signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
- if (!(signal & (kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate))) {
+ if (!(signal & signalFlags)) {
curRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
curRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
@@ -112,11 +112,6 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
GfxView *view = NULL;
Common::Rect celRect(0, 0);
GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view));
-
- // HACK: Ignore invalid views for now (perhaps unimplemented text views?)
- if (viewId == 0xFFFF) // invalid view
- return;
-
int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop));
int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel));
int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x));
@@ -126,26 +121,8 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z));
view = _cache->getView(viewId);
-
-#ifdef ENABLE_SCI32
- if (view->isSci2Hires())
- view->adjustToUpscaledCoordinates(y, x);
- else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE))
- _coordAdjuster->fromScriptToDisplay(y, x);
-#endif
-
view->getCelRect(loopNo, celNo, x, y, z, celRect);
-#ifdef ENABLE_SCI32
- if (view->isSci2Hires()) {
- view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
- view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
- } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) {
- _coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
- _coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
- }
-#endif
-
if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) {
setNSRect(objectReference, celRect);
}
@@ -153,32 +130,57 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
reg_t GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
Common::Rect checkRect;
- Common::Rect adjustedRect;
- uint16 signal, controlMask;
uint16 result;
checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
+ uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
if (!checkRect.isValidRect()) { // can occur in Iceman and Mother Goose - HACK? TODO: is this really occuring in sierra sci? check this
warning("kCan(t)BeHere - invalid rect %d, %d -> %d, %d", checkRect.left, checkRect.top, checkRect.right, checkRect.bottom);
return NULL_REG; // this means "can be here"
}
- adjustedRect = _coordAdjuster->onControl(checkRect);
-
- signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
- controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
+ Common::Rect adjustedRect = _coordAdjuster->onControl(checkRect);
+ uint16 controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
result = isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask;
if ((!result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
List *list = _segMan->lookupList(listReference);
if (!list)
error("kCanBeHere called with non-list as parameter");
- return canBeHereCheckRectList(curObject, checkRect, list);
+ return canBeHereCheckRectList(curObject, checkRect, list, kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate);
}
+
+ return make_reg(0, result);
+}
+
+reg_t GfxCompare::kernelCantBeHere32(const reg_t curObject, const reg_t listReference) const {
+ // Most of SCI32 graphics code converts rects from the VM to exclusive
+ // rects before operating on them, but this call leverages SCI16 engine
+ // code that operates on inclusive rects, so the rect's bottom-right
+ // point is not modified like in other SCI32 kernel calls
+ Common::Rect checkRect(
+ readSelectorValue(_segMan, curObject, SELECTOR(brLeft)),
+ readSelectorValue(_segMan, curObject, SELECTOR(brTop)),
+ readSelectorValue(_segMan, curObject, SELECTOR(brRight)),
+ readSelectorValue(_segMan, curObject, SELECTOR(brBottom))
+ );
+
+ uint16 result = 0;
+ uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
+ const uint16 signalFlags = kSignalIgnoreActor | kSignalHidden;
+
+ if ((signal & signalFlags) == 0) {
+ List *list = _segMan->lookupList(listReference);
+ if (!list) {
+ error("kCantBeHere called with non-list as parameter");
+ }
+ result = !canBeHereCheckRectList(curObject, checkRect, list, signalFlags).isNull();
+ }
+
return make_reg(0, result);
}
@@ -201,15 +203,9 @@ void GfxCompare::kernelBaseSetter(reg_t object) {
GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view));
int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel));
-
- // HACK: Ignore invalid views for now (perhaps unimplemented text views?)
- if (viewId == 0xFFFF) // invalid view
- return;
-
uint16 scaleSignal = 0;
- if (getSciVersion() >= SCI_VERSION_1_1) {
+ if (getSciVersion() >= SCI_VERSION_1_1)
scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));
- }
Common::Rect celRect;
diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h
index 88b44aeeb1..c7005980d0 100644
--- a/engines/sci/graphics/compare.h
+++ b/engines/sci/graphics/compare.h
@@ -40,6 +40,7 @@ public:
uint16 kernelOnControl(byte screenMask, const Common::Rect &rect);
void kernelSetNowSeen(reg_t objectReference);
reg_t kernelCanBeHere(reg_t curObject, reg_t listReference);
+ reg_t kernelCantBeHere32(const reg_t curObject, const reg_t listReference) const;
bool kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position);
void kernelBaseSetter(reg_t object);
Common::Rect getNSRect(reg_t object);
@@ -58,7 +59,7 @@ private:
* *different* from checkObject, has a brRect which is contained inside
* checkRect.
*/
- reg_t canBeHereCheckRectList(reg_t checkObject, const Common::Rect &checkRect, List *list);
+ reg_t canBeHereCheckRectList(const reg_t checkObject, const Common::Rect &checkRect, const List *list, const uint16 signalFlags) const;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp
index e2e250cf9d..b4bd92699a 100644
--- a/engines/sci/graphics/controls16.cpp
+++ b/engines/sci/graphics/controls16.cpp
@@ -151,7 +151,7 @@ void GfxControls16::kernelTexteditChange(reg_t controlObject, reg_t eventObject)
Common::Rect rect;
if (textReference.isNull())
- error("kEditControl called on object that doesnt have a text reference");
+ error("kEditControl called on object that doesn't have a text reference");
text = _segMan->getString(textReference);
uint16 oldCursorPos = cursorPos;
diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp
index 1bd497ce98..a877d8c276 100644
--- a/engines/sci/graphics/controls32.cpp
+++ b/engines/sci/graphics/controls32.cpp
@@ -23,9 +23,11 @@
#include "common/system.h"
#include "sci/sci.h"
+#include "sci/console.h"
#include "sci/event.h"
#include "sci/engine/kernel.h"
#include "sci/engine/seg_manager.h"
+#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/controls32.h"
@@ -34,171 +36,321 @@
#include "sci/graphics/text32.h"
namespace Sci {
+GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text) :
+ _segMan(segMan),
+ _gfxCache(cache),
+ _gfxText32(text),
+ _overwriteMode(false),
+ _nextCursorFlashTick(0) {}
-GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text)
- : _segMan(segMan), _cache(cache), _text(text) {
-}
+reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
+ SegManager *segMan = _segMan;
-GfxControls32::~GfxControls32() {
-}
+ TextEditor editor;
+ reg_t textObject = readSelector(_segMan, controlObject, SELECTOR(text));
+ editor.text = _segMan->getString(textObject);
+ editor.foreColor = readSelectorValue(_segMan, controlObject, SELECTOR(fore));
+ editor.backColor = readSelectorValue(_segMan, controlObject, SELECTOR(back));
+ editor.skipColor = readSelectorValue(_segMan, controlObject, SELECTOR(skip));
+ editor.fontId = readSelectorValue(_segMan, controlObject, SELECTOR(font));
+ editor.maxLength = readSelectorValue(_segMan, controlObject, SELECTOR(width));
+ editor.bitmap = readSelector(_segMan, controlObject, SELECTOR(bitmap));
+ editor.cursorCharPosition = 0;
+ editor.cursorIsDrawn = false;
+ editor.borderColor = readSelectorValue(_segMan, controlObject, SELECTOR(borderColor));
-void GfxControls32::kernelTexteditChange(reg_t controlObject) {
- SciEvent curEvent;
- uint16 maxChars = 40; //readSelectorValue(_segMan, controlObject, SELECTOR(max)); // TODO
- reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text));
- GfxFont *font = _cache->getFont(readSelectorValue(_segMan, controlObject, SELECTOR(font)));
- Common::String text;
- uint16 textSize;
- bool textChanged = false;
- bool textAddChar = false;
- Common::Rect rect;
+ reg_t titleObject = readSelector(_segMan, controlObject, SELECTOR(title));
+
+ int16 titleHeight = 0;
+ GuiResourceId titleFontId = readSelectorValue(_segMan, controlObject, SELECTOR(titleFont));
+ if (!titleObject.isNull()) {
+ GfxFont *titleFont = _gfxCache->getFont(titleFontId);
+ titleHeight += _gfxText32->scaleUpHeight(titleFont->getHeight()) + 1;
+ if (editor.borderColor != -1) {
+ titleHeight += 2;
+ }
+ }
- if (textReference.isNull())
- error("kEditControl called on object that doesnt have a text reference");
- text = _segMan->getString(textReference);
+ int16 width = 0;
+ int16 height = titleHeight;
- // TODO: Finish this
- warning("kEditText ('%s')", text.c_str());
- return;
+ GfxFont *editorFont = _gfxCache->getFont(editor.fontId);
+ height += _gfxText32->scaleUpHeight(editorFont->getHeight()) + 1;
+ _gfxText32->setFont(editor.fontId);
+ int16 emSize = _gfxText32->getCharWidth('M', true);
+ width += editor.maxLength * emSize + 1;
+ if (editor.borderColor != -1) {
+ width += 4;
+ height += 2;
+ }
- uint16 cursorPos = 0;
- //uint16 oldCursorPos = cursorPos;
- bool captureEvents = true;
- EventManager* eventMan = g_sci->getEventManager();
+ Common::Rect editorPlaneRect(width, height);
+ editorPlaneRect.translate(readSelectorValue(_segMan, controlObject, SELECTOR(x)), readSelectorValue(_segMan, controlObject, SELECTOR(y)));
- while (captureEvents) {
- curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK);
+ reg_t planeObj = readSelector(_segMan, controlObject, SELECTOR(plane));
+ Plane *sourcePlane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(planeObj);
+ if (sourcePlane == nullptr) {
+ error("Could not find plane %04x:%04x", PRINT_REG(planeObj));
+ }
+ editorPlaneRect.translate(sourcePlane->_gameRect.left, sourcePlane->_gameRect.top);
- if (curEvent.type == SCI_EVENT_NONE) {
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
+ editor.textRect = Common::Rect(2, titleHeight + 2, width - 1, height - 1);
+ editor.width = width;
+
+ if (editor.bitmap.isNull()) {
+ TextAlign alignment = (TextAlign)readSelectorValue(_segMan, controlObject, SELECTOR(mode));
+
+ if (titleObject.isNull()) {
+ bool dimmed = readSelectorValue(_segMan, controlObject, SELECTOR(dimmed));
+ editor.bitmap = _gfxText32->createFontBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, dimmed, true);
} else {
- textSize = text.size();
+ Common::String title = _segMan->getString(titleObject);
+ int16 titleBackColor = readSelectorValue(_segMan, controlObject, SELECTOR(titleBack));
+ int16 titleForeColor = readSelectorValue(_segMan, controlObject, SELECTOR(titleFore));
+ editor.bitmap = _gfxText32->createTitledBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, title, titleForeColor, titleBackColor, titleFontId, true);
+ }
+ }
+
+ drawCursor(editor);
- switch (curEvent.type) {
- case SCI_EVENT_MOUSE_PRESS:
- // TODO: Implement mouse support for cursor change
+ Plane *plane = new Plane(editorPlaneRect, kPlanePicTransparent);
+ plane->changePic();
+ g_sci->_gfxFrameout->addPlane(*plane);
+
+ CelInfo32 celInfo;
+ celInfo.type = kCelTypeMem;
+ celInfo.bitmap = editor.bitmap;
+
+ ScreenItem *screenItem = new ScreenItem(plane->_object, celInfo, Common::Point(), ScaleInfo());
+ plane->_screenItemList.add(screenItem);
+
+ // frameOut must be called after the screen item is
+ // created, and before it is updated at the end of the
+ // event loop, otherwise it has both created and updated
+ // flags set which crashes the engine (it runs updates
+ // before creations)
+ g_sci->_gfxFrameout->frameOut(true);
+
+ EventManager *eventManager = g_sci->getEventManager();
+ bool clearTextOnInput = true;
+ bool textChanged = false;
+ for (;;) {
+ // We peek here because the last event needs to be allowed to
+ // dispatch a second time to the normal event handling system.
+ // In the actual engine, the event is always consumed and then
+ // the last event just gets posted back to the event manager for
+ // reprocessing, but instead, we only remove the event from the
+ // queue *after* we have determined it is not a defocusing event
+ const SciEvent event = eventManager->getSciEvent(SCI_EVENT_ANY | SCI_EVENT_PEEK);
+
+ bool focused = true;
+ // Original engine did not have a QUIT event but we have to handle it
+ if (event.type == SCI_EVENT_QUIT) {
+ focused = false;
+ break;
+ } else if (event.type == SCI_EVENT_MOUSE_PRESS && !editorPlaneRect.contains(event.mousePosSci)) {
+ focused = false;
+ } else if (event.type == SCI_EVENT_KEYBOARD) {
+ switch (event.character) {
+ case SCI_KEY_ESC:
+ case SCI_KEY_UP:
+ case SCI_KEY_DOWN:
+ case SCI_KEY_TAB:
+ case SCI_KEY_SHIFT_TAB:
+ case SCI_KEY_ENTER:
+ focused = false;
break;
- case SCI_EVENT_KEYBOARD:
- switch (curEvent.character) {
- case SCI_KEY_BACKSPACE:
- if (cursorPos > 0) {
- cursorPos--; text.deleteChar(cursorPos);
- textChanged = true;
- }
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_DELETE:
- if (cursorPos < textSize) {
- text.deleteChar(cursorPos);
- textChanged = true;
- }
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_HOME: // HOME
- cursorPos = 0; textChanged = true;
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_END: // END
- cursorPos = textSize; textChanged = true;
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_LEFT: // LEFT
- if (cursorPos > 0) {
- cursorPos--; textChanged = true;
- }
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_RIGHT: // RIGHT
- if (cursorPos + 1 <= textSize) {
- cursorPos++; textChanged = true;
- }
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case 3: // returned in SCI1 late and newer when Control - C is pressed
- if (curEvent.modifiers & SCI_KEYMOD_CTRL) {
- // Control-C erases the whole line
- cursorPos = 0; text.clear();
- textChanged = true;
+ }
+ }
+
+ if (!focused) {
+ break;
+ }
+
+ // Consume the event now that we know it is not one of the
+ // defocusing events above
+ eventManager->getSciEvent(SCI_EVENT_ANY);
+
+ // NOTE: In the original engine, the font and bitmap were
+ // reset here on each iteration through the loop, but it
+ // doesn't seem like this should be necessary since
+ // control is not yielded back to the VM until input is
+ // received, which means there is nothing that could modify
+ // the GfxText32's state with a different font in the
+ // meantime
+
+ bool shouldDeleteChar = false;
+ bool shouldRedrawText = false;
+ uint16 lastCursorPosition = editor.cursorCharPosition;
+ if (event.type == SCI_EVENT_KEYBOARD) {
+ switch (event.character) {
+ case SCI_KEY_LEFT:
+ clearTextOnInput = false;
+ if (editor.cursorCharPosition > 0) {
+ --editor.cursorCharPosition;
+ }
+ break;
+
+ case SCI_KEY_RIGHT:
+ clearTextOnInput = false;
+ if (editor.cursorCharPosition < editor.text.size()) {
+ ++editor.cursorCharPosition;
+ }
+ break;
+
+ case SCI_KEY_HOME:
+ clearTextOnInput = false;
+ editor.cursorCharPosition = 0;
+ break;
+
+ case SCI_KEY_END:
+ clearTextOnInput = false;
+ editor.cursorCharPosition = editor.text.size();
+ break;
+
+ case SCI_KEY_INSERT:
+ clearTextOnInput = false;
+ // Redrawing also changes the cursor rect to
+ // reflect the new insertion mode
+ shouldRedrawText = true;
+ _overwriteMode = !_overwriteMode;
+ break;
+
+ case SCI_KEY_DELETE:
+ clearTextOnInput = false;
+ if (editor.cursorCharPosition < editor.text.size()) {
+ shouldDeleteChar = true;
+ }
+ break;
+
+ case SCI_KEY_BACKSPACE:
+ clearTextOnInput = false;
+ shouldDeleteChar = true;
+ if (editor.cursorCharPosition > 0) {
+ --editor.cursorCharPosition;
+ }
+ break;
+
+ case SCI_KEY_ETX:
+ editor.text.clear();
+ editor.cursorCharPosition = 0;
+ shouldRedrawText = true;
+ break;
+
+ default: {
+ if (event.character >= 20 && event.character < 257) {
+ if (clearTextOnInput) {
+ clearTextOnInput = false;
+ editor.text.clear();
}
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
- case SCI_KEY_UP:
- case SCI_KEY_DOWN:
- case SCI_KEY_ENTER:
- case SCI_KEY_ESC:
- case SCI_KEY_TAB:
- case SCI_KEY_SHIFT_TAB:
- captureEvents = false;
- break;
- default:
- if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.character == 'c') {
- // Control-C in earlier SCI games (SCI0 - SCI1 middle)
- // Control-C erases the whole line
- cursorPos = 0; text.clear();
- textChanged = true;
- } else if (curEvent.character > 31 && curEvent.character < 256 && textSize < maxChars) {
- // insert pressed character
- textAddChar = true;
- textChanged = true;
+
+ if (
+ (_overwriteMode && editor.cursorCharPosition < editor.maxLength) ||
+ (editor.text.size() < editor.maxLength && _gfxText32->getCharWidth(event.character, true) + _gfxText32->getStringWidth(editor.text) < editor.textRect.width())
+ ) {
+ if (_overwriteMode && editor.cursorCharPosition < editor.text.size()) {
+ editor.text.setChar(event.character, editor.cursorCharPosition);
+ } else {
+ editor.text.insertChar(event.character, editor.cursorCharPosition);
+ }
+
+ ++editor.cursorCharPosition;
+ shouldRedrawText = true;
}
- eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
- break;
}
- break;
+ }
}
}
- if (textChanged) {
- rect = g_sci->_gfxCompare->getNSRect(controlObject);
+ if (shouldDeleteChar) {
+ shouldRedrawText = true;
+ if (editor.cursorCharPosition < editor.text.size()) {
+ editor.text.deleteChar(editor.cursorCharPosition);
+ }
+ }
- if (textAddChar) {
- const char *textPtr = text.c_str();
+ if (shouldRedrawText) {
+ eraseCursor(editor);
+ _gfxText32->erase(editor.textRect, true);
+ _gfxText32->drawTextBox(editor.text);
+ drawCursor(editor);
+ textChanged = true;
+ screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
+ } else if (editor.cursorCharPosition != lastCursorPosition) {
+ eraseCursor(editor);
+ drawCursor(editor);
+ screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
+ } else {
+ flashCursor(editor);
+ screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
+ }
- // We check if we are really able to add the new char
- uint16 textWidth = 0;
- while (*textPtr)
- textWidth += font->getCharWidth((byte)*textPtr++);
- textWidth += font->getCharWidth(curEvent.character);
+ g_sci->_gfxFrameout->frameOut(true);
+ g_sci->getSciDebugger()->onFrame();
+ g_sci->getEngineState()->speedThrottler(16);
+ g_sci->getEngineState()->_throttleTrigger = true;
+ }
- // Does it fit?
- if (textWidth >= rect.width()) {
- return;
- }
+ g_sci->_gfxFrameout->deletePlane(*plane);
+ if (readSelectorValue(segMan, controlObject, SELECTOR(frameOut))) {
+ g_sci->_gfxFrameout->frameOut(true);
+ }
- text.insertChar(curEvent.character, cursorPos++);
+ _segMan->freeHunkEntry(editor.bitmap);
- // Note: the following checkAltInput call might make the text
- // too wide to fit, but SSCI fails to check that too.
- }
+ if (textChanged) {
+ editor.text.trim();
+ SciString *string = _segMan->lookupString(textObject);
+ string->fromString(editor.text);
+ }
+
+ return make_reg(0, textChanged);
+}
- reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap));
- Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject);
- //texteditCursorErase(); // TODO: Cursor
+void GfxControls32::drawCursor(TextEditor &editor) {
+ if (!editor.cursorIsDrawn) {
+ editor.cursorRect.left = editor.textRect.left + _gfxText32->getTextWidth(editor.text, 0, editor.cursorCharPosition);
- // Write back string
- _segMan->strcpy(textReference, text.c_str());
- // Modify the buffer and show it
- _text->createTextBitmap(controlObject, 0, 0, hunkId);
+ const int16 scaledFontHeight = _gfxText32->scaleUpHeight(_gfxText32->_font->getHeight());
- _text->drawTextBitmap(0, 0, nsRect, controlObject);
- //texteditCursorDraw(rect, text.c_str(), cursorPos); // TODO: Cursor
- g_system->updateScreen();
+ // NOTE: The original code branched on borderColor here but
+ // the two branches appeared to be identical, differing only
+ // because the compiler decided to be differently clever
+ // when optimising multiplication in each branch
+ if (_overwriteMode) {
+ editor.cursorRect.top = editor.textRect.top;
+ editor.cursorRect.setHeight(scaledFontHeight);
} else {
- // TODO: Cursor
- /*
- if (g_system->getMillis() >= _texteditBlinkTime) {
- _paint16->invertRect(_texteditCursorRect);
- _paint16->bitsShow(_texteditCursorRect);
- _texteditCursorVisible = !_texteditCursorVisible;
- texteditSetBlinkTime();
- }
- */
+ editor.cursorRect.top = editor.textRect.top + scaledFontHeight - 1;
+ editor.cursorRect.setHeight(1);
}
- textAddChar = false;
- textChanged = false;
- g_sci->sleep(10);
- } // while
+ const char currentChar = editor.cursorCharPosition < editor.text.size() ? editor.text[editor.cursorCharPosition] : ' ';
+ editor.cursorRect.setWidth(_gfxText32->getCharWidth(currentChar, true));
+
+ _gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true);
+
+ editor.cursorIsDrawn = true;
+ }
+
+ _nextCursorFlashTick = g_sci->getTickCount() + 30;
+}
+
+void GfxControls32::eraseCursor(TextEditor &editor) {
+ if (editor.cursorIsDrawn) {
+ _gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true);
+ editor.cursorIsDrawn = false;
+ }
+
+ _nextCursorFlashTick = g_sci->getTickCount() + 30;
}
+void GfxControls32::flashCursor(TextEditor &editor) {
+ if (g_sci->getTickCount() > _nextCursorFlashTick) {
+ _gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true);
+
+ editor.cursorIsDrawn = !editor.cursorIsDrawn;
+ _nextCursorFlashTick = g_sci->getTickCount() + 30;
+ }
+}
} // End of namespace Sci
diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h
index 5af7c20f16..1bb7679ddd 100644
--- a/engines/sci/graphics/controls32.h
+++ b/engines/sci/graphics/controls32.h
@@ -29,20 +29,95 @@ class GfxCache;
class GfxScreen;
class GfxText32;
+struct TextEditor {
+ /**
+ * The bitmap where the editor is rendered.
+ */
+ reg_t bitmap;
+
+ /**
+ * The width of the editor, in bitmap pixels.
+ */
+ int16 width;
+
+ /**
+ * The text in the editor.
+ */
+ Common::String text;
+
+ /**
+ * The rect where text should be drawn into the editor,
+ * in bitmap pixels.
+ */
+ Common::Rect textRect;
+
+ /**
+ * The color of the border. -1 indicates no border.
+ */
+ int16 borderColor;
+
+ /**
+ * The text color.
+ */
+ uint8 foreColor;
+
+ /**
+ * The background color.
+ */
+ uint8 backColor;
+
+ /**
+ * The transparent color.
+ */
+ uint8 skipColor;
+
+ /**
+ * The font used to render the text in the editor.
+ */
+ GuiResourceId fontId;
+
+ /**
+ * The current position of the cursor within the editor.
+ */
+ uint16 cursorCharPosition;
+
+ /**
+ * Whether or not the cursor is currently drawn to the
+ * screen.
+ */
+ bool cursorIsDrawn;
+
+ /**
+ * The rectangle for drawing the input cursor, in bitmap
+ * pixels.
+ */
+ Common::Rect cursorRect;
+
+ /**
+ * The maximum allowed text length, in characters.
+ */
+ uint16 maxLength;
+};
+
/**
* Controls class, handles drawing of controls in SCI32 (SCI2, SCI2.1, SCI3) games
*/
class GfxControls32 {
public:
GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text);
- ~GfxControls32();
- void kernelTexteditChange(reg_t controlObject);
+ reg_t kernelEditText(const reg_t controlObject);
private:
SegManager *_segMan;
- GfxCache *_cache;
- GfxText32 *_text;
+ GfxCache *_gfxCache;
+ GfxText32 *_gfxText32;
+
+ bool _overwriteMode;
+ uint32 _nextCursorFlashTick;
+ void drawCursor(TextEditor &editor);
+ void eraseCursor(TextEditor &editor);
+ void flashCursor(TextEditor &editor);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 1a58de073c..f5dd473959 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -336,6 +336,9 @@ void GfxCursor::setPosition(Common::Point pos) {
&& ((workaround->newPositionX == pos.x) && (workaround->newPositionY == pos.y))) {
EngineState *s = g_sci->getEngineState();
s->_cursorWorkaroundActive = true;
+ // At least on OpenPandora it seems that the cursor is actually set, but a bit afterwards
+ // touch screen controls will overwrite the position. More information see kGetEvent in kevent.cpp.
+ s->_cursorWorkaroundPosCount = 5; // should be enough for OpenPandora
s->_cursorWorkaroundPoint = pos;
s->_cursorWorkaroundRect = Common::Rect(workaround->rectLeft, workaround->rectTop, workaround->rectRight, workaround->rectBottom);
return;
@@ -453,6 +456,15 @@ void GfxCursor::kernelClearZoomZone() {
void GfxCursor::kernelSetZoomZone(byte multiplier, Common::Rect zone, GuiResourceId viewNum, int loopNum, int celNum, GuiResourceId picNum, byte zoomColor) {
kernelClearZoomZone();
+ // This function is a stub in the Mac version of Freddy Pharkas.
+ // This function was only used in two games (LB2 and Pharkas), but there
+ // was no version of LB2 for the Macintosh platform.
+ // CHECKME: This wasn't verified against disassembly, one might want
+ // to check against it, in case there's some leftover code in the stubbed
+ // function (although it does seem that this was completely removed).
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh)
+ return;
+
_zoomMultiplier = multiplier;
if (_zoomMultiplier != 1 && _zoomMultiplier != 2 && _zoomMultiplier != 4)
diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h
index c2d7998eb3..8d125c45b3 100644
--- a/engines/sci/graphics/cursor.h
+++ b/engines/sci/graphics/cursor.h
@@ -77,8 +77,18 @@ public:
*/
void kernelSetMoveZone(Common::Rect zone);
- void kernelClearZoomZone();
+ /**
+ * Creates a dynamic zoom cursor, that is used to zoom on specific parts of the screen,
+ * using a separate larger picture. This was only used by two SCI1.1 games, Laura Bow 2
+ * (for examining the glyphs), and Freddy Pharkas (for examining the prescription with
+ * the whisky glass).
+ *
+ * In the Mac version of Freddy Pharkas, this was removed completely, and the scene has
+ * been redesigned to work without this functionality. There was no version of LB2 for
+ * the Macintosh platform.
+ */
void kernelSetZoomZone(byte multiplier, Common::Rect zone, GuiResourceId viewNum, int loopNum, int celNum, GuiResourceId picNum, byte zoomColor);
+ void kernelClearZoomZone();
void kernelSetPos(Common::Point pos);
void kernelMoveCursor(Common::Point pos);
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index cb81fe8d61..6454a1eb32 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -21,6 +21,7 @@
*/
#include "common/algorithm.h"
+#include "common/config-manager.h"
#include "common/events.h"
#include "common/keyboard.h"
#include "common/list.h"
@@ -46,964 +47,1484 @@
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
#include "sci/graphics/picture.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/text32.h"
+#include "sci/graphics/plane32.h"
+#include "sci/graphics/screen_item32.h"
#include "sci/graphics/frameout.h"
#include "sci/video/robot_decoder.h"
namespace Sci {
-// TODO/FIXME: This is all guesswork
-
-enum SciSpeciaPlanelPictureCodes {
- kPlaneTranslucent = 0xfffe, // -2
- kPlanePlainColored = 0xffff // -1
+static int dissolveSequences[2][20] = {
+ /* SCI2.1early- */ { 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080 },
+ /* SCI2.1mid+ */ { 0, 0, 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080, 73728, 132096, 466944 }
+};
+static int16 divisionsDefaults[2][16] = {
+ /* SCI2.1early- */ { 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40, 40, 101, 101 },
+ /* SCI2.1mid+ */ { 1, 20, 20, 20, 20, 10, 10, 10, 10, 20, 20, 6, 10, 101, 101, 2 }
+};
+static int16 unknownCDefaults[2][16] = {
+ /* SCI2.1early- */ { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 0 },
+ /* SCI2.1mid+ */ { 0, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0, 7, 7, 0 }
};
-GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32)
- : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32), _isHiRes(false) {
-
- _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
- _curScrollText = -1;
- _showScrollText = false;
- _maxScrollTexts = 0;
+GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32) :
+ _isHiRes(false),
+ _cache(cache),
+ _palette(palette),
+ _resMan(resMan),
+ _screen(screen),
+ _segMan(segMan),
+ _paint32(paint32),
+ _showStyles(nullptr),
+ // TODO: Stop using _gfxScreen
+ _currentBuffer(screen->getDisplayWidth(), screen->getDisplayHeight(), nullptr),
+ _remapOccurred(false),
+ _frameNowVisible(false),
+ _screenRect(screen->getDisplayWidth(), screen->getDisplayHeight()),
+ _overdrawThreshold(0),
+ _palMorphIsOn(false) {
+
+ _currentBuffer.setPixels(calloc(1, screen->getDisplayWidth() * screen->getDisplayHeight()));
+
+ for (int i = 0; i < 236; i += 2) {
+ _styleRanges[i] = 0;
+ _styleRanges[i + 1] = -1;
+ }
+ for (int i = 236; i < ARRAYSIZE(_styleRanges); ++i) {
+ _styleRanges[i] = 0;
+ }
// TODO: Make hires detection work uniformly across all SCI engine
// versions (this flag is normally passed by SCI::MakeGraphicsMgr
- // to the GraphicsMgr constructor depending upon video configuration)
+ // to the GraphicsMgr constructor depending upon video configuration,
+ // so should be handled upstream based on game configuration instead
+ // of here)
if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _resMan->detectHires()) {
_isHiRes = true;
}
+
+ if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ _dissolveSequenceSeeds = dissolveSequences[0];
+ _defaultDivisions = divisionsDefaults[0];
+ _defaultUnknownC = unknownCDefaults[0];
+ } else {
+ _dissolveSequenceSeeds = dissolveSequences[1];
+ _defaultDivisions = divisionsDefaults[1];
+ _defaultUnknownC = unknownCDefaults[1];
+ }
+
+ switch (g_sci->getGameId()) {
+ case GID_GK2:
+ case GID_LIGHTHOUSE:
+ case GID_LSL7:
+ case GID_PHANTASMAGORIA2:
+ case GID_PQSWAT:
+ case GID_TORIN:
+ case GID_RAMA:
+ _currentBuffer.scriptWidth = 640;
+ _currentBuffer.scriptHeight = 480;
+ break;
+ default:
+ // default script width for other games is 320x200
+ break;
+ }
+
+ // TODO: Nothing in the renderer really uses this. Currently,
+ // the cursor renderer does, and kLocalToGlobal/kGlobalToLocal
+ // do, but in the real engine (1) the cursor is handled in
+ // frameOut, and (2) functions do a very simple lookup of the
+ // plane and arithmetic with the plane's gameRect. In
+ // principle, CoordAdjuster could be reused for
+ // convertGameRectToPlaneRect, but it is not super clear yet
+ // what the benefit would be to do that.
+ _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
+
+ // TODO: Script resolution is hard-coded per game;
+ // also this must be set or else the engine will crash
+ _coordAdjuster->setScriptsResolution(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight);
}
GfxFrameout::~GfxFrameout() {
clear();
+ CelObj::deinit();
+ free(_currentBuffer.getPixels());
}
+void GfxFrameout::run() {
+ CelObj::init();
+ Plane::init();
+ ScreenItem::init();
+
+ // NOTE: This happens in SCI::InitPlane in the actual engine,
+ // and is a background fill plane to ensure hidden planes
+ // (planes with a priority of -1) are never drawn
+ Plane *initPlane = new Plane(Common::Rect(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight));
+ initPlane->_priority = 0;
+ _planes.add(initPlane);
+}
+
+// SCI32 actually did not clear anything at all it seems on restore. The scripts actually cleared up
+// planes + screen items right before restoring. And after restoring they sync'd its internal planes list
+// as well.
void GfxFrameout::clear() {
- deletePlaneItems(NULL_REG);
_planes.clear();
- deletePlanePictures(NULL_REG);
- clearScrollTexts();
-}
-
-void GfxFrameout::clearScrollTexts() {
- _scrollTexts.clear();
- _curScrollText = -1;
-}
-
-void GfxFrameout::addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace) {
- //reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow);
- // HACK: We set the container dimensions manually
- reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow, 480, 70);
- ScrollTextEntry textEntry;
- textEntry.bitmapHandle = bitmapHandle;
- textEntry.kWindow = kWindow;
- textEntry.x = x;
- textEntry.y = y;
- if (!replace || _scrollTexts.size() == 0) {
- if (_scrollTexts.size() > _maxScrollTexts) {
- _scrollTexts.remove_at(0);
- _curScrollText--;
- }
- _scrollTexts.push_back(textEntry);
- _curScrollText++;
- } else {
- _scrollTexts.pop_back();
- _scrollTexts.push_back(textEntry);
- }
+ _visiblePlanes.clear();
+ _showList.clear();
}
-void GfxFrameout::showCurrentScrollText() {
- if (!_showScrollText || _curScrollText < 0)
+// This is what Game::restore does, only needed when our ScummVM dialogs are patched in
+// It actually does one pass before actual restore deleting screen items + planes
+// And after restore it does another pass adding screen items + planes.
+// Attention: at least Space Quest 6's option plane seems to stay in memory right from the start and is not re-created.
+void GfxFrameout::syncWithScripts(bool addElements) {
+ EngineState *engineState = g_sci->getEngineState();
+ SegManager *segMan = engineState->_segMan;
+
+ // In case original save/restore dialogs are active, don't do anything
+ if (ConfMan.getBool("originalsaveload"))
return;
- uint16 size = (uint16)_scrollTexts.size();
- if (size > 0) {
- assert(_curScrollText < size);
- ScrollTextEntry textEntry = _scrollTexts[_curScrollText];
- g_sci->_gfxText32->drawScrollTextBitmap(textEntry.kWindow, textEntry.bitmapHandle, textEntry.x, textEntry.y);
- }
-}
-
-extern void showScummVMDialog(const Common::String &message);
-
-void GfxFrameout::kernelAddPlane(reg_t object) {
- PlaneEntry newPlane;
-
- if (_planes.empty()) {
- // There has to be another way for sierra sci to do this or maybe script resolution is compiled into
- // interpreter (TODO)
- uint16 scriptWidth = readSelectorValue(_segMan, object, SELECTOR(resX));
- uint16 scriptHeight = readSelectorValue(_segMan, object, SELECTOR(resY));
-
- // Phantasmagoria 2 doesn't specify a script width/height
- if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
- scriptWidth = 640;
- scriptHeight = 480;
- }
-
- assert(scriptWidth > 0 && scriptHeight > 0);
- _coordAdjuster->setScriptsResolution(scriptWidth, scriptHeight);
- }
-
- // Import of QfG character files dialog is shown in QFG4.
- // Display additional popup information before letting user use it.
- // For the SCI0-SCI1.1 version of this, check kDrawControl().
- if (g_sci->inQfGImportRoom() && !strcmp(_segMan->getObjectName(object), "DSPlane")) {
- showScummVMDialog("Characters saved inside ScummVM are shown "
- "automatically. Character files saved in the original "
- "interpreter need to be put inside ScummVM's saved games "
- "directory and a prefix needs to be added depending on which "
- "game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' "
- "for Quest for Glory 2, 'qfg3-' for Quest for Glory 3. "
- "Example: 'qfg2-thief.sav'.");
- }
-
- newPlane.object = object;
- newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
- newPlane.lastPriority = -1; // hidden
- newPlane.planeOffsetX = 0;
- newPlane.planeOffsetY = 0;
- newPlane.pictureId = kPlanePlainColored;
- newPlane.planePictureMirrored = false;
- newPlane.planeBack = 0;
- _planes.push_back(newPlane);
-
- kernelUpdatePlane(object);
-}
-
-void GfxFrameout::kernelUpdatePlane(reg_t object) {
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
- if (it->object == object) {
- // Read some information
- it->priority = readSelectorValue(_segMan, object, SELECTOR(priority));
- GuiResourceId lastPictureId = it->pictureId;
- it->pictureId = readSelectorValue(_segMan, object, SELECTOR(picture));
- if (lastPictureId != it->pictureId) {
- // picture got changed, load new picture
- deletePlanePictures(object);
- // Draw the plane's picture if it's not a translucent/plane colored frame
- if ((it->pictureId != kPlanePlainColored) && (it->pictureId != kPlaneTranslucent)) {
- // SQ6 gives us a bad picture number for the control menu
- if (_resMan->testResource(ResourceId(kResourceTypePic, it->pictureId)))
- addPlanePicture(object, it->pictureId, 0);
- }
- }
- it->planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top));
- it->planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left));
- it->planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom));
- it->planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right));
-
- _coordAdjuster->fromScriptToDisplay(it->planeRect.top, it->planeRect.left);
- _coordAdjuster->fromScriptToDisplay(it->planeRect.bottom, it->planeRect.right);
-
- // We get negative left in kq7 in scrolling rooms
- if (it->planeRect.left < 0) {
- it->planeOffsetX = -it->planeRect.left;
- it->planeRect.left = 0;
- } else {
- it->planeOffsetX = 0;
- }
+ // Get planes list object
+ reg_t planesListObject = engineState->variables[VAR_GLOBAL][10];
+ reg_t planesListElements = readSelector(segMan, planesListObject, SELECTOR(elements));
- if (it->planeRect.top < 0) {
- it->planeOffsetY = -it->planeRect.top;
- it->planeRect.top = 0;
- } else {
- it->planeOffsetY = 0;
- }
+ List *planesList = segMan->lookupList(planesListElements);
+ reg_t planesNodeObject = planesList->first;
- // We get bad plane-bottom in sq6
- if (it->planeRect.right > _screen->getWidth())
- it->planeRect.right = _screen->getWidth();
- if (it->planeRect.bottom > _screen->getHeight())
- it->planeRect.bottom = _screen->getHeight();
-
- it->planeClipRect = Common::Rect(it->planeRect.width(), it->planeRect.height());
- it->upscaledPlaneRect = it->planeRect;
- it->upscaledPlaneClipRect = it->planeClipRect;
- if (_screen->getUpscaledHires()) {
- _screen->adjustToUpscaledCoordinates(it->upscaledPlaneRect.top, it->upscaledPlaneRect.left);
- _screen->adjustToUpscaledCoordinates(it->upscaledPlaneRect.bottom, it->upscaledPlaneRect.right);
- _screen->adjustToUpscaledCoordinates(it->upscaledPlaneClipRect.top, it->upscaledPlaneClipRect.left);
- _screen->adjustToUpscaledCoordinates(it->upscaledPlaneClipRect.bottom, it->upscaledPlaneClipRect.right);
- }
+ // Go through all elements of planes::elements
+ while (!planesNodeObject.isNull()) {
+ Node *planesNode = segMan->lookupNode(planesNodeObject);
+ reg_t planeObject = planesNode->value;
+
+ if (addElements) {
+ // Add this plane object
+ kernelAddPlane(planeObject);
+ }
+
+ reg_t planeCastsObject = readSelector(segMan, planeObject, SELECTOR(casts));
+ reg_t setListElements = readSelector(segMan, planeCastsObject, SELECTOR(elements));
+
+ // Now go through all elements of plane::casts::elements
+ List *planeCastsList = segMan->lookupList(setListElements);
+ reg_t planeCastsNodeObject = planeCastsList->first;
+
+ while (!planeCastsNodeObject.isNull()) {
+ Node *castsNode = segMan->lookupNode(planeCastsNodeObject);
+ reg_t castsObject = castsNode->value;
+
+ reg_t castsListElements = readSelector(segMan, castsObject, SELECTOR(elements));
+
+ List *castsList = segMan->lookupList(castsListElements);
+ reg_t castNodeObject = castsList->first;
- it->planePictureMirrored = readSelectorValue(_segMan, object, SELECTOR(mirrored));
- it->planeBack = readSelectorValue(_segMan, object, SELECTOR(back));
+ while (!castNodeObject.isNull()) {
+ Node *castNode = segMan->lookupNode(castNodeObject);
+ reg_t castObject = castNode->value;
- sortPlanes();
+ // read selector "-info-" of this object
+ // TODO: Seems to have been changed for SCI3
+ // Do NOT use getInfoSelector in here. SCI3 games did not use infoToa, but an actual selector.
+ // Maybe that selector is just a straight copy, but it needs to get verified/checked.
+ uint16 castInfoSelector = readSelectorValue(segMan, castObject, SELECTOR(_info_));
- // Update the items in the plane
- for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
- reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
- if (object == itemPlane) {
- kernelUpdateScreenItem((*listIterator)->object);
+ if (castInfoSelector & kInfoFlagViewInserted) {
+ if (addElements) {
+ // Flag set, so add this screen item
+ kernelAddScreenItem(castObject);
+ } else {
+ // Flag set, so delete this screen item
+ kernelDeleteScreenItem(castObject);
+ }
}
+
+ castNodeObject = castNode->succ;
}
- return;
+ planeCastsNodeObject = castsNode->succ;
+ }
+
+ if (!addElements) {
+ // Delete this plane object
+ kernelDeletePlane(planeObject);
}
+
+ planesNodeObject = planesNode->succ;
}
- error("kUpdatePlane called on plane that wasn't added before");
}
-void GfxFrameout::kernelDeletePlane(reg_t object) {
- deletePlaneItems(object);
- deletePlanePictures(object);
+#pragma mark -
+#pragma mark Screen items
+
+void GfxFrameout::kernelAddScreenItem(const reg_t object) {
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
- if (it->object == object) {
- _planes.erase(it);
- Common::Rect planeRect;
- planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top));
- planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left));
- planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom));
- planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right));
+ _segMan->getObject(object)->setInfoSelectorFlag(kInfoFlagViewInserted);
+
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("kAddScreenItem: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(object));
+ }
+
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
+ if (screenItem != nullptr) {
+ screenItem->update(object);
+ } else {
+ screenItem = new ScreenItem(object);
+ plane->_screenItemList.add(screenItem);
+ }
+}
- _coordAdjuster->fromScriptToDisplay(planeRect.top, planeRect.left);
- _coordAdjuster->fromScriptToDisplay(planeRect.bottom, planeRect.right);
+void GfxFrameout::kernelUpdateScreenItem(const reg_t object) {
+ const reg_t magnifierObject = readSelector(_segMan, object, SELECTOR(magnifier));
+ if (magnifierObject.isNull()) {
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("kUpdateScreenItem: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(object));
+ }
- // Blackout removed plane rect
- _paint32->fillRect(planeRect, 0);
- return;
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
+ if (screenItem == nullptr) {
+ error("kUpdateScreenItem: Screen item %04x:%04x not found in plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
}
+
+ screenItem->update(object);
+ } else {
+ error("Magnifier view is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!");
}
}
-void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY) {
- if (pictureId == kPlanePlainColored || pictureId == kPlaneTranslucent) // sanity check
+void GfxFrameout::kernelDeleteScreenItem(const reg_t object) {
+ _segMan->getObject(object)->clearInfoSelectorFlag(kInfoFlagViewInserted);
+
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ return;
+ }
+
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
+ if (screenItem == nullptr) {
return;
+ }
- PlanePictureEntry newPicture;
- newPicture.object = object;
- newPicture.pictureId = pictureId;
- newPicture.picture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, pictureId, false);
- newPicture.startX = startX;
- newPicture.startY = startY;
- newPicture.pictureCels = 0;
- _planePictures.push_back(newPicture);
+ if (screenItem->_created == 0) {
+ screenItem->_created = 0;
+ screenItem->_updated = 0;
+ screenItem->_deleted = getScreenCount();
+ } else {
+ plane->_screenItemList.erase(screenItem);
+ plane->_screenItemList.pack();
+ }
}
-void GfxFrameout::deletePlanePictures(reg_t object) {
- PlanePictureList::iterator it = _planePictures.begin();
+#pragma mark -
+#pragma mark Planes
- while (it != _planePictures.end()) {
- if (it->object == object || object.isNull()) {
- delete it->pictureCels;
- delete it->picture;
- it = _planePictures.erase(it);
- } else {
- ++it;
- }
+void GfxFrameout::kernelAddPlane(const reg_t object) {
+ Plane *plane = _planes.findByObject(object);
+ if (plane != nullptr) {
+ plane->update(object);
+ updatePlane(*plane);
+ } else {
+ plane = new Plane(object);
+ addPlane(*plane);
}
}
-// Provides the same functionality as kGraph(DrawLine)
-reg_t GfxFrameout::addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) {
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
- if (it->object == object) {
- PlaneLineEntry line;
- line.hunkId = _segMan->allocateHunkEntry("PlaneLine()", 1); // we basically use this for a unique ID
- line.startPoint = startPoint;
- line.endPoint = endPoint;
- line.color = color;
- line.priority = priority;
- line.control = control;
- it->lines.push_back(line);
- return line.hunkId;
- }
+void GfxFrameout::kernelUpdatePlane(const reg_t object) {
+ Plane *plane = _planes.findByObject(object);
+ if (plane == nullptr) {
+ error("kUpdatePlane: Plane %04x:%04x not found", PRINT_REG(object));
}
- return NULL_REG;
+ plane->update(object);
+ updatePlane(*plane);
}
-void GfxFrameout::updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) {
- // Check if we're asked to update a line that was never added
- if (hunkId.isNull())
- return;
+void GfxFrameout::kernelDeletePlane(const reg_t object) {
+ Plane *plane = _planes.findByObject(object);
+ if (plane == nullptr) {
+ error("kDeletePlane: Plane %04x:%04x not found", PRINT_REG(object));
+ }
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
- if (it->object == object) {
- for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) {
- if (it2->hunkId == hunkId) {
- it2->startPoint = startPoint;
- it2->endPoint = endPoint;
- it2->color = color;
- it2->priority = priority;
- it2->control = control;
- return;
- }
- }
- }
+ if (plane->_created) {
+ // NOTE: The original engine calls some `AbortPlane` function that
+ // just ends up doing this anyway so we skip the extra indirection
+ _planes.erase(plane);
+ } else {
+ plane->_created = 0;
+ plane->_deleted = g_sci->_gfxFrameout->getScreenCount();
}
}
-void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) {
- // Check if we're asked to delete a line that was never added (happens during the intro of LSL6)
- if (hunkId.isNull())
- return;
+void GfxFrameout::deletePlane(Plane &planeToFind) {
+ Plane *plane = _planes.findByObject(planeToFind._object);
+ if (plane == nullptr) {
+ error("deletePlane: Plane %04x:%04x not found", PRINT_REG(planeToFind._object));
+ }
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
- if (it->object == object) {
- for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) {
- if (it2->hunkId == hunkId) {
- _segMan->freeHunkEntry(hunkId);
- it2 = it->lines.erase(it2);
- return;
- }
- }
- }
+ if (plane->_created) {
+ _planes.erase(plane);
+ } else {
+ plane->_created = 0;
+ plane->_moved = 0;
+ plane->_deleted = getScreenCount();
}
}
-// Adapted from GfxAnimate::applyGlobalScaling()
-void GfxFrameout::applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight) {
- // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
- int16 maxScale = readSelectorValue(_segMan, itemEntry->object, SELECTOR(maxScale));
- int16 maxCelHeight = (maxScale * celHeight) >> 7;
- reg_t globalVar2 = g_sci->getEngineState()->variables[VAR_GLOBAL][2]; // current room object
- int16 vanishingY = readSelectorValue(_segMan, globalVar2, SELECTOR(vanishingY));
+void GfxFrameout::kernelMovePlaneItems(const reg_t object, const int16 deltaX, const int16 deltaY, const bool scrollPics) {
+ Plane *plane = _planes.findByObject(object);
+ if (plane == nullptr) {
+ error("kMovePlaneItems: Plane %04x:%04x not found", PRINT_REG(object));
+ }
- int16 fixedPortY = planeRect.bottom - vanishingY;
- int16 fixedEntryY = itemEntry->y - vanishingY;
- if (!fixedEntryY)
- fixedEntryY = 1;
+ plane->scrollScreenItems(deltaX, deltaY, scrollPics);
- if ((celHeight == 0) || (fixedPortY == 0))
- error("global scaling panic");
+ for (ScreenItemList::iterator it = plane->_screenItemList.begin(); it != plane->_screenItemList.end(); ++it) {
+ ScreenItem &screenItem = **it;
- itemEntry->scaleY = (maxCelHeight * fixedEntryY) / fixedPortY;
- itemEntry->scaleY = (itemEntry->scaleY * maxScale) / celHeight;
+ // If object is a number, the screen item from the
+ // engine, not a script, and should be ignored
+ if (screenItem._object.isNumber()) {
+ continue;
+ }
- // Make sure that the calculated value is sane
- if (itemEntry->scaleY < 1 /*|| itemEntry->scaleY > 128*/)
- itemEntry->scaleY = 128;
+ if (deltaX != 0) {
+ writeSelectorValue(_segMan, screenItem._object, SELECTOR(x), readSelectorValue(_segMan, screenItem._object, SELECTOR(x)) + deltaX);
+ }
- itemEntry->scaleX = itemEntry->scaleY;
+ if (deltaY != 0) {
+ writeSelectorValue(_segMan, screenItem._object, SELECTOR(y), readSelectorValue(_segMan, screenItem._object, SELECTOR(y)) + deltaY);
+ }
+ }
+}
- // and set objects scale selectors
- //writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleX), itemEntry->scaleX);
- //writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleY), itemEntry->scaleY);
+int16 GfxFrameout::kernelGetHighPlanePri() {
+ return _planes.getTopSciPlanePriority();
}
-void GfxFrameout::kernelAddScreenItem(reg_t object) {
- // Ignore invalid items
- if (!_segMan->isObject(object)) {
- warning("kernelAddScreenItem: Attempt to add an invalid object (%04x:%04x)", PRINT_REG(object));
- return;
+void GfxFrameout::addPlane(Plane &plane) {
+ if (_planes.findByObject(plane._object) == nullptr) {
+ plane.clipScreenRect(_screenRect);
+ _planes.add(&plane);
+ } else {
+ plane._deleted = 0;
+ if (plane._created == 0) {
+ plane._moved = g_sci->_gfxFrameout->getScreenCount();
+ }
+ _planes.sort();
}
+}
+
+void GfxFrameout::updatePlane(Plane &plane) {
+ // NOTE: This assertion comes from SCI engine code.
+ assert(_planes.findByObject(plane._object) == &plane);
- FrameoutEntry *itemEntry = new FrameoutEntry();
- memset(itemEntry, 0, sizeof(FrameoutEntry));
- itemEntry->object = object;
- itemEntry->givenOrderNr = _screenItems.size();
- itemEntry->visible = true;
- _screenItems.push_back(itemEntry);
+ Plane *visiblePlane = _visiblePlanes.findByObject(plane._object);
+ plane.sync(visiblePlane, _screenRect);
+ // NOTE: updateScreenRect was originally called a second time here,
+ // but it is already called at the end of the Plane::Update call
+ // in the original engine anyway.
- kernelUpdateScreenItem(object);
+ _planes.sort();
}
-void GfxFrameout::kernelUpdateScreenItem(reg_t object) {
- // Ignore invalid items
- if (!_segMan->isObject(object)) {
- warning("kernelUpdateScreenItem: Attempt to update an invalid object (%04x:%04x)", PRINT_REG(object));
- return;
- }
+#pragma mark -
+#pragma mark Pics
- FrameoutEntry *itemEntry = findScreenItem(object);
- if (!itemEntry) {
- warning("kernelUpdateScreenItem: invalid object %04x:%04x", PRINT_REG(object));
- return;
+void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX) {
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("kAddPicAt: Plane %04x:%04x not found", PRINT_REG(planeObject));
}
+ plane->addPic(pictureId, Common::Point(x, y), mirrorX);
+}
- itemEntry->viewId = readSelectorValue(_segMan, object, SELECTOR(view));
- itemEntry->loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
- itemEntry->celNo = readSelectorValue(_segMan, object, SELECTOR(cel));
- itemEntry->x = readSelectorValue(_segMan, object, SELECTOR(x));
- itemEntry->y = readSelectorValue(_segMan, object, SELECTOR(y));
- itemEntry->z = readSelectorValue(_segMan, object, SELECTOR(z));
- itemEntry->priority = readSelectorValue(_segMan, object, SELECTOR(priority));
- if (readSelectorValue(_segMan, object, SELECTOR(fixPriority)) == 0)
- itemEntry->priority = itemEntry->y;
+#pragma mark -
+#pragma mark Rendering
- itemEntry->signal = readSelectorValue(_segMan, object, SELECTOR(signal));
- itemEntry->scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));
+void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect) {
+// TODO: Robot
+// if (_robot != nullptr) {
+// _robot.doRobot();
+// }
- if (itemEntry->scaleSignal & kScaleSignalDoScaling32) {
- itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX));
- itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY));
- } else {
- itemEntry->scaleX = 128;
- itemEntry->scaleY = 128;
- }
- itemEntry->visible = true;
+ // NOTE: The original engine allocated these as static arrays of 100
+ // pointers to ScreenItemList / RectList
+ ScreenItemListList screenItemLists;
+ EraseListList eraseLists;
- // Check if the entry can be hidden
- if (lookupSelector(_segMan, object, SELECTOR(visible), NULL, NULL) != kSelectorNone)
- itemEntry->visible = readSelectorValue(_segMan, object, SELECTOR(visible));
-}
+ screenItemLists.resize(_planes.size());
+ eraseLists.resize(_planes.size());
-void GfxFrameout::kernelDeleteScreenItem(reg_t object) {
- FrameoutEntry *itemEntry = findScreenItem(object);
- // If the item could not be found, it may already have been deleted
- if (!itemEntry)
- return;
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
+ }
- _screenItems.remove(itemEntry);
- delete itemEntry;
-}
+ calcLists(screenItemLists, eraseLists, rect);
-void GfxFrameout::deletePlaneItems(reg_t planeObject) {
- FrameoutList::iterator listIterator = _screenItems.begin();
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ list->sort();
+ }
- while (listIterator != _screenItems.end()) {
- bool objectMatches = false;
- if (!planeObject.isNull()) {
- reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
- objectMatches = (planeObject == itemPlane);
- } else {
- objectMatches = true;
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
+ (*drawItem)->screenItem->getCelObj().submitPalette();
}
+ }
- if (objectMatches) {
- FrameoutEntry *itemEntry = *listIterator;
- listIterator = _screenItems.erase(listIterator);
- delete itemEntry;
- } else {
- ++listIterator;
- }
+ _remapOccurred = _palette->updateForFrame();
+
+ // NOTE: SCI engine set this to false on each loop through the
+ // planelist iterator below. Since that is a waste, we only set
+ // it once.
+ _frameNowVisible = false;
+
+ for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
+ drawEraseList(eraseLists[i], *_planes[i]);
+ drawScreenItemList(screenItemLists[i]);
}
-}
-FrameoutEntry *GfxFrameout::findScreenItem(reg_t object) {
- for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
- FrameoutEntry *itemEntry = *listIterator;
- if (itemEntry->object == object)
- return itemEntry;
+// TODO: Robot
+// if (_robot != nullptr) {
+// _robot->frameAlmostVisible();
+// }
+
+ _palette->updateHardware();
+
+ if (shouldShowBits) {
+ showBits();
}
- return NULL;
-}
+ _frameNowVisible = true;
-int16 GfxFrameout::kernelGetHighPlanePri() {
- sortPlanes();
- return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back().object, SELECTOR(priority));
+// TODO: Robot
+// if (_robot != nullptr) {
+// robot->frameNowVisible();
+// }
}
-void GfxFrameout::kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY) {
- addPlanePicture(planeObj, pictureId, pictureX, pictureY);
-}
+// Determine the parts of 'r' that aren't overlapped by 'other'.
+// Returns -1 if r and other have no intersection.
+// Returns number of returned parts (in outRects) otherwise.
+// (In particular, this returns 0 if r is contained in other.)
+int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]) {
+ if (!r.intersects(other)) {
+ return -1;
+ }
-bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) {
- if (entry1->priority == entry2->priority) {
- if (entry1->y == entry2->y)
- return (entry1->givenOrderNr < entry2->givenOrderNr);
- return (entry1->y < entry2->y);
+ int count = 0;
+ if (r.top < other.top) {
+ Common::Rect &t = outRects[count++];
+ t = r;
+ t.bottom = other.top;
+ r.top = other.top;
}
- return (entry1->priority < entry2->priority);
-}
-bool planeSortHelper(const PlaneEntry &entry1, const PlaneEntry &entry2) {
- if (entry1.priority < 0)
- return true;
+ if (r.bottom > other.bottom) {
+ Common::Rect &t = outRects[count++];
+ t = r;
+ t.top = other.bottom;
+ r.bottom = other.bottom;
+ }
- if (entry2.priority < 0)
- return false;
+ if (r.left < other.left) {
+ Common::Rect &t = outRects[count++];
+ t = r;
+ t.right = other.left;
+ r.left = other.left;
+ }
- return entry1.priority < entry2.priority;
+ if (r.right > other.right) {
+ Common::Rect &t = outRects[count++];
+ t = r;
+ t.left = other.right;
+ }
+
+ return count;
}
-void GfxFrameout::sortPlanes() {
- // First, remove any invalid planes
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end();) {
- if (!_segMan->isObject(it->object))
- it = _planes.erase(it);
- else
- it++;
+void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &calcRect) {
+ RectList rectlist;
+ Common::Rect outRects[4];
+
+ int deletedPlaneCount = 0;
+ bool addedToRectList = false;
+ int planeCount = _planes.size();
+ bool foundTransparentPlane = false;
+
+ if (!calcRect.isEmpty()) {
+ addedToRectList = true;
+ rectlist.add(calcRect);
}
- // Sort the rest of them
- Common::sort(_planes.begin(), _planes.end(), planeSortHelper);
-}
+ for (int outerPlaneIndex = 0; outerPlaneIndex < planeCount; ++outerPlaneIndex) {
+ Plane *outerPlane = _planes[outerPlaneIndex];
-void GfxFrameout::showVideo() {
- bool skipVideo = false;
- 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 (outerPlane->_type == kPlaneTypeTransparent) {
+ foundTransparentPlane = true;
+ }
- if (videoDecoder->hasDirtyPalette())
- g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
+ Plane *visiblePlane = _visiblePlanes.findByObject(outerPlane->_object);
- while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
- if (videoDecoder->needsUpdate()) {
- const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
- if (frame) {
- // 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 (outerPlane->_deleted) {
+ if (visiblePlane != nullptr) {
+ if (!visiblePlane->_screenRect.isEmpty()) {
+ addedToRectList = true;
+ rectlist.add(visiblePlane->_screenRect);
+ }
+ }
+ ++deletedPlaneCount;
+ } else if (visiblePlane != nullptr) {
+ if (outerPlane->_updated) {
+ --outerPlane->_updated;
+
+ int splitcount = splitRects(visiblePlane->_screenRect, outerPlane->_screenRect, outRects);
+ if (splitcount) {
+ if (splitcount == -1) {
+ if (!visiblePlane->_screenRect.isEmpty()) {
+ rectlist.add(visiblePlane->_screenRect);
+ }
+ } else {
+ for (int i = 0; i < splitcount; ++i) {
+ rectlist.add(outRects[i]);
+ }
+ }
- if (videoDecoder->hasDirtyPalette())
- g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256);
+ addedToRectList = true;
+ }
- g_system->updateScreen();
+ if (!outerPlane->_redrawAllCount) {
+ int splitCount = splitRects(outerPlane->_screenRect, visiblePlane->_screenRect, outRects);
+ if (splitCount) {
+ for (int i = 0; i < splitCount; ++i) {
+ rectlist.add(outRects[i]);
+ }
+ addedToRectList = true;
+ }
+ }
}
}
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event)) {
- if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
- skipVideo = true;
- }
+ if (addedToRectList) {
+ for (RectList::iterator rect = rectlist.begin(); rect != rectlist.end(); ++rect) {
+ for (int innerPlaneIndex = _planes.size() - 1; innerPlaneIndex >= 0; --innerPlaneIndex) {
+ Plane *innerPlane = _planes[innerPlaneIndex];
+
+ if (!innerPlane->_deleted && innerPlane->_type != kPlaneTypeTransparent && innerPlane->_screenRect.intersects(**rect)) {
+ if (innerPlane->_redrawAllCount == 0) {
+ eraseLists[innerPlaneIndex].add(innerPlane->_screenRect.findIntersectingRect(**rect));
+ }
+
+ int splitCount = splitRects(**rect, innerPlane->_screenRect, outRects);
+ for (int i = 0; i < splitCount; ++i) {
+ rectlist.add(outRects[i]);
+ }
+
+ rectlist.erase(rect);
+ break;
+ }
+ }
+ }
- g_system->delayMillis(10);
+ rectlist.pack();
+ }
}
-}
-void GfxFrameout::createPlaneItemList(reg_t planeObject, FrameoutList &itemList) {
- // Copy screen items of the current frame to the list of items to be drawn
- for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
- reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
- if (planeObject == itemPlane) {
- kernelUpdateScreenItem((*listIterator)->object); // TODO: Why is this necessary?
- itemList.push_back(*listIterator);
+ // clean up deleted planes
+ if (deletedPlaneCount) {
+ for (int planeIndex = planeCount - 1; planeIndex >= 0; --planeIndex) {
+ Plane *plane = _planes[planeIndex];
+
+ if (plane->_deleted) {
+ --plane->_deleted;
+ if (plane->_deleted <= 0) {
+ PlaneList::iterator visiblePlaneIt = Common::find_if(_visiblePlanes.begin(), _visiblePlanes.end(), FindByObject<Plane *>(plane->_object));
+ if (visiblePlaneIt != _visiblePlanes.end()) {
+ _visiblePlanes.erase(visiblePlaneIt);
+ }
+
+ _planes.remove_at(planeIndex);
+ eraseLists.remove_at(planeIndex);
+ drawLists.remove_at(planeIndex);
+ }
+
+ if (--deletedPlaneCount <= 0) {
+ break;
+ }
+ }
}
}
- for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
- if (pictureIt->object == planeObject) {
- GfxPicture *planePicture = pictureIt->picture;
- // Allocate memory for picture cels
- pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()];
+ planeCount = _planes.size();
+ for (int outerIndex = 0; outerIndex < planeCount; ++outerIndex) {
+ // "outer" just refers to the outer loop
+ Plane *outerPlane = _planes[outerIndex];
+ if (outerPlane->_priorityChanged) {
+ --outerPlane->_priorityChanged;
+
+ Plane *visibleOuterPlane = _visiblePlanes.findByObject(outerPlane->_object);
+
+ rectlist.add(outerPlane->_screenRect.findIntersectingRect(visibleOuterPlane->_screenRect));
+
+ for (int innerIndex = planeCount - 1; innerIndex >= 0; --innerIndex) {
+ // "inner" just refers to the inner loop
+ Plane *innerPlane = _planes[innerIndex];
+ Plane *visibleInnerPlane = _visiblePlanes.findByObject(innerPlane->_object);
+
+ int rectCount = rectlist.size();
+ for (int rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
+ int splitCount = splitRects(*rectlist[rectIndex], _planes[innerIndex]->_screenRect, outRects);
+
+ if (splitCount == 0) {
+ if (visibleInnerPlane != nullptr) {
+ // same priority, or relative priority between inner/outer changed
+ if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane->_priority - innerPlane->_priority) <= 0) {
+ if (outerPlane->_priority <= innerPlane->_priority) {
+ eraseLists[innerIndex].add(*rectlist[rectIndex]);
+ } else {
+ eraseLists[outerIndex].add(*rectlist[rectIndex]);
+ }
+ }
+ }
+
+ rectlist.erase_at(rectIndex);
+ } else if (splitCount != -1) {
+ for (int i = 0; i < splitCount; ++i) {
+ rectlist.add(outRects[i]);
+ }
+
+ if (visibleInnerPlane != nullptr) {
+ // same priority, or relative priority between inner/outer changed
+ if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane->_priority - innerPlane->_priority) <= 0) {
+ *rectlist[rectIndex] = outerPlane->_screenRect.findIntersectingRect(innerPlane->_screenRect);
+ if (outerPlane->_priority <= innerPlane->_priority) {
+ eraseLists[innerIndex].add(*rectlist[rectIndex]);
+ }
+ else {
+ eraseLists[outerIndex].add(*rectlist[rectIndex]);
+ }
+ }
+ }
+ rectlist.erase_at(rectIndex);
+ }
+ }
+ rectlist.pack();
+ }
+ }
+ }
- // Add following cels to the itemlist
- FrameoutEntry *picEntry = pictureIt->pictureCels;
- int planePictureCels = planePicture->getSci32celCount();
- for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) {
- picEntry->celNo = pictureCelNr;
- picEntry->object = NULL_REG;
- picEntry->picture = planePicture;
- picEntry->y = planePicture->getSci32celY(pictureCelNr);
- picEntry->x = planePicture->getSci32celX(pictureCelNr);
- picEntry->picStartX = pictureIt->startX;
- picEntry->picStartY = pictureIt->startY;
- picEntry->visible = true;
+ for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+ Plane *plane = _planes[planeIndex];
+ Plane *visiblePlane = nullptr;
- picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);
+ PlaneList::iterator visiblePlaneIt = Common::find_if(_visiblePlanes.begin(), _visiblePlanes.end(), FindByObject<Plane *>(plane->_object));
+ if (visiblePlaneIt != _visiblePlanes.end()) {
+ visiblePlane = *visiblePlaneIt;
+ }
- itemList.push_back(picEntry);
- picEntry++;
+ if (plane->_redrawAllCount) {
+ plane->redrawAll(visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
+ } else {
+ if (visiblePlane == nullptr) {
+ error("Missing visible plane for source plane %04x:%04x", PRINT_REG(plane->_object));
}
+
+ plane->calcLists(*visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
+ }
+
+ if (plane->_created) {
+ _visiblePlanes.add(new Plane(*plane));
+ --plane->_created;
+ } else if (plane->_moved) {
+ assert(visiblePlaneIt != _visiblePlanes.end());
+ **visiblePlaneIt = *plane;
+ --plane->_moved;
}
}
- // Now sort our itemlist
- Common::sort(itemList.begin(), itemList.end(), sortHelper);
-}
+ if (foundTransparentPlane) {
+ for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+ for (int i = planeIndex + 1; i < planeCount; ++i) {
+ if (_planes[i]->_type == kPlaneTypeTransparent) {
+ _planes[i]->filterUpEraseRects(drawLists[i], eraseLists[planeIndex]);
+ }
+ }
-bool GfxFrameout::isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY) {
- // Out of view horizontally (sanity checks)
- int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x;
- int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo);
- int16 planeStartX = planeOffsetX;
- int16 planeEndX = planeStartX + planeRect.width();
- if (pictureCelEndX < planeStartX)
- return true;
- if (pictureCelStartX > planeEndX)
- return true;
+ if (_planes[planeIndex]->_type == kPlaneTypeTransparent) {
+ for (int i = planeIndex - 1; i >= 0; --i) {
+ _planes[i]->filterDownEraseRects(drawLists[i], eraseLists[i], eraseLists[planeIndex]);
+ }
- // Out of view vertically (sanity checks)
- int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y;
- int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo);
- int16 planeStartY = planeOffsetY;
- int16 planeEndY = planeStartY + planeRect.height();
- if (pictureCelEndY < planeStartY)
- return true;
- if (pictureCelStartY > planeEndY)
- return true;
+ if (eraseLists[planeIndex].size() > 0) {
+ error("Transparent plane's erase list not absorbed");
+ }
+ }
- return false;
+ for (int i = planeIndex + 1; i < planeCount; ++i) {
+ if (_planes[i]->_type == kPlaneTypeTransparent) {
+ _planes[i]->filterUpDrawRects(drawLists[i], drawLists[planeIndex]);
+ }
+ }
+ }
+ }
}
-void GfxFrameout::drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored) {
- int16 pictureOffsetX = planeOffsetX;
- int16 pictureX = itemEntry->x;
- if ((planeOffsetX) || (itemEntry->picStartX)) {
- if (planeOffsetX <= itemEntry->picStartX) {
- pictureX += itemEntry->picStartX - planeOffsetX;
- pictureOffsetX = 0;
- } else {
- pictureOffsetX = planeOffsetX - itemEntry->picStartX;
- }
+void GfxFrameout::drawEraseList(const RectList &eraseList, const Plane &plane) {
+ if (plane._type != kPlaneTypeColored) {
+ return;
}
- int16 pictureOffsetY = planeOffsetY;
- int16 pictureY = itemEntry->y;
- if ((planeOffsetY) || (itemEntry->picStartY)) {
- if (planeOffsetY <= itemEntry->picStartY) {
- pictureY += itemEntry->picStartY - planeOffsetY;
- pictureOffsetY = 0;
- } else {
- pictureOffsetY = planeOffsetY - itemEntry->picStartY;
+ for (RectList::const_iterator it = eraseList.begin(); it != eraseList.end(); ++it) {
+ mergeToShowList(**it, _showList, _overdrawThreshold);
+ _currentBuffer.fillRect(**it, plane._back);
+ }
+}
+
+void GfxFrameout::drawScreenItemList(const DrawList &screenItemList) {
+ for (DrawList::const_iterator it = screenItemList.begin(); it != screenItemList.end(); ++it) {
+ DrawItem &drawItem = **it;
+ mergeToShowList(drawItem.rect, _showList, _overdrawThreshold);
+ ScreenItem &screenItem = *drawItem.screenItem;
+ // TODO: Remove
+// debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), PRINT_RECT(drawItem.rect));
+ CelObj &celObj = *screenItem._celObj;
+ celObj.draw(_currentBuffer, screenItem, drawItem.rect, screenItem._mirrorX ^ celObj._mirrorX);
+ }
+}
+
+void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold) {
+ Common::Rect merged(drawRect);
+
+ bool didDelete = true;
+ RectList::size_type count = showList.size();
+ while (didDelete && count) {
+ didDelete = false;
+
+ for (RectList::size_type i = 0; i < count; ++i) {
+ Common::Rect existing = *showList[i];
+ Common::Rect candidate;
+ candidate.left = MIN(merged.left, existing.left);
+ candidate.top = MIN(merged.top, existing.top);
+ candidate.right = MAX(merged.right, existing.right);
+ candidate.bottom = MAX(merged.bottom, existing.bottom);
+
+ if (candidate.height() * candidate.width() - merged.width() * merged.height() - existing.width() * existing.height() <= overdrawThreshold) {
+ merged = candidate;
+ showList.erase_at(i);
+ didDelete = true;
+ }
}
+
+ count = showList.pack();
}
- itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, planePictureMirrored);
- // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
+ showList.add(merged);
}
-/* TODO: This is the proper implementation of GraphicsMgr::FrameOut transcribed from SQ6 SCI engine disassembly.
-static DrawList* g_drawLists[100];
-static RectList* g_rectLists[100];
-void GfxFrameout::FrameOut(bool shouldShowBits, SOL_Rect *rect) {
- if (robot) {
- robot.doRobot();
+void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) {
+ Palette sourcePalette(*_palette->getNextPalette());
+ alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
+
+ int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16();
+
+ Common::Rect rect(_screen->getDisplayWidth(), _screen->getDisplayHeight());
+ _showList.add(rect);
+ showBits();
+
+ Common::Rect calcRect(0, 0);
+
+ // NOTE: The original engine allocated these as static arrays of 100
+ // pointers to ScreenItemList / RectList
+ ScreenItemListList screenItemLists;
+ EraseListList eraseLists;
+
+ screenItemLists.resize(_planes.size());
+ eraseLists.resize(_planes.size());
+
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
}
- auto planeCount = screen.planeList.planeCount;
- if (planeCount > 0) {
- for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- Plane plane = *screen.planeList[planeIndex];
+ calcLists(screenItemLists, eraseLists, calcRect);
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ list->sort();
+ }
- DrawList* drawList = new DrawList();
- g_drawLists[planeIndex] = drawList;
- RectList* rectList = new RectList();
- g_rectLists[planeIndex] = rectList;
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
+ (*drawItem)->screenItem->getCelObj().submitPalette();
}
}
-
- if (g_Remap_numActiveRemaps > 0 && remapNeeded) {
- screen.RemapMarkRedraw();
+
+ _remapOccurred = _palette->updateForFrame();
+ _frameNowVisible = false;
+
+ for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
+ drawEraseList(eraseLists[i], *_planes[i]);
+ drawScreenItemList(screenItemLists[i]);
}
-
- CalcLists(&g_drawLists, &g_rectLists, rect);
- // SCI engine stores reference *after* CalcLists
- planeCount = screen.planeList.planeCount;
- if (planeCount > 0) {
- for (int drawListIndex = 0; drawListIndex < planeCount; ++i) {
- DrawList* drawList = g_drawLists[drawListIndex];
- drawList->Sort();
- }
+ Palette nextPalette(*_palette->getNextPalette());
- for (int drawListIndex = 0; drawListIndex < planeCount; ++i) {
- DrawList* drawList = g_drawLists[drawListIndex];
- if (drawList == nullptr || drawList->count == 0) {
- continue;
+ if (prevRoom < 1000) {
+ for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
+ if (styleRanges[i] == -1 || styleRanges[i] == 0) {
+ sourcePalette.colors[i] = nextPalette.colors[i];
+ sourcePalette.colors[i].used = true;
}
-
- for (int screenItemIndex = 0, screenItemCount = drawList->count; screenItemIndex < screenItemCount; ++screenItemIndex) {
- ScreenItem* screenItem = drawList->items[screenItemIndex];
- screenItem->GetCelObj()->SubmitPalette();
+ }
+ } else {
+ for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
+ if (styleRanges[i] == -1 || (styleRanges[i] == 0 && i > 71 && i < 104)) {
+ sourcePalette.colors[i] = nextPalette.colors[i];
+ sourcePalette.colors[i].used = true;
}
}
}
- // UpdateForFrame is where all palette mutations occur (cycles, varies, etc.)
- bool remapNeeded = GPalette().UpdateForFrame();
- if (planeCount > 0) {
- frameNowVisible = false;
+ _palette->submit(sourcePalette);
+ _palette->updateFFrame();
+ _palette->updateHardware();
+ alterVmap(nextPalette, sourcePalette, 1, _styleRanges);
- for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- Plane* plane = screen.planeList[planeIndex];
+ if (showStyle && showStyle->type != kShowStyleUnknown) {
+// TODO: SCI2.1mid transition effects
+// processEffects();
+ warning("Transition %d not implemented!", showStyle->type);
+ } else {
+ showBits();
+ }
+
+ _frameNowVisible = true;
- DrawEraseList(g_rectLists[planeIndex], plane);
- DrawScreenItemsList(g_drawLists[planeIndex]);
+ for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) {
+ (*plane)->_redrawAllCount = getScreenCount();
+ }
+
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
+ }
+
+ calcLists(screenItemLists, eraseLists, calcRect);
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ list->sort();
+ }
+
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
+ (*drawItem)->screenItem->getCelObj().submitPalette();
}
}
- if (robot) {
- robot.FrameAlmostVisible();
+ _remapOccurred = _palette->updateForFrame();
+ // NOTE: During this second loop, `_frameNowVisible = false` is
+ // inside the next loop in SCI2.1mid
+ _frameNowVisible = false;
+
+ for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
+ drawEraseList(eraseLists[i], *_planes[i]);
+ drawScreenItemList(screenItemLists[i]);
}
- GPalette().UpdateHardware();
+ _palette->submit(nextPalette);
+ _palette->updateFFrame();
+ _palette->updateHardware();
+ showBits();
- if (shouldShowBits) {
- ShowBits();
+ _frameNowVisible = true;
+}
+
+// TODO: What does the bit masking for the show rects do,
+// and does it cause an off-by-one error in rect calculations
+// since SOL_Rect is BR inclusive and Common::Rect is BR
+// exclusive?
+void GfxFrameout::showBits() {
+ for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
+ Common::Rect rounded(**rect);
+ // NOTE: SCI engine used BR-inclusive rects so used slightly
+ // different masking here to ensure that the width of rects
+ // was always even.
+ rounded.left &= ~1;
+ rounded.right = (rounded.right + 1) & ~1;
+
+ // TODO:
+ // _cursor->GonnaPaint(rounded);
}
- frameNowVisible = true;
+ // TODO:
+ // _cursor->PaintStarting();
+
+ for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
+ Common::Rect rounded(**rect);
+ // NOTE: SCI engine used BR-inclusive rects so used slightly
+ // different masking here to ensure that the width of rects
+ // was always even.
+ rounded.left &= ~1;
+ rounded.right = (rounded.right + 1) & ~1;
- if (robot) {
- robot.FrameNowVisible();
+ byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left;
+
+ g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height());
}
- if (planeCount > 0) {
- for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- if (g_rectLists[planeIndex] != nullptr) {
- delete g_rectLists[planeIndex];
+ // TODO:
+ // _cursor->DonePainting();
+
+ _showList.clear();
+}
+
+void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges) {
+ uint8 clut[256];
+
+ for (int paletteIndex = 0; paletteIndex < ARRAYSIZE(palette1.colors); ++paletteIndex) {
+ int outerR = palette1.colors[paletteIndex].r;
+ int outerG = palette1.colors[paletteIndex].g;
+ int outerB = palette1.colors[paletteIndex].b;
+
+ if (styleRanges[paletteIndex] == style) {
+ int minDiff = 262140;
+ int minDiffIndex;
+
+ for (int i = 0; i < 236; ++i) {
+ if (styleRanges[i] != style) {
+ int r = palette1.colors[i].r;
+ int g = palette1.colors[i].g;
+ int b = palette1.colors[i].b;
+ int diffSquared = (outerR - r) * (outerR - r) + (outerG - g) * (outerG - g) + (outerB - b) * (outerB - b);
+ if (diffSquared < minDiff) {
+ minDiff = diffSquared;
+ minDiffIndex = i;
+ }
+ }
}
- if (g_drawLists[planeIndex] != nullptr) {
- delete g_drawLists[planeIndex];
+
+ clut[paletteIndex] = minDiffIndex;
+ }
+
+ if (style == 1 && styleRanges[paletteIndex] == 0) {
+ int minDiff = 262140;
+ int minDiffIndex;
+
+ for (int i = 0; i < 236; ++i) {
+ int r = palette2.colors[i].r;
+ int g = palette2.colors[i].g;
+ int b = palette2.colors[i].b;
+
+ int diffSquared = (outerR - r) * (outerR - r) + (outerG - g) * (outerG - g) + (outerB - b) * (outerB - b);
+ if (diffSquared < minDiff) {
+ minDiff = diffSquared;
+ minDiffIndex = i;
+ }
}
+
+ clut[paletteIndex] = minDiffIndex;
+ }
+ }
+
+ // NOTE: This is currBuffer->ptr in SCI engine
+ byte *pixels = (byte *)_currentBuffer.getPixels();
+
+ for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) {
+ byte currentValue = pixels[pixelIndex];
+ int8 styleRangeValue = styleRanges[currentValue];
+ if (styleRangeValue == -1 && styleRangeValue == style) {
+ currentValue = pixels[pixelIndex] = clut[currentValue];
+ // NOTE: In original engine this assignment happens outside of the
+ // condition, but if the branch is not followed the value is just
+ // going to be the same as it was before
+ styleRangeValue = styleRanges[currentValue];
+ }
+
+ if (
+ (styleRangeValue == 1 && styleRangeValue == style) ||
+ (styleRangeValue == 0 && style == 1)
+ ) {
+ pixels[pixelIndex] = clut[currentValue];
}
}
}
-void GfxFrameout::CalcLists(DrawList **drawLists, RectList **rectLists, SOL_Rect *rect) {
- screen.CalcLists(&visibleScreen, drawLists, rectLists, rect);
-}
-*/
-void GfxFrameout::kernelFrameout() {
- if (g_sci->_robotDecoder->isVideoLoaded()) {
- showVideo();
+
+void GfxFrameout::kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor) {
+ if (toColor > fromColor) {
return;
}
- _palette->updateForFrame();
+ for (int i = fromColor; i < toColor; ++i) {
+ _styleRanges[i] = 0;
+ }
+}
- // TODO: Tons of drawing stuff should be here, see commented out implementation above
+inline ShowStyleEntry * GfxFrameout::findShowStyleForPlane(const reg_t planeObj) const {
+ ShowStyleEntry *entry = _showStyles;
+ while (entry != nullptr) {
+ if (entry->plane == planeObj) {
+ break;
+ }
+ entry = entry->next;
+ }
- _palette->updateHardware();
+ return entry;
+}
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
- reg_t planeObject = it->object;
+inline ShowStyleEntry *GfxFrameout::deleteShowStyleInternal(ShowStyleEntry *const showStyle) {
+ ShowStyleEntry *lastEntry = nullptr;
- // Draw any plane lines, if they exist
- // These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires)
- // FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires).
- // Perhaps something is painted over them?
- for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) {
- Common::Point startPoint = it2->startPoint;
- Common::Point endPoint = it2->endPoint;
- _coordAdjuster->kernelLocalToGlobal(startPoint.x, startPoint.y, it->object);
- _coordAdjuster->kernelLocalToGlobal(endPoint.x, endPoint.y, it->object);
- _screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control);
+ for (ShowStyleEntry *testEntry = _showStyles; testEntry != nullptr; testEntry = testEntry->next) {
+ if (testEntry == showStyle) {
+ break;
}
+ lastEntry = testEntry;
+ }
- int16 planeLastPriority = it->lastPriority;
+ if (lastEntry == nullptr) {
+ _showStyles = showStyle->next;
+ lastEntry = _showStyles;
+ } else {
+ lastEntry->next = showStyle->next;
+ }
- // Update priority here, sq6 sets it w/o UpdatePlane
- int16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
+ delete[] showStyle->fadeColorRanges;
+ delete showStyle;
- it->lastPriority = planePriority;
- if (planePriority < 0) { // Plane currently not meant to be shown
- // If plane was shown before, delete plane rect
- if (planePriority != planeLastPriority)
- _paint32->fillRect(it->planeRect, 0);
- continue;
- }
+ // TODO: Verify that this is the correct entry to return
+ // for the loop in processShowStyles to work correctly
+ return lastEntry;
+}
- // There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX.
- // Since I first wrote the patch, the race has stopped occurring for me though.
- // I'll leave this for investigation later, when someone can reproduce.
- //if (it->pictureId == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes)
- if (it->pictureId == kPlanePlainColored && (it->planeBack || g_sci->getGameId() != GID_GK1))
- _paint32->fillRect(it->planeRect, it->planeBack);
+// TODO: 10-argument version is only in SCI3; argc checks are currently wrong for this version
+// and need to be fixed in future
+// TODO: SQ6 does not use 'priority' (exists since SCI2) or 'blackScreen' (exists since SCI3);
+// check to see if other versions use or if they are just always ignored
+void GfxFrameout::kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 back, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen) {
+
+ bool hasDivisions = false;
+ bool hasFadeArray = false;
+
+ // KQ7 2.0b uses a mismatched version of the Styler script (SCI2.1early script
+ // for SCI2.1mid engine), so the calls it makes to kSetShowStyle are wrong and
+ // put `divisions` where `pFadeArray` is supposed to be
+ if (getSciVersion() == SCI_VERSION_2_1_MIDDLE && g_sci->getGameId() == GID_KQ7) {
+ hasDivisions = argc > 7;
+ hasFadeArray = false;
+ divisions = argc > 7 ? pFadeArray.toSint16() : -1;
+ pFadeArray = NULL_REG;
+ } else if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
+ hasDivisions = argc > 7;
+ hasFadeArray = false;
+ } else if (getSciVersion() < SCI_VERSION_3) {
+ hasDivisions = argc > 8;
+ hasFadeArray = argc > 7;
+ } else {
+ hasDivisions = argc > 9;
+ hasFadeArray = argc > 8;
+ }
- _coordAdjuster->pictureSetDisplayArea(it->planeRect);
- // Invoking drewPicture() with an invalid picture ID in SCI32 results in
- // invalidating the palVary palette when a palVary effect is active. This
- // is quite obvious in QFG4, where the day time palette is incorrectly
- // shown when exiting the caves, and the correct night time palette
- // flashes briefly each time that kPalVaryInit is called.
- if (it->pictureId != 0xFFFF)
- _palette->drewPicture(it->pictureId);
+ bool isFadeUp;
+ int16 color;
+ if (back != -1) {
+ isFadeUp = false;
+ color = back;
+ } else {
+ isFadeUp = true;
+ color = 0;
+ }
- FrameoutList itemList;
+ if ((getSciVersion() < SCI_VERSION_2_1_MIDDLE && type == 15) || type > 15) {
+ error("Illegal show style %d for plane %04x:%04x", type, PRINT_REG(planeObj));
+ }
- createPlaneItemList(planeObject, itemList);
+ Plane *plane = _planes.findByObject(planeObj);
+ if (plane == nullptr) {
+ error("Plane %04x:%04x is not present in active planes list", PRINT_REG(planeObj));
+ }
- for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
- FrameoutEntry *itemEntry = *listIterator;
+ bool createNewEntry = true;
+ ShowStyleEntry *entry = findShowStyleForPlane(planeObj);
+ if (entry != nullptr) {
+ // TODO: SCI2.1early has different criteria for show style reuse
+ bool useExisting = true;
- if (!itemEntry->visible)
- continue;
+ if (useExisting) {
+ useExisting = entry->divisions == (hasDivisions ? divisions : _defaultDivisions[type]) && entry->unknownC == _defaultUnknownC[type];
+ }
- if (itemEntry->object.isNull()) {
- // Picture cel data
- _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
- _coordAdjuster->fromScriptToDisplay(itemEntry->picStartY, itemEntry->picStartX);
+ if (useExisting) {
+ createNewEntry = false;
+ isFadeUp = true;
+ entry->currentStep = 0;
+ } else {
+ isFadeUp = true;
+ color = entry->color;
+ deleteShowStyleInternal(entry/*, true*/);
+ entry = nullptr;
+ }
+ }
- if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY))
- drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored);
- } else {
- GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL;
- int16 dummyX = 0;
-
- if (view && view->isSci2Hires()) {
- view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
- view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
- } else if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
- _coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
- _coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX);
+ if (type > 0) {
+ if (createNewEntry) {
+ entry = new ShowStyleEntry;
+ // NOTE: SCI2.1 engine tests if allocation returned a null pointer
+ // but then only avoids setting currentStep if this is so. Since
+ // this is a nonsensical approach, we do not do that here
+ entry->currentStep = 0;
+ entry->unknownC = _defaultUnknownC[type];
+ entry->processed = false;
+ entry->divisions = hasDivisions ? divisions : _defaultDivisions[type];
+ entry->plane = planeObj;
+
+ entry->fadeColorRanges = nullptr;
+ if (hasFadeArray) {
+ // NOTE: SCI2.1mid engine does no check to verify that an array is
+ // successfully retrieved, and SegMan will cause a fatal error
+ // if we try to use a memory segment that is not an array
+ SciArray<reg_t> *table = _segMan->lookupArray(pFadeArray);
+
+ uint32 rangeCount = table->getSize();
+ entry->fadeColorRangesCount = rangeCount;
+
+ // NOTE: SCI engine code always allocates memory even if the range
+ // table has no entries, but this does not really make sense, so
+ // we avoid the allocation call in this case
+ if (rangeCount > 0) {
+ entry->fadeColorRanges = new uint16[rangeCount];
+ for (size_t i = 0; i < rangeCount; ++i) {
+ entry->fadeColorRanges[i] = table->getValue(i).toUint16();
+ }
}
+ } else {
+ entry->fadeColorRangesCount = 0;
+ }
+ }
- // Adjust according to current scroll position
- itemEntry->x -= it->planeOffsetX;
- itemEntry->y -= it->planeOffsetY;
-
- uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
- if (useInsetRect) {
- itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
- itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
- itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom));
- itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight));
- if (view && view->isSci2Hires()) {
- view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
- view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
- }
- itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
- // TODO: maybe we should clip the cels rect with this, i'm not sure
- // the only currently known usage is game menu of gk1
- } else if (view) {
- // Process global scaling, if needed.
- // TODO: Seems like SCI32 always processes global scaling for scaled objects
- // TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
- if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) &&
- !(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) &&
- (itemEntry->scaleX == itemEntry->scaleY) &&
- itemEntry->scaleX != 128)
- applyGlobalScaling(itemEntry, it->planeRect, view->getHeight(itemEntry->loopNo, itemEntry->celNo));
-
- if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
- view->getCelRect(itemEntry->loopNo, itemEntry->celNo,
- itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
- else
- view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo,
- itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX,
- itemEntry->scaleY, itemEntry->celRect);
-
- Common::Rect nsRect = itemEntry->celRect;
- // Translate back to actual coordinate within scrollable plane
- nsRect.translate(it->planeOffsetX, it->planeOffsetY);
-
- if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
- // HACK: Some (?) objects in Phantasmagoria 2 have no NS rect. Skip them for now.
- // TODO: Remove once we figure out how Phantasmagoria 2 draws objects on screen.
- if (lookupSelector(_segMan, itemEntry->object, SELECTOR(nsLeft), NULL, NULL) != kSelectorVariable)
- continue;
- }
+ // NOTE: The original engine had no nullptr check and would just crash
+ // if it got to here
+ if (entry == nullptr) {
+ error("Cannot edit non-existing ShowStyle entry");
+ }
- if (view && view->isSci2Hires()) {
- view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
- view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
- g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
- } else if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _isHiRes) {
- _coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left);
- _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right);
- g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
- }
+ entry->fadeUp = isFadeUp;
+ entry->color = color;
+ entry->nextTick = g_sci->getTickCount();
+ entry->type = type;
+ entry->animate = animate;
+ entry->delay = (seconds * 60 + entry->divisions - 1) / entry->divisions;
- // TODO: For some reason, the top left nsRect coordinates get
- // swapped in the GK1 inventory screen, investigate why.
- // This is also needed for GK1 rooms 710 and 720 (catacombs, inner and
- // outer circle), for handling the tiles and talking to Wolfgang.
- // HACK: Fix the coordinates by explicitly setting them here for GK1.
- // Also check bug #6729, for another case where this is needed.
- if (g_sci->getGameId() == GID_GK1)
- g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
- }
+ if (entry->delay == 0) {
+ if (entry->fadeColorRanges != nullptr) {
+ delete[] entry->fadeColorRanges;
+ }
+ delete entry;
+ error("ShowStyle has no duration");
+ }
- // Don't attempt to draw sprites that are outside the visible
- // screen area. An example is the random people walking in
- // Jackson Square in GK1.
- if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= _screen->getDisplayHeight() ||
- itemEntry->celRect.right < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth())
- continue;
-
- Common::Rect clipRect, translatedClipRect;
- clipRect = itemEntry->celRect;
-
- if (view && view->isSci2Hires()) {
- clipRect.clip(it->upscaledPlaneClipRect);
- translatedClipRect = clipRect;
- translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top);
- } else {
- // QFG4 passes invalid rectangles when a battle is starting
- if (!clipRect.isValidRect())
- continue;
- clipRect.clip(it->planeClipRect);
- translatedClipRect = clipRect;
- translatedClipRect.translate(it->planeRect.left, it->planeRect.top);
- }
+ if (frameOutNow) {
+ Common::Rect frameOutRect(0, 0);
+ frameOut(false, frameOutRect);
+ }
+
+ if (createNewEntry) {
+ // TODO: Implement SCI2.1early and SCI3
+ entry->next = _showStyles;
+ _showStyles = entry;
+ }
+ }
+}
- if (view) {
- if (!clipRect.isEmpty()) {
- if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
- view->draw(itemEntry->celRect, clipRect, translatedClipRect,
- itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
- else
- view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect,
- itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
+// NOTE: Different version of SCI engine support different show styles
+// SCI2 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12, 13, 14
+// SCI2.1 implements 0, 1/2/3/4/5/6/7/8/9/10/11/12/15, 13, 14
+// SCI3 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12/15, 13, 14
+// TODO: Sierra code needs to be replaced with code that uses the
+// computed entry->delay property instead of just counting divisors,
+// as the latter is machine-speed-dependent and leads to wrong
+// transition speeds
+void GfxFrameout::processShowStyles() {
+ uint32 now = g_sci->getTickCount();
+
+ bool continueProcessing;
+
+ // TODO: Change to bool? Engine uses inc to set the value to true,
+ // but there does not seem to be any reason to actually count how
+ // many times it was set
+ int doFrameOut;
+ do {
+ continueProcessing = false;
+ doFrameOut = 0;
+ ShowStyleEntry *showStyle = _showStyles;
+ while (showStyle != nullptr) {
+ bool retval = false;
+
+ if (!showStyle->animate) {
+ ++doFrameOut;
+ }
+
+ if (showStyle->nextTick < now || !showStyle->animate) {
+ // TODO: Different versions of SCI use different processors!
+ // This is the SQ6/KQ7/SCI2.1mid table.
+ switch (showStyle->type) {
+ case kShowStyleNone: {
+ retval = processShowStyleNone(showStyle);
+ break;
+ }
+ case kShowStyleHShutterOut:
+ case kShowStyleVShutterOut:
+ case kShowStyleWipeLeft:
+ case kShowStyleWipeUp:
+ case kShowStyleIrisOut:
+ case kShowStyleHShutterIn:
+ case kShowStyleVShutterIn:
+ case kShowStyleWipeRight:
+ case kShowStyleWipeDown:
+ case kShowStyleIrisIn:
+ case kShowStyle11:
+ case kShowStyle12:
+ case kShowStyleUnknown: {
+ retval = processShowStyleMorph(showStyle);
+ break;
+ }
+ case kShowStyleFadeOut: {
+ retval = processShowStyleFade(-1, showStyle);
+ break;
+ }
+ case kShowStyleFadeIn: {
+ retval = processShowStyleFade(1, showStyle);
+ break;
}
}
+ }
- // Draw text, if it exists
- if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
- g_sci->_gfxText32->drawTextBitmap(itemEntry->x, itemEntry->y, it->planeRect, itemEntry->object);
- }
+ if (!retval) {
+ continueProcessing = true;
}
- }
- for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
- if (pictureIt->object == planeObject) {
- delete[] pictureIt->pictureCels;
- pictureIt->pictureCels = 0;
+ if (retval && showStyle->processed) {
+ showStyle = deleteShowStyleInternal(showStyle);
+ } else {
+ showStyle = showStyle->next;
}
}
- }
- showCurrentScrollText();
+ if (doFrameOut) {
+ frameOut(true);
+
+ // TODO: Transitions without the “animate†flag are too
+ // fast, but the throttle value is arbitrary. Someone on
+ // real hardware probably needs to test what the actual
+ // speed of these transitions should be
+ EngineState *state = g_sci->getEngineState();
+ state->speedThrottler(33);
+ state->_throttleTrigger = true;
+ }
+ } while(continueProcessing && doFrameOut);
+}
- _screen->copyToScreen();
+bool GfxFrameout::processShowStyleNone(ShowStyleEntry *const showStyle) {
+ if (showStyle->fadeUp) {
+ _palette->setFade(100, 0, 255);
+ } else {
+ _palette->setFade(0, 0, 255);
+ }
- g_sci->getEngineState()->_throttleTrigger = true;
+ showStyle->processed = true;
+ return true;
}
-void GfxFrameout::printPlaneList(Console *con) {
- for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) {
- PlaneEntry p = *it;
- Common::String curPlaneName = _segMan->getObjectName(p.object);
- Common::Rect r = p.upscaledPlaneRect;
- Common::Rect cr = p.upscaledPlaneClipRect;
-
- con->debugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n",
- PRINT_REG(p.object), curPlaneName.c_str(),
- (int16)p.priority, (int16)p.lastPriority,
- p.planeOffsetX, p.planeOffsetY, p.pictureId,
- p.planePictureMirrored, p.planeBack);
- con->debugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n",
- r.left, r.top, r.right, r.bottom,
- cr.left, cr.top, cr.right, cr.bottom);
-
- if (p.pictureId != 0xffff && p.pictureId != 0xfffe) {
- con->debugPrintf("Pictures:\n");
-
- for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
- if (pictureIt->object == p.object) {
- con->debugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY);
- }
+bool GfxFrameout::processShowStyleMorph(ShowStyleEntry *const showStyle) {
+ palMorphFrameOut(_styleRanges, showStyle);
+ showStyle->processed = true;
+ return true;
+}
+
+// TODO: Normalise use of 'entry' vs 'showStyle'
+bool GfxFrameout::processShowStyleFade(const int direction, ShowStyleEntry *const showStyle) {
+ bool unchanged = true;
+ if (showStyle->currentStep < showStyle->divisions) {
+ int percent;
+ if (direction <= 0) {
+ percent = showStyle->divisions - showStyle->currentStep - 1;
+ } else {
+ percent = showStyle->currentStep;
+ }
+
+ percent *= 100;
+ percent /= showStyle->divisions - 1;
+
+ if (showStyle->fadeColorRangesCount > 0) {
+ for (int i = 0, len = showStyle->fadeColorRangesCount; i < len; i += 2) {
+ _palette->setFade(percent, showStyle->fadeColorRanges[i], showStyle->fadeColorRanges[i + 1]);
}
+ } else {
+ _palette->setFade(percent, 0, 255);
}
+
+ ++showStyle->currentStep;
+ showStyle->nextTick += showStyle->delay;
+ unchanged = false;
+ }
+
+ if (showStyle->currentStep >= showStyle->divisions && unchanged) {
+ if (direction > 0) {
+ showStyle->processed = true;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void GfxFrameout::kernelFrameOut(const bool shouldShowBits) {
+ if (_showStyles != nullptr) {
+ processShowStyles();
+ } else if (_palMorphIsOn) {
+ palMorphFrameOut(_styleRanges, nullptr);
+ _palMorphIsOn = false;
+ } else {
+// TODO: Window scroll
+// if (g_PlaneScroll) {
+// processScrolls();
+// }
+
+ frameOut(shouldShowBits);
+ }
+}
+
+#pragma mark -
+#pragma mark Mouse cursor
+
+reg_t GfxFrameout::kernelIsOnMe(const reg_t object, const Common::Point &position, bool checkPixel) const {
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
+ Plane *plane = _visiblePlanes.findByObject(planeObject);
+ if (plane == nullptr) {
+ return make_reg(0, 0);
+ }
+
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
+ if (screenItem == nullptr) {
+ return make_reg(0, 0);
}
+
+ // NOTE: The original engine passed a copy of the ScreenItem into isOnMe
+ // as a hack around the fact that the screen items in `_visiblePlanes`
+ // did not have their `_celObj` pointers cleared when their CelInfo was
+ // updated by `Plane::decrementScreenItemArrayCounts`. We handle this
+ // this more intelligently by clearing `_celObj` in the copy assignment
+ // operator, which is only ever called by `decrementScreenItemArrayCounts`
+ // anyway.
+ return make_reg(0, isOnMe(*screenItem, *plane, position, checkPixel));
}
-void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) {
- for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
- FrameoutEntry *e = *listIterator;
- reg_t itemPlane = readSelector(_segMan, e->object, SELECTOR(plane));
+bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const {
+
+ Common::Point scaledPosition(position);
+ mulru(scaledPosition, Ratio(_currentBuffer.screenWidth, _currentBuffer.scriptWidth), Ratio(_currentBuffer.screenHeight, _currentBuffer.scriptHeight));
+ scaledPosition.x += plane._planeRect.left;
+ scaledPosition.y += plane._planeRect.top;
+
+ if (!screenItem._screenRect.contains(scaledPosition)) {
+ return false;
+ }
+
+ if (checkPixel) {
+ CelObj &celObj = screenItem.getCelObj();
+
+ bool mirrorX = screenItem._mirrorX ^ celObj._mirrorX;
+
+ scaledPosition.x -= screenItem._scaledPosition.x;
+ scaledPosition.y -= screenItem._scaledPosition.y;
- if (planeObject == itemPlane) {
- Common::String curItemName = _segMan->getObjectName(e->object);
- Common::Rect icr = e->celRect;
- GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0;
+ mulru(scaledPosition, Ratio(celObj._scaledWidth, _currentBuffer.screenWidth), Ratio(celObj._scaledHeight, _currentBuffer.screenHeight));
- con->debugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, "
- "signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), "
- "pic %d, picX %d, picY %d, visible %d\n",
- e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(),
- e->viewId, e->loopNo, e->celNo, e->x, e->y, e->z,
- e->signal, e->scaleSignal, e->scaleX, e->scaleY,
- icr.left, icr.top, icr.right, icr.bottom,
- picId, e->picStartX, e->picStartY, e->visible);
+ if (screenItem._scale.signal != kScaleSignalNone && screenItem._scale.x && screenItem._scale.y) {
+ scaledPosition.x = scaledPosition.x * 128 / screenItem._scale.x;
+ scaledPosition.y = scaledPosition.y * 128 / screenItem._scale.y;
}
+
+ uint8 pixel = celObj.readPixel(scaledPosition.x, scaledPosition.y, mirrorX);
+ return pixel != celObj._transparentColor;
}
+
+ return true;
+}
+
+void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const {
+ const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane));
+
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("kSetNowSeen: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(screenItemObject));
+ }
+
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject);
+ if (screenItem == nullptr) {
+ error("kSetNowSeen: Screen item %04x:%04x not found in plane %04x:%04x", PRINT_REG(screenItemObject), PRINT_REG(planeObject));
+ }
+
+ Common::Rect result = screenItem->getNowSeenRect(*plane);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), result.left);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1);
+}
+
+void GfxFrameout::remapMarkRedraw() {
+ for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) {
+ Plane *p = *it;
+ p->remapMarkRedraw();
+ }
+}
+
+#pragma mark -
+#pragma mark Debugging
+
+void GfxFrameout::printPlaneListInternal(Console *con, const PlaneList &planeList) const {
+ for (PlaneList::const_iterator it = planeList.begin(); it != planeList.end(); ++it) {
+ Plane *p = *it;
+ p->printDebugInfo(con);
+ }
+}
+
+void GfxFrameout::printPlaneList(Console *con) const {
+ printPlaneListInternal(con, _planes);
+}
+
+void GfxFrameout::printVisiblePlaneList(Console *con) const {
+ printPlaneListInternal(con, _visiblePlanes);
+}
+
+void GfxFrameout::printPlaneItemListInternal(Console *con, const ScreenItemList &screenItemList) const {
+ ScreenItemList::size_type i = 0;
+ for (ScreenItemList::const_iterator sit = screenItemList.begin(); sit != screenItemList.end(); sit++) {
+ ScreenItem *screenItem = *sit;
+ con->debugPrintf("%2d: ", i++);
+ screenItem->printDebugInfo(con);
+ }
+}
+
+void GfxFrameout::printPlaneItemList(Console *con, const reg_t planeObject) const {
+ Plane *p = _planes.findByObject(planeObject);
+
+ if (p == nullptr) {
+ con->debugPrintf("Plane does not exist");
+ return;
+ }
+
+ printPlaneItemListInternal(con, p->_screenItemList);
+}
+
+void GfxFrameout::printVisiblePlaneItemList(Console *con, const reg_t planeObject) const {
+ Plane *p = _visiblePlanes.findByObject(planeObject);
+
+ if (p == nullptr) {
+ con->debugPrintf("Plane does not exist");
+ return;
+ }
+
+ printPlaneItemListInternal(con, p->_screenItemList);
}
} // End of namespace Sci
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index d1a706e8de..8ed95a00de 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -23,86 +23,132 @@
#ifndef SCI_GRAPHICS_FRAMEOUT_H
#define SCI_GRAPHICS_FRAMEOUT_H
-namespace Sci {
+#include "sci/graphics/plane32.h"
+#include "sci/graphics/screen_item32.h"
-class GfxPicture;
+namespace Sci {
+// TODO: Don't do this this way
+int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]);
-struct PlaneLineEntry {
- reg_t hunkId;
- Common::Point startPoint;
- Common::Point endPoint;
- byte color;
- byte priority;
- byte control;
+// TODO: Verify display styles and adjust names appropriately for
+// types 1 through 12 & 15 (others are correct)
+// Names should be:
+// * VShutterIn, VShutterOut
+// * HShutterIn, HShutterOut
+// * WipeLeft, WipeRight, WipeDown, WipeUp
+// * PixelDissolve
+// * ShutDown and Kill? (and Plain and Fade?)
+enum ShowStyleType /* : uint8 */ {
+ kShowStyleNone = 0,
+ kShowStyleHShutterOut = 1,
+ kShowStyleHShutterIn = 2,
+ kShowStyleVShutterOut = 3,
+ kShowStyleVShutterIn = 4,
+ kShowStyleWipeLeft = 5,
+ kShowStyleWipeRight = 6,
+ kShowStyleWipeUp = 7,
+ kShowStyleWipeDown = 8,
+ kShowStyleIrisOut = 9,
+ kShowStyleIrisIn = 10,
+ kShowStyle11 = 11,
+ kShowStyle12 = 12,
+ kShowStyleFadeOut = 13,
+ kShowStyleFadeIn = 14,
+ // TODO: Only in SCI3
+ kShowStyleUnknown = 15
};
-typedef Common::List<PlaneLineEntry> PlaneLineList;
-
-struct PlaneEntry {
- reg_t object;
- int16 priority;
- int16 lastPriority;
- int16 planeOffsetX;
- int16 planeOffsetY;
- GuiResourceId pictureId;
- Common::Rect planeRect;
- Common::Rect planeClipRect;
- Common::Rect upscaledPlaneRect;
- Common::Rect upscaledPlaneClipRect;
- bool planePictureMirrored;
- byte planeBack;
- PlaneLineList lines;
-};
+/**
+ * Show styles represent transitions applied to draw planes.
+ * One show style per plane can be active at a time.
+ */
+struct ShowStyleEntry {
+ /**
+ * The ID of the plane this show style belongs to.
+ * In SCI2.1mid (at least SQ6), per-plane transitions
+ * were removed and a single plane ID is used.
+ */
+ reg_t plane;
-typedef Common::List<PlaneEntry> PlaneList;
-
-struct FrameoutEntry {
- uint16 givenOrderNr;
- reg_t object;
- GuiResourceId viewId;
- int16 loopNo;
- int16 celNo;
- int16 x, y, z;
- int16 priority;
- uint16 signal;
- uint16 scaleSignal;
- int16 scaleX;
- int16 scaleY;
- Common::Rect celRect;
- GfxPicture *picture;
- int16 picStartX;
- int16 picStartY;
- bool visible;
-};
+ /**
+ * The type of the transition.
+ */
+ ShowStyleType type;
-typedef Common::List<FrameoutEntry *> FrameoutList;
+ // TODO: This name is probably incorrect
+ bool fadeUp;
-struct PlanePictureEntry {
- reg_t object;
- int16 startX;
- int16 startY;
- GuiResourceId pictureId;
- GfxPicture *picture;
- FrameoutEntry *pictureCels; // temporary
-};
+ /**
+ * The number of steps for the show style.
+ */
+ int16 divisions;
-typedef Common::List<PlanePictureEntry> PlanePictureList;
+ // NOTE: This property exists from SCI2 through at least
+ // SCI2.1mid but is never used in the actual processing
+ // of the styles?
+ int unknownC;
-struct ScrollTextEntry {
- reg_t bitmapHandle;
- reg_t kWindow;
- uint16 x;
- uint16 y;
-};
+ /**
+ * The color used by transitions that draw CelObjColor
+ * screen items. -1 for transitions that do not draw
+ * screen items.
+ */
+ int16 color;
+
+ // TODO: Probably uint32
+ // TODO: This field probably should be used in order to
+ // provide time-accurate processing of show styles. In the
+ // actual SCI engine (at least 2–2.1mid) it appears that
+ // style transitions are drawn “as fast as possibleâ€, one
+ // step per loop, even though this delay field exists
+ int delay;
+
+ // TODO: Probably bool, but never seems to be true?
+ int animate;
-typedef Common::Array<ScrollTextEntry> ScrollTextList;
+ /**
+ * The wall time at which the next step of the animation
+ * should execute.
+ */
+ uint32 nextTick;
-enum ViewScaleSignals32 {
- kScaleSignalDoScaling32 = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY)
- kScaleSignalUnk1 = 0x0002, // unknown
- kScaleSignalDisableGlobalScaling32 = 0x0004
+ /**
+ * During playback of the show style, the current step
+ * (out of divisions).
+ */
+ int currentStep;
+
+ /**
+ * The next show style.
+ */
+ ShowStyleEntry *next;
+
+ /**
+ * Whether or not this style has finished running and
+ * is ready for disposal.
+ */
+ bool processed;
+
+ //
+ // Engine specific properties for SCI2.1mid through SCI3
+ //
+
+ /**
+ * The number of entries in the fadeColorRanges array.
+ */
+ uint8 fadeColorRangesCount;
+
+ /**
+ * A pointer to an dynamically sized array of palette
+ * indexes, in the order [ fromColor, toColor, ... ].
+ * Only colors within this range are transitioned.
+ */
+ uint16 *fadeColorRanges;
};
+typedef Common::Array<DrawList> ScreenItemListList;
+typedef Common::Array<RectList> EraseListList;
+
class GfxCache;
class GfxCoordAdjuster32;
class GfxPaint32;
@@ -114,69 +160,293 @@ class GfxScreen;
* Roughly equivalent to GraphicsMgr in the actual SCI engine.
*/
class GfxFrameout {
+private:
+ bool _isHiRes;
+ GfxCache *_cache;
+ GfxCoordAdjuster32 *_coordAdjuster;
+ GfxPalette32 *_palette;
+ ResourceManager *_resMan;
+ GfxScreen *_screen;
+ SegManager *_segMan;
+ GfxPaint32 *_paint32;
+
public:
GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32);
~GfxFrameout();
- void kernelAddPlane(reg_t object);
- void kernelUpdatePlane(reg_t object);
- void kernelDeletePlane(reg_t object);
- void applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight);
- void kernelAddScreenItem(reg_t object);
- void kernelUpdateScreenItem(reg_t object);
- void kernelDeleteScreenItem(reg_t object);
- void deletePlaneItems(reg_t planeObject);
- FrameoutEntry *findScreenItem(reg_t object);
- int16 kernelGetHighPlanePri();
- void kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY);
- void kernelFrameout();
-
- void addPlanePicture(reg_t object, GuiResourceId pictureId, uint16 startX, uint16 startY = 0);
- void deletePlanePictures(reg_t object);
- reg_t addPlaneLine(reg_t object, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control);
- void updatePlaneLine(reg_t object, reg_t hunkId, Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control);
- void deletePlaneLine(reg_t object, reg_t hunkId);
void clear();
+ void syncWithScripts(bool addElements); // this is what Game::restore does, only needed when our ScummVM dialogs are patched in
+ void run();
- // Scroll text functions
- void addScrollTextEntry(Common::String &text, reg_t kWindow, uint16 x, uint16 y, bool replace);
- void showCurrentScrollText();
- void initScrollText(uint16 maxItems) { _maxScrollTexts = maxItems; }
- void clearScrollTexts();
- void firstScrollText() { if (_scrollTexts.size() > 0) _curScrollText = 0; }
- void lastScrollText() { if (_scrollTexts.size() > 0) _curScrollText = _scrollTexts.size() - 1; }
- void prevScrollText() { if (_curScrollText > 0) _curScrollText--; }
- void nextScrollText() { if (_curScrollText + 1 < (uint16)_scrollTexts.size()) _curScrollText++; }
- void toggleScrollText(bool show) { _showScrollText = show; }
+#pragma mark -
+#pragma mark Screen items
+private:
+ void deleteScreenItem(ScreenItem *screenItem, const reg_t plane);
+ void remapMarkRedraw();
- void printPlaneList(Console *con);
- void printPlaneItemList(Console *con, reg_t planeObject);
+public:
+ void kernelAddScreenItem(const reg_t object);
+ void kernelUpdateScreenItem(const reg_t object);
+ void kernelDeleteScreenItem(const reg_t object);
+ void kernelSetNowSeen(const reg_t screenItemObject) const;
+#pragma mark -
+#pragma mark Planes
private:
- bool _isHiRes;
+ /**
+ * The list of planes (i.e. layers) that have been added
+ * to the screen.
+ *
+ * @note This field is on `GraphicsMgr.screen` in SCI
+ * engine.
+ */
+ PlaneList _planes;
- void showVideo();
- void createPlaneItemList(reg_t planeObject, FrameoutList &itemList);
- bool isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY);
- void drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored);
+ /**
+ * Updates an existing plane with properties from the
+ * given VM object.
+ */
+ void updatePlane(Plane &plane);
- SegManager *_segMan;
- ResourceManager *_resMan;
- GfxCoordAdjuster32 *_coordAdjuster;
- GfxCache *_cache;
- GfxPalette32 *_palette;
- GfxScreen *_screen;
- GfxPaint32 *_paint32;
+public:
+ /**
+ * Creates and adds a new plane to the plane list, or
+ * cancels deletion and updates an already-existing
+ * plane if a plane matching the given plane VM object
+ * already exists within the current plane list.
+ *
+ * @note This method is on Screen in SCI engine, but it
+ * is only ever called on `GraphicsMgr.screen`.
+ */
+ void addPlane(Plane &plane);
- FrameoutList _screenItems;
- PlaneList _planes;
- PlanePictureList _planePictures;
- ScrollTextList _scrollTexts;
- int16 _curScrollText;
- bool _showScrollText;
- uint16 _maxScrollTexts;
+ /**
+ * Deletes a plane within the current plane list.
+ *
+ * @note This method is on Screen in SCI engine, but it
+ * is only ever called on `GraphicsMgr.screen`.
+ */
+ void deletePlane(Plane &plane);
- void sortPlanes();
+ const PlaneList &getPlanes() const {
+ return _planes;
+ }
+ const PlaneList &getVisiblePlanes() const {
+ return _visiblePlanes;
+ }
+ void kernelAddPlane(const reg_t object);
+ void kernelUpdatePlane(const reg_t object);
+ void kernelDeletePlane(const reg_t object);
+ void kernelMovePlaneItems(const reg_t object, const int16 deltaX, const int16 deltaY, const bool scrollPics);
+ int16 kernelGetHighPlanePri();
+
+#pragma mark -
+#pragma mark Pics
+public:
+ void kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 pictureX, const int16 pictureY, const bool mirrorX);
+
+#pragma mark -
+
+ // TODO: Remap-related?
+ void kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor);
+
+#pragma mark -
+#pragma mark Transitions
+private:
+ int *_dissolveSequenceSeeds;
+ int16 *_defaultDivisions;
+ int16 *_defaultUnknownC;
+
+ /**
+ * TODO: Documentation
+ */
+ ShowStyleEntry *_showStyles;
+
+ inline ShowStyleEntry *findShowStyleForPlane(const reg_t planeObj) const;
+ inline ShowStyleEntry *deleteShowStyleInternal(ShowStyleEntry *const showStyle);
+ void processShowStyles();
+ bool processShowStyleNone(ShowStyleEntry *showStyle);
+ bool processShowStyleMorph(ShowStyleEntry *showStyle);
+ bool processShowStyleFade(const int direction, ShowStyleEntry *showStyle);
+
+public:
+ // NOTE: This signature is taken from SCI3 Phantasmagoria 2
+ // and is valid for all implementations of SCI32
+ void kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 direction, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen);
+
+#pragma mark -
+#pragma mark Rendering
+private:
+ /**
+ * TODO: Documentation
+ */
+ int8 _styleRanges[256];
+
+ /**
+ * The internal display pixel buffer. During frameOut,
+ * this buffer is drawn into according to the draw and
+ * erase rects calculated by `calcLists`, then drawn out
+ * to the hardware surface according to the `_showList`
+ * rects (which are also calculated by `calcLists`).
+ */
+ Buffer _currentBuffer;
+
+ /**
+ * TODO: Documentation
+ */
+ bool _remapOccurred;
+
+ /**
+ * Whether or not the data in the current buffer is what
+ * is visible to the user. During rendering updates,
+ * this flag is set to false.
+ */
+ bool _frameNowVisible;
+
+ /**
+ * TODO: Document
+ * TODO: Depending upon if the engine ever modifies this
+ * rect, it may be stupid to store it separately instead
+ * of just getting width/height from GfxScreen.
+ *
+ * @note This field is on `GraphicsMgr.screen` in SCI
+ * engine.
+ */
+ Common::Rect _screenRect;
+
+ /**
+ * A list of rectangles, in display coordinates, that
+ * represent portions of the internal screen buffer that
+ * should be drawn to the hardware display surface.
+ *
+ * @note This field is on `GraphicsMgr.screen` in SCI
+ * engine.
+ */
+ RectList _showList;
+
+ /**
+ * The amount of extra overdraw that is acceptable when
+ * merging two show list rectangles together into a
+ * single larger rectangle.
+ *
+ * @note This field is on `GraphicsMgr.screen` in SCI
+ * engine.
+ */
+ int _overdrawThreshold;
+
+ /**
+ * A list of planes that are currently drawn to the
+ * hardware display surface. Used to calculate
+ * differences in plane properties between the last
+ * frame and current frame.
+ *
+ * @note This field is on `GraphicsMgr.visibleScreen` in
+ * SCI engine.
+ */
+ PlaneList _visiblePlanes;
+
+ /**
+ * Calculates the location and dimensions of dirty rects
+ * over the entire screen for rendering the next frame.
+ * The draw and erase lists in `drawLists` and
+ * `eraseLists` each represent one plane on the screen.
+ */
+ void calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &calcRect);
+
+ /**
+ * Erases the areas in the given erase list from the
+ * visible screen buffer by filling them with the color
+ * from the corresponding plane. This is an optimisation
+ * for colored-type planes only; other plane types have
+ * to be redrawn from pixel data.
+ */
+ void drawEraseList(const RectList &eraseList, const Plane &plane);
+
+ /**
+ * Draws all screen items from the given draw list to
+ * the visible screen buffer.
+ */
+ void drawScreenItemList(const DrawList &screenItemList);
+
+ /**
+ * Adds a new rectangle to the list of regions to write
+ * out to the hardware. The provided rect may be merged
+ * into an existing rectangle to reduce the number of
+ * blit operations.
+ */
+ void mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold);
+
+ /**
+ * TODO: Documentation
+ */
+ void palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle);
+
+ /**
+ * Writes the internal frame buffer out to hardware and
+ * clears the show list.
+ */
+ void showBits();
+
+public:
+ /**
+ * Whether palMorphFrameOut should be used instead of
+ * frameOut for rendering. Used by kMorphOn to
+ * explicitly enable palMorphFrameOut for one frame.
+ */
+ bool _palMorphIsOn;
+
+ inline Buffer &getCurrentBuffer() {
+ return _currentBuffer;
+ }
+
+ void kernelFrameOut(const bool showBits);
+
+ /**
+ * Updates the internal screen buffer for the next
+ * frame. If `shouldShowBits` is true, also sends the
+ * buffer to hardware.
+ */
+ void frameOut(const bool shouldShowBits, const Common::Rect &rect = Common::Rect());
+
+ /**
+ * Modifies the raw pixel data for the next frame with
+ * new palette indexes based on matched style ranges.
+ */
+ void alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges);
+
+ // NOTE: This function is used within ScreenItem subsystem and assigned
+ // to various booleanish fields that seem to represent the state of the
+ // screen item (created, updated, deleted). In GK1/DOS, Phant1/m68k,
+ // SQ6/DOS, SQ6/Win, and Phant2/Win, this function simply returns 1. If
+ // you know of any game/environment where this function returns some
+ // value other than 1, or if you used to work at Sierra and can explain
+ // why this is a thing (and if anyone needs to care about it), please
+ // open a ticket!!
+ inline int getScreenCount() const {
+ return 1;
+ };
+
+#pragma mark -
+#pragma mark Mouse cursor
+private:
+ /**
+ * Determines whether or not the point given by
+ * `position` is inside of the given screen item.
+ */
+ bool isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const;
+
+public:
+ reg_t kernelIsOnMe(const reg_t object, const Common::Point &position, const bool checkPixel) const;
+
+#pragma mark -
+#pragma mark Debugging
+public:
+ void printPlaneList(Console *con) const;
+ void printVisiblePlaneList(Console *con) const;
+ void printPlaneListInternal(Console *con, const PlaneList &planeList) const;
+ void printPlaneItemList(Console *con, const reg_t planeObject) const;
+ void printVisiblePlaneItemList(Console *con, const reg_t planeObject) const;
+ void printPlaneItemListInternal(Console *con, const ScreenItemList &screenItemList) const;
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index e5b9f2aaed..19dddd74b8 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -26,6 +26,11 @@
#include "common/endian.h" // for READ_LE_UINT16
#include "common/rect.h"
#include "common/serializer.h"
+#ifdef ENABLE_SCI32
+#include "common/rational.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#endif
#include "sci/engine/vm_types.h"
namespace Sci {
@@ -45,6 +50,9 @@ typedef int16 TextAlignment;
#define PORTS_FIRSTWINDOWID 2
#define PORTS_FIRSTSCRIPTWINDOWID 3
+#ifdef ENABLE_SCI32
+#define PRINT_RECT(x) (x).left,(x).top,(x).right,(x).bottom
+#endif
struct Port {
uint16 id;
@@ -118,6 +126,102 @@ struct Window : public Port, public Common::Serializable {
}
};
+#ifdef ENABLE_SCI32
+/**
+ * Multiplies a rectangle by two ratios with default
+ * rounding. Modifies the rect directly.
+ */
+inline void mul(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY) {
+ rect.left = (rect.left * ratioX).toInt();
+ rect.top = (rect.top * ratioY).toInt();
+ rect.right = (rect.right * ratioX).toInt();
+ rect.bottom = (rect.bottom * ratioY).toInt();
+}
+
+/**
+ * Multiplies a rectangle by two ratios with default
+ * rounding. Modifies the rect directly. Uses inclusive
+ * rectangle rounding.
+ */
+inline void mulinc(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY) {
+ rect.left = (rect.left * ratioX).toInt();
+ rect.top = (rect.top * ratioY).toInt();
+ rect.right = ((rect.right - 1) * ratioX).toInt() + 1;
+ rect.bottom = ((rect.bottom - 1) * ratioY).toInt() + 1;
+}
+
+/**
+ * Multiplies a number by a rational number, rounding up to
+ * the nearest whole number.
+ */
+inline int mulru(const int value, const Common::Rational &ratio, const int extra = 0) {
+ int num = (value + extra) * ratio.getNumerator();
+ int result = num / ratio.getDenominator();
+ if (num > ratio.getDenominator() && num % ratio.getDenominator()) {
+ ++result;
+ }
+ return result - extra;
+}
+
+/**
+ * Multiplies a point by two rational numbers for X and Y,
+ * rounding up to the nearest whole number. Modifies the
+ * point directly.
+ */
+inline void mulru(Common::Point &point, const Common::Rational &ratioX, const Common::Rational &ratioY) {
+ point.x = mulru(point.x, ratioX);
+ point.y = mulru(point.y, ratioY);
+}
+
+/**
+ * Multiplies a point by two rational numbers for X and Y,
+ * rounding up to the nearest whole number. Modifies the
+ * rect directly.
+ */
+inline void mulru(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY, const int extra) {
+ rect.left = mulru(rect.left, ratioX);
+ rect.top = mulru(rect.top, ratioY);
+ rect.right = mulru(rect.right - 1, ratioX, extra) + 1;
+ rect.bottom = mulru(rect.bottom - 1, ratioY, extra) + 1;
+}
+
+struct Buffer : public Graphics::Surface {
+ uint16 screenWidth;
+ uint16 screenHeight;
+ uint16 scriptWidth;
+ uint16 scriptHeight;
+
+ Buffer(const uint16 width, const uint16 height, uint8 *const pix) :
+ screenWidth(width),
+ screenHeight(height),
+ // TODO: These values are not correct for all games. Script
+ // dimensions were hard-coded per game in the original
+ // interpreter. Search all games for their internal script
+ // dimensions and set appropriately. (This code does not
+ // appear to exist at all in SCI3, which uses 640x480.)
+ scriptWidth(320),
+ scriptHeight(200) {
+ init(width, height, width, pix, Graphics::PixelFormat::createFormatCLUT8());
+ }
+
+ void clear(const uint8 value) {
+ memset(pixels, value, w * h);
+ }
+
+ inline uint8 *getAddress(const uint16 x, const uint16 y) {
+ return (uint8 *)getBasePtr(x, y);
+ }
+
+ inline uint8 *getAddressSimRes(const uint16 x, const uint16 y) {
+ return (uint8*)pixels + (y * w * screenHeight / scriptHeight) + (x * screenWidth / scriptWidth);
+ }
+
+ bool isNull() {
+ return pixels == nullptr;
+ }
+};
+#endif
+
struct Color {
byte used;
byte r, g, b;
@@ -146,7 +250,7 @@ struct Palette {
}
}
- return false;
+ return true;
}
inline bool operator!=(const Palette &other) const {
return !(*this == other);
diff --git a/engines/sci/graphics/lists32.h b/engines/sci/graphics/lists32.h
new file mode 100644
index 0000000000..4f74c77325
--- /dev/null
+++ b/engines/sci/graphics/lists32.h
@@ -0,0 +1,192 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SCI_GRAPHICS_LISTS32_H
+#define SCI_GRAPHICS_LISTS32_H
+
+#include "common/array.h"
+
+namespace Sci {
+
+/**
+ * StablePointerArray holds pointers in a fixed-size array
+ * that maintains position of erased items until `pack` is
+ * called. It is used by DrawList, RectList, and
+ * ScreenItemList. StablePointerArray takes ownership of
+ * all pointers that are passed to it and deletes them when
+ * calling `erase` or when destroying the
+ * StablePointerArray.
+ */
+template<class T, uint N>
+class StablePointerArray {
+ uint _size;
+ T *_items[N];
+
+public:
+ typedef T **iterator;
+ typedef T *const *const_iterator;
+ typedef T *value_type;
+ typedef uint size_type;
+
+ StablePointerArray() : _size(0), _items() {}
+ StablePointerArray(const StablePointerArray &other) : _size(other._size) {
+ for (size_type i = 0; i < _size; ++i) {
+ if (other._items[i] == nullptr) {
+ _items[i] = nullptr;
+ } else {
+ _items[i] = new T(*other._items[i]);
+ }
+ }
+ }
+ ~StablePointerArray() {
+ for (size_type i = 0; i < _size; ++i) {
+ delete _items[i];
+ }
+ }
+
+ void operator=(const StablePointerArray &other) {
+ clear();
+ _size = other._size;
+ for (size_type i = 0; i < _size; ++i) {
+ if (other._items[i] == nullptr) {
+ _items[i] = nullptr;
+ } else {
+ _items[i] = new T(*other._items[i]);
+ }
+ }
+ }
+
+ T *const &operator[](size_type index) const {
+ assert(index < _size);
+ return _items[index];
+ }
+
+ T *&operator[](size_type index) {
+ assert(index < _size);
+ return _items[index];
+ }
+
+ /**
+ * Adds a new pointer to the array.
+ */
+ void add(T *item) {
+ assert(_size < N);
+ _items[_size++] = item;
+ }
+
+ iterator begin() {
+ return _items;
+ }
+
+ const_iterator begin() const {
+ return _items;
+ }
+
+ void clear() {
+ for (size_type i = 0; i < _size; ++i) {
+ delete _items[i];
+ _items[i] = nullptr;
+ }
+
+ _size = 0;
+ }
+
+ iterator end() {
+ return _items + _size;
+ }
+
+ const_iterator end() const {
+ return _items + _size;
+ }
+
+ /**
+ * Erases the object pointed to by the given iterator.
+ */
+ void erase(T *item) {
+ for (iterator it = begin(); it != end(); ++it) {
+ if (*it == item) {
+ delete *it;
+ *it = nullptr;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Erases the object pointed to by the given iterator.
+ */
+ void erase(iterator &it) {
+ assert(it >= _items && it < _items + _size);
+ delete *it;
+ *it = nullptr;
+ }
+
+ /**
+ * Erases the object pointed to at the given index.
+ */
+ void erase_at(size_type index) {
+ assert(index < _size);
+
+ delete _items[index];
+ _items[index] = nullptr;
+ }
+
+ /**
+ * Removes freed pointers from the pointer list.
+ */
+ size_type pack() {
+ iterator freePtr = begin();
+ size_type newSize = 0;
+
+ for (iterator it = begin(), last = end(); it != last; ++it) {
+ if (*it != nullptr) {
+ *freePtr = *it;
+ ++freePtr;
+ ++newSize;
+ }
+ }
+
+ _size = newSize;
+ return newSize;
+ }
+
+ /**
+ * The number of populated slots in the array. The size
+ * of the array will only go down once `pack` is called.
+ */
+ size_type size() const {
+ return _size;
+ }
+};
+
+template<typename T>
+class FindByObject {
+ const reg_t &_object;
+public:
+ FindByObject(const reg_t &object) : _object(object) {}
+ bool operator()(const T entry) const {
+ return entry && entry->_object == _object;
+ }
+};
+
+} // End of namespace Sci
+#endif
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index 106924ecd3..1514ad838f 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -32,6 +32,7 @@
#include "sci/graphics/cache.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/view.h"
@@ -103,9 +104,6 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen)
default:
error("GfxPalette: Unknown view type");
}
-
- _remapOn = false;
- resetRemapping();
}
GfxPalette::~GfxPalette() {
@@ -310,7 +308,7 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) {
uint32 systime = _sysPalette.timestamp;
if (force || newPalette->timestamp != systime) {
- // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes
+ // SCI1.1+ doesn't do real merging anymore, but simply copying over the used colors from other palettes
// There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo)
if ((forceRealMerge) || (_useMerging))
_sysPaletteChanged |= merge(newPalette, force, forceRealMerge);
@@ -336,79 +334,6 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) {
}
}
-byte GfxPalette::remapColor(byte remappedColor, byte screenColor) {
- assert(_remapOn);
- if (_remappingType[remappedColor] == kRemappingByRange)
- return _remappingByRange[screenColor];
- else if (_remappingType[remappedColor] == kRemappingByPercent)
- return _remappingByPercent[screenColor];
- else
- error("remapColor(): Color %d isn't remapped", remappedColor);
-
- return 0; // should never reach here
-}
-
-void GfxPalette::resetRemapping() {
- _remapOn = false;
- _remappingPercentToSet = 0;
-
- for (int i = 0; i < 256; i++) {
- _remappingType[i] = kRemappingNone;
- _remappingByPercent[i] = i;
- _remappingByRange[i] = i;
- }
-}
-
-void GfxPalette::setRemappingPercent(byte color, byte percent) {
- _remapOn = true;
-
- // We need to defer the setup of the remapping table every time the screen
- // palette is changed, so that kernelFindColor() can find the correct
- // colors. Set it once here, in case the palette stays the same and update
- // it on each palette change by copySysPaletteToScreen().
- _remappingPercentToSet = percent;
-
- for (int i = 0; i < 256; i++) {
- byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100;
- byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100;
- byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100;
- _remappingByPercent[i] = kernelFindColor(r, g, b);
- }
-
- _remappingType[color] = kRemappingByPercent;
-}
-
-void GfxPalette::setRemappingPercentGray(byte color, byte percent) {
- _remapOn = true;
-
- // We need to defer the setup of the remapping table every time the screen
- // palette is changed, so that kernelFindColor() can find the correct
- // colors. Set it once here, in case the palette stays the same and update
- // it on each palette change by copySysPaletteToScreen().
- _remappingPercentToSet = percent;
-
- // Note: This is not what the original does, but the results are the same visually
- for (int i = 0; i < 256; i++) {
- byte rComponent = (byte)(_sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100);
- byte gComponent = (byte)(_sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100);
- byte bComponent = (byte)(_sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100);
- byte luminosity = rComponent + gComponent + bComponent;
- _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity);
- }
-
- _remappingType[color] = kRemappingByPercent;
-}
-
-void GfxPalette::setRemappingRange(byte color, byte from, byte to, byte base) {
- _remapOn = true;
-
- for (int i = from; i <= to; i++) {
- _remappingByRange[i] = i + base;
- }
-
- _remappingType[color] = kRemappingByRange;
-}
-
bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) {
bool paletteChanged = false;
@@ -589,15 +514,8 @@ void GfxPalette::copySysPaletteToScreen() {
}
}
- // Check if we need to reset remapping by percent with the new colors.
- if (_remappingPercentToSet) {
- for (int i = 0; i < 256; i++) {
- byte r = _sysPalette.colors[i].r * _remappingPercentToSet / 100;
- byte g = _sysPalette.colors[i].g * _remappingPercentToSet / 100;
- byte b = _sysPalette.colors[i].b * _remappingPercentToSet / 100;
- _remappingByPercent[i] = kernelFindColor(r, g, b);
- }
- }
+ if (g_sci->_gfxRemap16)
+ g_sci->_gfxRemap16->updateRemapping();
g_system->getPaletteManager()->setPalette(bpal, 0, 256);
}
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 61a8d36cb9..7335dc59d0 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -35,12 +35,6 @@ class GfxScreen;
#define SCI_PALETTE_MATCH_PERFECT 0x8000
#define SCI_PALETTE_MATCH_COLORMASK 0xFF
-enum ColorRemappingType {
- kRemappingNone = 0,
- kRemappingByRange = 1,
- kRemappingByPercent = 2
-};
-
/**
* Palette class, handles palette operations like changing intensity, setting up the palette, merging different palettes
*/
@@ -64,15 +58,6 @@ public:
void getSys(Palette *pal);
uint16 getTotalColorCount() const { return _totalScreenColors; }
- void resetRemapping();
- void setRemappingPercent(byte color, byte percent);
- void setRemappingPercentGray(byte color, byte percent);
- void setRemappingRange(byte color, byte from, byte to, byte base);
- bool isRemapped(byte color) const {
- return _remapOn && (_remappingType[color] != kRemappingNone);
- }
- byte remapColor(byte remappedColor, byte screenColor);
-
void setOnScreen();
void copySysPaletteToScreen();
@@ -138,12 +123,6 @@ protected:
int _palVarySignal;
uint16 _totalScreenColors;
- bool _remapOn;
- ColorRemappingType _remappingType[256];
- byte _remappingByPercent[256];
- byte _remappingByRange[256];
- uint16 _remappingPercentToSet;
-
void loadMacIconBarPalette();
byte *_macClut;
};
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index e330b5620b..6844011675 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -28,29 +28,41 @@
#include "sci/event.h"
#include "sci/resource.h"
#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
namespace Sci {
-
+
GfxPalette32::GfxPalette32(ResourceManager *resMan, GfxScreen *screen)
: GfxPalette(resMan, screen),
+ // Palette versioning
+ _version(1),
+ _versionUpdated(false),
+ _sourcePalette(_sysPalette),
+ _nextPalette(_sysPalette),
+ // Clut
_clutTable(nullptr),
- // Palette cycling
- _cyclers(), _cycleMap(),
// Palette varying
- _sourcePalette(_sysPalette), _nextPalette(_sysPalette),
- _varyTime(0), _varyDirection(0), _varyTargetPercent(0),
- _varyTargetPalette(nullptr), _varyStartPalette(nullptr),
- _varyFromColor(0), _varyToColor(255), _varyNumTimesPaused(0),
- _varyPercent(_varyTargetPercent), _varyLastTick(0),
- // Palette versioning
- _version(1), _versionUpdated(false) {
- memset(_fadeTable, 100, sizeof(_fadeTable));
-
+ _varyStartPalette(nullptr),
+ _varyTargetPalette(nullptr),
+ _varyFromColor(0),
+ _varyToColor(255),
+ _varyLastTick(0),
+ _varyTime(0),
+ _varyDirection(0),
+ _varyTargetPercent(0),
+ _varyNumTimesPaused(0),
+ // Palette cycling
+ _cyclers(),
+ _cycleMap() {
+ _varyPercent = _varyTargetPercent;
+ for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) {
+ _fadeTable[i] = 100;
+ }
// NOTE: In SCI engine, the palette manager constructor loads
// the default palette, but in ScummVM this initialisation
// is performed by SciEngine::run; see r49523 for details
- }
+}
GfxPalette32::~GfxPalette32() {
unloadClut();
@@ -59,13 +71,17 @@ GfxPalette32::~GfxPalette32() {
}
inline void mergePaletteInternal(Palette *const to, const Palette *const from) {
- for (int i = 0; i < ARRAYSIZE(to->colors); ++i) {
+ for (int i = 0, len = ARRAYSIZE(to->colors); i < len; ++i) {
if (from->colors[i].used) {
to->colors[i] = from->colors[i];
}
}
}
+const Palette *GfxPalette32::getNextPalette() const {
+ return &_nextPalette;
+}
+
void GfxPalette32::submit(Palette &palette) {
// TODO: The resource manager in SCI32 retains raw data of palettes from
// the ResourceManager (ResourceMgr) through SegManager (MemoryMgr), and
@@ -205,17 +221,22 @@ int16 GfxPalette32::matchColor(const byte r, const byte g, const byte b, const i
return bestIndex;
}
-void GfxPalette32::updateForFrame() {
+bool GfxPalette32::updateForFrame() {
applyAll();
_versionUpdated = false;
- // TODO: Implement remapping
- // g_sci->_gfxFrameout->remapAllTables(_nextPalette != _sysPalette);
+ return g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette);
+}
+
+void GfxPalette32::updateFFrame() {
+ for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) {
+ _nextPalette.colors[i] = _sourcePalette.colors[i];
+ }
+ _versionUpdated = false;
+ g_sci->_gfxRemap32->remapAllTables(_nextPalette != _sysPalette);
}
void GfxPalette32::updateHardware() {
if (_sysPalette == _nextPalette) {
- // TODO: This condition has never been encountered yet
- debug("Skipping hardware update because palettes are identical");
return;
}
@@ -246,9 +267,8 @@ void GfxPalette32::applyAll() {
applyFade();
}
-//
-// Clut
-//
+#pragma mark -
+#pragma mark Colour look-up
bool GfxPalette32::loadClut(uint16 clutId) {
// loadClut() will load a color lookup table from a clu file and set
@@ -300,9 +320,8 @@ void GfxPalette32::unloadClut() {
_clutTable = nullptr;
}
-//
-// Palette vary
-//
+#pragma mark -
+#pragma mark Varying
inline bool GfxPalette32::createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const {
Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, paletteId), false);
@@ -409,7 +428,7 @@ void GfxPalette32::setVaryPercent(const int16 percent, const int time, const int
}
int16 GfxPalette32::getVaryPercent() const {
- return abs(_varyPercent);
+ return ABS(_varyPercent);
}
void GfxPalette32::varyOff() {
@@ -542,9 +561,8 @@ void GfxPalette32::applyVary() {
}
}
-//
-// Palette cycling
-//
+#pragma mark -
+#pragma mark Cycling
inline void GfxPalette32::clearCycleMap(const uint16 fromColor, const uint16 numColorsToClear) {
bool *mapEntry = _cycleMap + fromColor;
@@ -677,14 +695,8 @@ void GfxPalette32::cycleAllOn() {
}
void GfxPalette32::cycleAllPause() {
- // TODO: The SCI SQ6 cycleAllPause function does not seem to perform
- // nullptr checking?? This would definitely cause null pointer
- // dereference in SCI code. I have not seen anything actually call
- // this function yet, so it is possible it is just unused and broken
- // in SCI SQ6. This assert exists so that if this function is called,
- // it is noticed and can be rechecked in the actual engine.
- // Obviously this code *does* do nullptr checks instead of crashing. :)
- assert(0);
+ // NOTE: The original engine did not check for null pointers in the
+ // palette cyclers pointer array.
for (int i = 0, len = ARRAYSIZE(_cyclers); i < len; ++i) {
PalCycler *cycler = _cyclers[i];
if (cycler != nullptr) {
@@ -768,11 +780,16 @@ void GfxPalette32::applyCycles() {
}
}
-//
-// Palette fading
-//
+#pragma mark -
+#pragma mark Fading
-void GfxPalette32::setFade(uint8 percent, uint8 fromColor, uint16 numColorsToFade) {
+// NOTE: There are some game scripts (like SQ6 Sierra logo and main menu) that call
+// setFade with numColorsToFade set to 256, but other parts of the engine like
+// processShowStyleNone use 255 instead of 256. It is not clear if this is because
+// the last palette entry is intentionally left unmodified, or if this is a bug
+// in the engine. It certainly seems confused because all other places that accept
+// color ranges typically receive values in the range of 0–255.
+void GfxPalette32::setFade(uint16 percent, uint8 fromColor, uint16 numColorsToFade) {
if (fromColor > numColorsToFade) {
return;
}
@@ -794,9 +811,10 @@ void GfxPalette32::applyFade() {
Color &color = _nextPalette.colors[i];
- color.r = (int16)color.r * _fadeTable[i] / 100;
- color.g = (int16)color.g * _fadeTable[i] / 100;
- color.b = (int16)color.b * _fadeTable[i] / 100;
+ color.r = MIN(255, (uint16)color.r * _fadeTable[i] / 100);
+ color.g = MIN(255, (uint16)color.g * _fadeTable[i] / 100);
+ color.b = MIN(255, (uint16)color.b * _fadeTable[i] / 100);
}
}
-}
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index 8744687e4c..a5450776dc 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -25,6 +25,7 @@
#include "sci/graphics/palette.h"
+namespace Sci {
enum PalCyclerDirection {
PalCycleBackward = 0,
PalCycleForward = 1
@@ -71,188 +72,213 @@ struct PalCycler {
uint16 numTimesPaused;
};
-namespace Sci {
- class GfxPalette32 : public GfxPalette {
- public:
- GfxPalette32(ResourceManager *resMan, GfxScreen *screen);
- ~GfxPalette32();
-
- protected:
- /**
- * The palette revision version. Increments once per game
- * loop that changes the source palette. TODO: Possibly
- * other areas also change _version, double-check once it
- * is all implemented.
- */
- uint32 _version;
-
- /**
- * Whether or not the palette manager version was updated
- * during this loop.
- */
- bool _versionUpdated;
-
- /**
- * The unmodified source palette loaded by kPalette. Additional
- * palette entries may be mixed into the source palette by
- * CelObj objects, which contain their own palettes.
- */
- Palette _sourcePalette;
-
- /**
- * The palette to be used when the hardware is next updated.
- * On update, _nextPalette is transferred to _sysPalette.
- */
- Palette _nextPalette;
-
- // SQ6 defines 10 cyclers
- PalCycler *_cyclers[10];
-
- /**
- * The cycle map is used to detect overlapping cyclers.
- * According to SCI engine code, when two cyclers overlap,
- * a fatal error has occurred and the engine will display
- * an error and then exit.
- */
- bool _cycleMap[256];
- inline void clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
- inline void setCycleMap(uint16 fromColor, uint16 numColorsToClear);
- inline PalCycler *getCycler(uint16 fromColor);
-
- /**
- * The fade table records the expected intensity level of each pixel
- * in the palette that will be displayed on the next frame.
- */
- byte _fadeTable[256];
-
- /**
- * An optional lookup table used to remap RGB565 colors to a palette
- * index. Used by Phantasmagoria 2 in 8-bit color environments.
- */
- byte *_clutTable;
-
- /**
- * An optional palette used to describe the source colors used
- * in a palette vary operation. If this palette is not specified,
- * sourcePalette is used instead.
- */
- Palette *_varyStartPalette;
-
- /**
- * An optional palette used to describe the target colors used
- * in a palette vary operation.
- */
- Palette *_varyTargetPalette;
-
- /**
- * The minimum palette index that has been varied from the
- * source palette. 0–255
- */
- uint8 _varyFromColor;
-
- /**
- * The maximum palette index that is has been varied from the
- * source palette. 0-255
- */
- uint8 _varyToColor;
-
- /**
- * The tick at the last time the palette vary was updated.
- */
- uint32 _varyLastTick;
-
- /**
- * TODO: Document
- * The velocity of change in percent?
- */
- int _varyTime;
-
- /**
- * TODO: Better documentation
- * The direction of change, -1, 0, or 1.
- */
- int16 _varyDirection;
-
- /**
- * The amount, in percent, that the vary color is currently
- * blended into the source color.
- */
- int16 _varyPercent;
-
- /**
- * The target amount that a vary color will be blended into
- * the source color.
- */
- int16 _varyTargetPercent;
-
- /**
- * The number of time palette varying has been paused.
- */
- uint16 _varyNumTimesPaused;
-
- /**
- * Submits a palette to display. Entries marked as “used†in the
- * submitted palette are merged into the existing entries of
- * _sourcePalette.
- */
- void submit(Palette &palette);
-
- public:
- virtual void saveLoadWithSerializer(Common::Serializer &s) override;
-
- bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
- int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
- void set(Palette *newPalette, bool force, bool forceRealMerge = false) override;
- int16 matchColor(const byte matchRed, const byte matchGreen, const byte matchBlue, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable);
-
- void updateForFrame();
- void updateHardware();
- void applyAll();
-
- bool loadClut(uint16 clutId);
- byte matchClutColor(uint16 color);
- void unloadClut();
-
- void kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
- void kernelPalVaryMergeTarget(const GuiResourceId paletteId);
- void kernelPalVarySetTarget(const GuiResourceId paletteId);
- void kernelPalVarySetStart(const GuiResourceId paletteId);
- void kernelPalVaryMergeStart(const GuiResourceId paletteId);
- virtual void kernelPalVaryPause(bool pause) override;
-
- void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
- void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate);
- int16 getVaryPercent() const;
- void varyOff();
- void mergeTarget(const Palette *const palette);
- void varyPause();
- void varyOn();
- void setVaryTime(const int time);
- void setTarget(const Palette *const palette);
- void setStart(const Palette *const palette);
- void mergeStart(const Palette *const palette);
- private:
- bool createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const;
- Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const;
- void setVaryTimeInternal(const int16 percent, const int time);
- public:
- void applyVary();
-
- void setCycle(const uint8 fromColor, const uint8 toColor, const int16 direction, const int16 delay);
- void doCycle(const uint8 fromColor, const int16 speed);
- void cycleOn(const uint8 fromColor);
- void cyclePause(const uint8 fromColor);
- void cycleAllOn();
- void cycleAllPause();
- void cycleOff(const uint8 fromColor);
- void cycleAllOff();
- void applyAllCycles();
- void applyCycles();
-
- void setFade(const uint8 percent, const uint8 fromColor, const uint16 toColor);
- void fadeOff();
- void applyFade();
- };
-}
+class GfxPalette32 : public GfxPalette {
+public:
+ GfxPalette32(ResourceManager *resMan, GfxScreen *screen);
+ ~GfxPalette32();
+
+private:
+ // NOTE: currentPalette in SCI engine is called _sysPalette
+ // here.
+
+ /**
+ * The palette revision version. Increments once per game
+ * loop that changes the source palette. TODO: Possibly
+ * other areas also change _version, double-check once it
+ * is all implemented.
+ */
+ uint32 _version;
+
+ /**
+ * Whether or not the palette manager version was updated
+ * during this loop.
+ */
+ bool _versionUpdated;
+
+ /**
+ * The unmodified source palette loaded by kPalette. Additional
+ * palette entries may be mixed into the source palette by
+ * CelObj objects, which contain their own palettes.
+ */
+ Palette _sourcePalette;
+
+ /**
+ * The palette to be used when the hardware is next updated.
+ * On update, _nextPalette is transferred to _sysPalette.
+ */
+ Palette _nextPalette;
+
+ bool createPaletteFromResourceInternal(const GuiResourceId paletteId, Palette *const out) const;
+ Palette getPaletteFromResourceInternal(const GuiResourceId paletteId) const;
+
+public:
+ virtual void saveLoadWithSerializer(Common::Serializer &s) override;
+ const Palette *getNextPalette() const;
+
+ bool kernelSetFromResource(GuiResourceId resourceId, bool force) override;
+ int16 kernelFindColor(uint16 r, uint16 g, uint16 b) override;
+ void set(Palette *newPalette, bool force, bool forceRealMerge = false) override;
+ int16 matchColor(const byte matchRed, const byte matchGreen, const byte matchBlue, const int defaultDifference, int &lastCalculatedDifference, const bool *const matchTable);
+
+ /**
+ * Submits a palette to display. Entries marked as “used†in the
+ * submitted palette are merged into the existing entries of
+ * _sourcePalette.
+ */
+ void submit(Palette &palette);
+
+ bool updateForFrame();
+ void updateFFrame();
+ void updateHardware();
+ void applyAll();
+
+#pragma mark -
+#pragma mark color look-up
+private:
+ /**
+ * An optional lookup table used to remap RGB565 colors to a palette
+ * index. Used by Phantasmagoria 2 in 8-bit color environments.
+ */
+ byte *_clutTable;
+
+public:
+ bool loadClut(uint16 clutId);
+ byte matchClutColor(uint16 color);
+ void unloadClut();
+
+#pragma mark -
+#pragma mark Varying
+private:
+ /**
+ * An optional palette used to describe the source colors used
+ * in a palette vary operation. If this palette is not specified,
+ * sourcePalette is used instead.
+ */
+ Palette *_varyStartPalette;
+
+ /**
+ * An optional palette used to describe the target colors used
+ * in a palette vary operation.
+ */
+ Palette *_varyTargetPalette;
+
+ /**
+ * The minimum palette index that has been varied from the
+ * source palette. 0–255
+ */
+ uint8 _varyFromColor;
+
+ /**
+ * The maximum palette index that is has been varied from the
+ * source palette. 0-255
+ */
+ uint8 _varyToColor;
+
+ /**
+ * The tick at the last time the palette vary was updated.
+ */
+ uint32 _varyLastTick;
+
+ /**
+ * The amount of time to elapse, in ticks, between each cycle
+ * of a palette vary animation.
+ */
+ int _varyTime;
+
+ /**
+ * The direction of change: -1, 0, or 1.
+ */
+ int16 _varyDirection;
+
+ /**
+ * The amount, in percent, that the vary color is currently
+ * blended into the source color.
+ */
+ int16 _varyPercent;
+
+ /**
+ * The target amount that a vary color will be blended into
+ * the source color.
+ */
+ int16 _varyTargetPercent;
+
+ /**
+ * The number of time palette varying has been paused.
+ */
+ uint16 _varyNumTimesPaused;
+
+public:
+ void kernelPalVarySet(const GuiResourceId paletteId, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
+ void kernelPalVaryMergeTarget(const GuiResourceId paletteId);
+ void kernelPalVarySetTarget(const GuiResourceId paletteId);
+ void kernelPalVarySetStart(const GuiResourceId paletteId);
+ void kernelPalVaryMergeStart(const GuiResourceId paletteId);
+ virtual void kernelPalVaryPause(bool pause) override;
+
+ void setVary(const Palette *const targetPalette, const int16 percent, const int time, const int16 fromColor, const int16 toColor);
+ void setVaryPercent(const int16 percent, const int time, const int16 fromColor, const int16 fromColorAlternate);
+ int16 getVaryPercent() const;
+ void varyOff();
+ void mergeTarget(const Palette *const palette);
+ void varyPause();
+ void varyOn();
+ void setVaryTime(const int time);
+ void setTarget(const Palette *const palette);
+ void setStart(const Palette *const palette);
+ void mergeStart(const Palette *const palette);
+ void setVaryTimeInternal(const int16 percent, const int time);
+ void applyVary();
+
+#pragma mark -
+#pragma mark Cycling
+private:
+ // SQ6 defines 10 cyclers
+ PalCycler *_cyclers[10];
+
+ /**
+ * The cycle map is used to detect overlapping cyclers.
+ * According to SCI engine code, when two cyclers overlap,
+ * a fatal error has occurred and the engine will display
+ * an error and then exit.
+ */
+ bool _cycleMap[256];
+ inline void clearCycleMap(uint16 fromColor, uint16 numColorsToClear);
+ inline void setCycleMap(uint16 fromColor, uint16 numColorsToClear);
+ inline PalCycler *getCycler(uint16 fromColor);
+
+public:
+ void setCycle(const uint8 fromColor, const uint8 toColor, const int16 direction, const int16 delay);
+ void doCycle(const uint8 fromColor, const int16 speed);
+ void cycleOn(const uint8 fromColor);
+ void cyclePause(const uint8 fromColor);
+ void cycleAllOn();
+ void cycleAllPause();
+ void cycleOff(const uint8 fromColor);
+ void cycleAllOff();
+ void applyAllCycles();
+ void applyCycles();
+ const bool *getCyclemap() { return _cycleMap; }
+
+#pragma mark -
+#pragma mark Fading
+private:
+ /**
+ * The fade table records the expected intensity level of each pixel
+ * in the palette that will be displayed on the next frame.
+ */
+ uint16 _fadeTable[256];
+
+public:
+ /**
+ * Sets the intensity level for a range of palette
+ * entries. An intensity of zero indicates total
+ * darkness. Intensity may be set to over 100 percent.
+ */
+ void setFade(const uint16 percent, const uint8 fromColor, const uint16 toColor);
+ void fadeOff();
+ void applyFade();
+};
+
+} // End of namespace Sci
#endif
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index d7ef84dc1e..2eab391afd 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -209,12 +209,12 @@ void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictu
}
// Header
- // [headerSize:WORD] [celCount:BYTE] [Unknown:BYTE] [Unknown:WORD] [paletteOffset:DWORD] [Unknown:DWORD]
+ // 0[headerSize:WORD] 2[celCount:BYTE] 3[Unknown:BYTE] 4[celHeaderSize:WORD] 6[paletteOffset:DWORD] 10[Unknown:WORD] 12[Unknown:WORD]
// cel-header follow afterwards, each is 42 bytes
// Cel-Header
- // [width:WORD] [height:WORD] [displaceX:WORD] [displaceY:WORD] [clearColor:BYTE] [compressed:BYTE]
+ // 0[width:WORD] 2[height:WORD] 4[displaceX:WORD] 6[displaceY:WORD] 8[clearColor:BYTE] 9[compressed:BYTE]
// offset 10-23 is unknown
- // [rleOffset:DWORD] [literalOffset:DWORD] [Unknown:WORD] [Unknown:WORD] [priority:WORD] [relativeXpos:WORD] [relativeYpos:WORD]
+ // 24[rleOffset:DWORD] 28[literalOffset:DWORD] 32[Unknown:WORD] 34[Unknown:WORD] 36[priority:WORD] 38[relativeXpos:WORD] 40[relativeYpos:WORD]
cel_headerPos += 42 * celNo;
diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h
index 2404f99b41..942fa0f107 100644
--- a/engines/sci/graphics/picture.h
+++ b/engines/sci/graphics/picture.h
@@ -38,6 +38,9 @@ enum {
class GfxPorts;
class GfxScreen;
class GfxPalette;
+class GfxCoordAdjuster;
+class ResourceManager;
+class Resource;
/**
* Picture class, handles loading and displaying of picture resources
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
new file mode 100644
index 0000000000..d05e4f79e1
--- /dev/null
+++ b/engines/sci/graphics/plane32.cpp
@@ -0,0 +1,907 @@
+/* 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 "sci/console.h"
+#include "sci/engine/kernel.h"
+#include "sci/engine/selector.h"
+#include "sci/engine/state.h"
+#include "sci/graphics/frameout.h"
+#include "sci/graphics/lists32.h"
+#include "sci/graphics/plane32.h"
+#include "sci/graphics/remap.h"
+#include "sci/graphics/screen.h"
+#include "sci/graphics/screen_item32.h"
+
+namespace Sci {
+#pragma mark DrawList
+void DrawList::add(ScreenItem *screenItem, const Common::Rect &rect) {
+ DrawItem *drawItem = new DrawItem;
+ drawItem->screenItem = screenItem;
+ drawItem->rect = rect;
+ DrawListBase::add(drawItem);
+}
+
+#pragma mark -
+#pragma mark Plane
+uint16 Plane::_nextObjectId = 20000;
+
+Plane::Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId) :
+_width(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),
+_height(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight),
+_pictureId(pictureId),
+_mirrored(false),
+_back(0),
+_priorityChanged(0),
+_object(make_reg(0, _nextObjectId++)),
+_redrawAllCount(g_sci->_gfxFrameout->getScreenCount()),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_moved(0),
+_gameRect(gameRect) {
+ convertGameRectToPlaneRect();
+ _priority = MAX(10000, g_sci->_gfxFrameout->getPlanes().getTopPlanePriority() + 1);
+ setType();
+ _screenRect = _planeRect;
+}
+
+Plane::Plane(reg_t object) :
+_width(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),
+_height(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight),
+_priorityChanged(false),
+_object(object),
+_redrawAllCount(g_sci->_gfxFrameout->getScreenCount()),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_moved(0) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+ _vanishingPoint.x = readSelectorValue(segMan, object, SELECTOR(vanishingX));
+ _vanishingPoint.y = readSelectorValue(segMan, object, SELECTOR(vanishingY));
+
+ _gameRect.left = readSelectorValue(segMan, object, SELECTOR(inLeft));
+ _gameRect.top = readSelectorValue(segMan, object, SELECTOR(inTop));
+ _gameRect.right = readSelectorValue(segMan, object, SELECTOR(inRight)) + 1;
+ _gameRect.bottom = readSelectorValue(segMan, object, SELECTOR(inBottom)) + 1;
+ convertGameRectToPlaneRect();
+
+ _back = readSelectorValue(segMan, object, SELECTOR(back));
+ _priority = readSelectorValue(segMan, object, SELECTOR(priority));
+ _pictureId = readSelectorValue(segMan, object, SELECTOR(picture));
+ setType();
+
+ _mirrored = readSelectorValue(segMan, object, SELECTOR(mirrored));
+ _screenRect = _planeRect;
+ changePic();
+}
+
+Plane::Plane(const Plane &other) :
+_pictureId(other._pictureId),
+_mirrored(other._mirrored),
+_field_34(other._field_34), _field_38(other._field_38),
+_field_3C(other._field_3C), _field_40(other._field_40),
+_back(other._back),
+_object(other._object),
+_priority(other._priority),
+_planeRect(other._planeRect),
+_gameRect(other._gameRect),
+_screenRect(other._screenRect),
+_screenItemList(other._screenItemList) {}
+
+void Plane::operator=(const Plane &other) {
+ _gameRect = other._gameRect;
+ _planeRect = other._planeRect;
+ _vanishingPoint = other._vanishingPoint;
+ _pictureId = other._pictureId;
+ _type = other._type;
+ _mirrored = other._mirrored;
+ _priority = other._priority;
+ _back = other._back;
+ _width = other._width;
+ _field_34 = other._field_34;
+ _height = other._height;
+ _screenRect = other._screenRect;
+ _field_3C = other._field_3C;
+ _priorityChanged = other._priorityChanged;
+}
+
+void Plane::init() {
+ _nextObjectId = 20000;
+}
+
+void Plane::convertGameRectToPlaneRect() {
+ const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
+ const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ const Ratio ratioX = Ratio(screenWidth, scriptWidth);
+ const Ratio ratioY = Ratio(screenHeight, scriptHeight);
+
+ _planeRect = _gameRect;
+ mulru(_planeRect, ratioX, ratioY, 1);
+}
+
+void Plane::printDebugInfo(Console *con) const {
+ Common::String name;
+
+ if (_object.isNumber()) {
+ name = "-scummvm-";
+ } else {
+ name = g_sci->getEngineState()->_segMan->getObjectName(_object);
+ }
+
+ con->debugPrintf("%04x:%04x (%s): type %d, prio %d, pic %d, mirror %d, back %d\n",
+ PRINT_REG(_object),
+ name.c_str(),
+ _type,
+ _priority,
+ _pictureId,
+ _mirrored,
+ _back
+ );
+ con->debugPrintf(" game rect: (%d, %d, %d, %d), plane rect: (%d, %d, %d, %d)\n screen rect: (%d, %d, %d, %d)\n",
+ PRINT_RECT(_gameRect),
+ PRINT_RECT(_planeRect),
+ PRINT_RECT(_screenRect)
+ );
+ con->debugPrintf(" # screen items: %d\n", _screenItemList.size());
+}
+
+#pragma mark -
+#pragma mark Plane - Pic
+
+void Plane::addPicInternal(const GuiResourceId pictureId, const Common::Point *position, const bool mirrorX) {
+
+ uint16 celCount = 1000;
+ for (uint16 celNo = 0; celNo < celCount; ++celNo) {
+ CelObjPic *celObj = new CelObjPic(pictureId, celNo);
+ if (celCount == 1000) {
+ celCount = celObj->_celCount;
+ }
+
+ ScreenItem *screenItem = new ScreenItem(_object, celObj->_info);
+ screenItem->_pictureId = pictureId;
+ screenItem->_mirrorX = mirrorX;
+ screenItem->_priority = celObj->_priority;
+ screenItem->_fixPriority = true;
+ if (position != nullptr) {
+ screenItem->_position = *position + celObj->_relativePosition;
+ } else {
+ screenItem->_position = celObj->_relativePosition;
+ }
+ _screenItemList.add(screenItem);
+
+ delete screenItem->_celObj;
+ screenItem->_celObj = celObj;
+ }
+}
+
+void Plane::addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX) {
+ deletePic(pictureId);
+ addPicInternal(pictureId, &position, mirrorX);
+ // NOTE: In SCI engine this method returned the pictureId of the
+ // plane, but this return value was never used
+}
+
+void Plane::changePic() {
+ _pictureChanged = false;
+
+ if (_type != kPlaneTypePicture) {
+ return;
+ }
+
+ addPicInternal(_pictureId, nullptr, _mirrored);
+}
+
+void Plane::deletePic(const GuiResourceId pictureId) {
+ for (ScreenItemList::iterator it = _screenItemList.begin(); it != _screenItemList.end(); ++it) {
+ ScreenItem *screenItem = *it;
+ if (screenItem->_pictureId == pictureId) {
+ screenItem->_created = 0;
+ screenItem->_updated = 0;
+ screenItem->_deleted = g_sci->_gfxFrameout->getScreenCount();
+ }
+ }
+}
+
+void Plane::deletePic(const GuiResourceId oldPictureId, const GuiResourceId newPictureId) {
+ deletePic(oldPictureId);
+ _pictureId = newPictureId;
+}
+
+void Plane::deleteAllPics() {
+ for (ScreenItemList::iterator it = _screenItemList.begin(); it != _screenItemList.end(); ++it) {
+ ScreenItem *screenItem = *it;
+ if (screenItem != nullptr && screenItem->_celInfo.type == kCelTypePic) {
+ if (screenItem->_created == 0) {
+ screenItem->_created = 0;
+ screenItem->_updated = 0;
+ screenItem->_deleted = g_sci->_gfxFrameout->getScreenCount();
+ } else {
+ _screenItemList.erase(it);
+ }
+ }
+ }
+
+ _screenItemList.pack();
+}
+
+#pragma mark -
+#pragma mark Plane - Rendering
+
+void Plane::breakDrawListByPlanes(DrawList &drawList, const PlaneList &planeList) const {
+ int index = planeList.findIndexByObject(_object);
+
+ for (DrawList::size_type i = 0; i < drawList.size(); ++i) {
+ for (PlaneList::size_type j = index + 1; j < planeList.size(); ++j) {
+ if (planeList[j]->_type != kPlaneTypeTransparent) {
+ Common::Rect ptr[4];
+ int count = splitRects(drawList[i]->rect, planeList[j]->_screenRect, ptr);
+ if (count != -1) {
+ for (int k = count - 1; k >= 0; --k) {
+ drawList.add(drawList[i]->screenItem, ptr[k]);
+ }
+
+ drawList.erase_at(i);
+ break;
+ }
+ }
+ }
+ }
+ drawList.pack();
+}
+
+void Plane::breakEraseListByPlanes(RectList &eraseList, const PlaneList &planeList) const {
+ int index = planeList.findIndexByObject(_object);
+
+ for (RectList::size_type i = 0; i < eraseList.size(); ++i) {
+ for (PlaneList::size_type j = index + 1; j < planeList.size(); ++j) {
+ if (planeList[j]->_type != kPlaneTypeTransparent) {
+ Common::Rect ptr[4];
+
+ int count = splitRects(*eraseList[i], planeList[j]->_screenRect, ptr);
+ if (count != -1) {
+ for (int k = count - 1; k >= 0; --k) {
+ eraseList.add(ptr[k]);
+ }
+
+ eraseList.erase_at(i);
+ break;
+ }
+ }
+ }
+ }
+ eraseList.pack();
+}
+
+void Plane::calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList) {
+ ScreenItemList::size_type planeItemCount = _screenItemList.size();
+ ScreenItemList::size_type visiblePlaneItemCount = visiblePlane._screenItemList.size();
+
+ for (ScreenItemList::size_type i = 0; i < planeItemCount; ++i) {
+ ScreenItem *vitem = nullptr;
+ // NOTE: The original engine used an array without bounds checking
+ // so could just get the visible screen item directly; we need to
+ // verify that the index is actually within the valid range for
+ // the visible plane before accessing the item to avoid a range
+ // error.
+ if (i < visiblePlaneItemCount) {
+ vitem = visiblePlane._screenItemList[i];
+ }
+ ScreenItem *item = _screenItemList[i];
+
+ if (i < _screenItemList.size() && item != nullptr) {
+ if (item->_deleted) {
+ // add item's rect to erase list
+ if (
+ i < visiblePlane._screenItemList.size() &&
+ vitem != nullptr &&
+ !vitem->_screenRect.isEmpty()
+ ) {
+ if (g_sci->_gfxRemap32->getRemapCount()) {
+ mergeToRectList(vitem->_screenRect, eraseList);
+ } else {
+ eraseList.add(vitem->_screenRect);
+ }
+ }
+ } else if (item->_created) {
+ // add item to draw list
+ item->calcRects(*this);
+
+ if(!item->_screenRect.isEmpty()) {
+ if (g_sci->_gfxRemap32->getRemapCount()) {
+ drawList.add(item, item->_screenRect);
+ mergeToRectList(item->_screenRect, eraseList);
+ } else {
+ drawList.add(item, item->_screenRect);
+ }
+ }
+ } else if (item->_updated) {
+ // add old rect to erase list, new item to draw list
+ item->calcRects(*this);
+ if (g_sci->_gfxRemap32->getRemapCount()) {
+ // if item and vitem don't overlap, ...
+ if (item->_screenRect.isEmpty() ||
+ i >= visiblePlaneItemCount ||
+ vitem == nullptr ||
+ vitem->_screenRect.isEmpty() ||
+ !vitem->_screenRect.intersects(item->_screenRect)
+ ) {
+ // add item to draw list, and old rect to erase list
+ if (!item->_screenRect.isEmpty()) {
+ drawList.add(item, item->_screenRect);
+ mergeToRectList(item->_screenRect, eraseList);
+ }
+ if (
+ i < visiblePlaneItemCount &&
+ vitem != nullptr &&
+ !vitem->_screenRect.isEmpty()
+ ) {
+ mergeToRectList(vitem->_screenRect, eraseList);
+ }
+ } else {
+ // otherwise, add bounding box of old+new to erase list,
+ // and item to draw list
+
+ // TODO: This was changed from disasm, verify please!
+ Common::Rect extendedScreenRect = vitem->_screenRect;
+ extendedScreenRect.extend(item->_screenRect);
+
+ drawList.add(item, item->_screenRect);
+ mergeToRectList(extendedScreenRect, eraseList);
+ }
+ } else {
+ // if no active remaps, just add item to draw list and old rect
+ // to erase list
+ if (!item->_screenRect.isEmpty()) {
+ drawList.add(item, item->_screenRect);
+ }
+ if (
+ i < visiblePlaneItemCount &&
+ vitem != nullptr &&
+ !vitem->_screenRect.isEmpty()
+ ) {
+ eraseList.add(vitem->_screenRect);
+ }
+ }
+ }
+ }
+ }
+
+ // Remove parts of eraselist/drawlist that are covered by other planes
+ breakEraseListByPlanes(eraseList, planeList);
+ breakDrawListByPlanes(drawList, planeList);
+
+ // We store the current size of the drawlist, as we want to loop
+ // over the currently inserted entries later.
+ DrawList::size_type drawListSizePrimary = drawList.size();
+
+ if (/* TODO: dword_C6288 */ false) { // "high resolution pictures"????
+ _screenItemList.sort();
+ bool encounteredPic = false;
+ bool v81 = false;
+
+ for (RectList::size_type i = 0; i < eraseList.size(); ++i) {
+ const Common::Rect *rect = eraseList[i];
+
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+
+ if (j < _screenItemList.size() && item != nullptr) {
+ if (rect->intersects(item->_screenRect)) {
+ const Common::Rect intersection = rect->findIntersectingRect(item->_screenRect);
+ if (!item->_deleted) {
+ if (encounteredPic) {
+ if (item->_celInfo.type == kCelTypePic) {
+ if (v81 || item->_celInfo.celNo == 0) {
+ drawList.add(item, intersection);
+ }
+ } else {
+ if (!item->_updated && !item->_created) {
+ drawList.add(item, intersection);
+ }
+ v81 = true;
+ }
+ } else {
+ if (!item->_updated && !item->_created) {
+ drawList.add(item, intersection);
+ }
+ if (item->_celInfo.type == kCelTypePic) {
+ encounteredPic = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ _screenItemList.unsort();
+ } else {
+ // add all items overlapping the erase list to the draw list
+ for (RectList::size_type i = 0; i < eraseList.size(); ++i) {
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+ if (
+ item != nullptr &&
+ !item->_created && !item->_updated && !item->_deleted &&
+ eraseList[i]->intersects(item->_screenRect)
+ ) {
+ drawList.add(item, eraseList[i]->findIntersectingRect(item->_screenRect));
+ }
+ }
+ }
+ }
+
+ if (g_sci->_gfxRemap32->getRemapCount() == 0) { // no remaps active?
+ // Add all items that overlap with items in the drawlist and have higher
+ // priority.
+
+ // We only loop over "primary" items in the draw list, skipping
+ // those that were added because of the erase list in the previous loop,
+ // or those to be added in this loop.
+ for (DrawList::size_type i = 0; i < drawListSizePrimary; ++i) {
+ DrawItem *dli = drawList[i];
+
+ for (ScreenItemList::size_type j = 0; j < planeItemCount; ++j) {
+ ScreenItem *sli = _screenItemList[j];
+
+ if (
+ i < drawList.size() && dli != nullptr &&
+ j < _screenItemList.size() && sli != nullptr &&
+ !sli->_created && !sli->_updated && !sli->_deleted
+ ) {
+ ScreenItem *item = dli->screenItem;
+
+ if (
+ (sli->_priority > item->_priority || (sli->_priority == item->_priority && sli->_object > item->_object)) &&
+ dli->rect.intersects(sli->_screenRect)
+ ) {
+ drawList.add(sli, dli->rect.findIntersectingRect(sli->_screenRect));
+ }
+ }
+ }
+ }
+ }
+
+ decrementScreenItemArrayCounts(&visiblePlane, false);
+ _screenItemList.pack();
+ visiblePlane._screenItemList.pack();
+}
+
+void Plane::decrementScreenItemArrayCounts(Plane *visiblePlane, const bool forceUpdate) {
+ // The size of the screenItemList may change, so it is
+ // critical to re-check the size on each iteration
+ for (ScreenItemList::size_type i = 0; i < _screenItemList.size(); ++i) {
+ ScreenItem *item = _screenItemList[i];
+
+ if (item != nullptr) {
+ // update item in visiblePlane if item is updated
+ if (
+ item->_updated ||
+ (
+ forceUpdate &&
+ visiblePlane != nullptr &&
+ visiblePlane->_screenItemList.findByObject(item->_object) != nullptr
+ )
+ ) {
+ *visiblePlane->_screenItemList[i] = *_screenItemList[i];
+ }
+
+ if (item->_updated) {
+ item->_updated--;
+ }
+
+ // create new item in visiblePlane if item was added
+ if (item->_created) {
+ item->_created--;
+ if (visiblePlane != nullptr) {
+ visiblePlane->_screenItemList.add(new ScreenItem(*item));
+ }
+ }
+
+ // delete item from both planes if it was deleted
+ if (item->_deleted) {
+ item->_deleted--;
+ if (!item->_deleted) {
+ visiblePlane->_screenItemList.erase_at(i);
+ _screenItemList.erase_at(i);
+ }
+ }
+ }
+ }
+}
+
+void Plane::filterDownEraseRects(DrawList &drawList, RectList &eraseList, RectList &transparentEraseList) const {
+ if (_type == kPlaneTypeTransparent) {
+ for (RectList::size_type i = 0; i < transparentEraseList.size(); ++i) {
+ const Common::Rect *r = transparentEraseList[i];
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+ if (item != nullptr) {
+ if (r->intersects(item->_screenRect)) {
+ mergeToDrawList(j, *r, drawList);
+ }
+ }
+ }
+ }
+ } else {
+ for (RectList::size_type i = 0; i < transparentEraseList.size(); ++i) {
+ Common::Rect *r = transparentEraseList[i];
+ if (r->intersects(_screenRect)) {
+ r->clip(_screenRect);
+ mergeToRectList(*r, eraseList);
+
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+
+ if (item != nullptr) {
+ if (r->intersects(item->_screenRect)) {
+ mergeToDrawList(j, *r, drawList);
+ }
+ }
+ }
+
+ Common::Rect ptr[4];
+ const Common::Rect *r2 = transparentEraseList[i];
+ int count = splitRects(*r2, *r, ptr);
+ for (int k = count - 1; k >= 0; --k) {
+ transparentEraseList.add(ptr[k]);
+ }
+ transparentEraseList.erase_at(i);
+ }
+ }
+
+ transparentEraseList.pack();
+ }
+}
+
+void Plane::filterUpDrawRects(DrawList &transparentDrawList, const DrawList &drawList) const {
+ for (DrawList::size_type i = 0; i < drawList.size(); ++i) {
+ const Common::Rect &r = drawList[i]->rect;
+
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+ if (item != nullptr) {
+ if (r.intersects(item->_screenRect)) {
+ mergeToDrawList(j, r, transparentDrawList);
+ }
+ }
+ }
+ }
+}
+
+void Plane::filterUpEraseRects(DrawList &drawList, RectList &eraseList) const {
+ for (RectList::size_type i = 0; i < eraseList.size(); ++i) {
+ const Common::Rect &r = *eraseList[i];
+ for (ScreenItemList::size_type j = 0; j < _screenItemList.size(); ++j) {
+ ScreenItem *item = _screenItemList[j];
+
+ if (item != nullptr) {
+ if (r.intersects(item->_screenRect)) {
+ mergeToDrawList(j, r, drawList);
+ }
+ }
+ }
+ }
+}
+
+void Plane::mergeToDrawList(const ScreenItemList::size_type index, const Common::Rect &rect, DrawList &drawList) const {
+ RectList rects;
+
+ ScreenItem *item = _screenItemList[index];
+ Common::Rect r = item->_screenRect;
+ r.clip(rect);
+ rects.add(r);
+
+ for (RectList::size_type i = 0; i < rects.size(); ++i) {
+ r = *rects[i];
+
+ for (DrawList::size_type j = 0; j < drawList.size(); ++j) {
+ const DrawItem *drawitem = drawList[j];
+ if (item->_object == drawitem->screenItem->_object) {
+ if (drawitem->rect.contains(r)) {
+ rects.erase_at(i);
+ break;
+ }
+
+ Common::Rect outRects[4];
+ const int count = splitRects(r, drawitem->rect, outRects);
+ if (count != -1) {
+ for (int k = count - 1; k >= 0; --k) {
+ rects.add(outRects[k]);
+ }
+
+ rects.erase_at(i);
+
+ // proceed to the next rect
+ r = *rects[++i];
+ }
+ }
+ }
+ }
+
+ rects.pack();
+
+ for (RectList::size_type i = 0; i < rects.size(); ++i) {
+ drawList.add(item, *rects[i]);
+ }
+}
+
+void Plane::mergeToRectList(const Common::Rect &rect, RectList &rectList) const {
+ RectList temp;
+ temp.add(rect);
+
+ for (RectList::size_type i = 0; i < temp.size(); ++i) {
+ Common::Rect r = *temp[i];
+
+ for (RectList::size_type j = 0; j < rectList.size(); ++j) {
+ const Common::Rect *innerRect = rectList[j];
+ if (innerRect->contains(r)) {
+ temp.erase_at(i);
+ break;
+ }
+
+ Common::Rect out[4];
+ const int count = splitRects(r, *innerRect, out);
+ if (count != -1) {
+ for (int k = count - 1; k >= 0; --k) {
+ temp.add(out[k]);
+ }
+
+ temp.erase_at(i);
+
+ // proceed to the next rect
+ r = *temp[++i];
+ }
+ }
+ }
+
+ temp.pack();
+
+ for (RectList::size_type i = 0; i < temp.size(); ++i) {
+ rectList.add(*temp[i]);
+ }
+}
+
+void Plane::redrawAll(Plane *visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList) {
+ for (ScreenItemList::const_iterator screenItemPtr = _screenItemList.begin(); screenItemPtr != _screenItemList.end(); ++screenItemPtr) {
+ if (*screenItemPtr != nullptr) {
+ ScreenItem &screenItem = **screenItemPtr;
+ if (!screenItem._deleted) {
+ screenItem.calcRects(*this);
+ if (!screenItem._screenRect.isEmpty()) {
+ drawList.add(&screenItem, screenItem._screenRect);
+ }
+ }
+ }
+ }
+
+ eraseList.clear();
+
+ if (!_screenRect.isEmpty() && _type != kPlaneTypePicture && _type != kPlaneTypeOpaque) {
+ eraseList.add(_screenRect);
+ }
+ breakEraseListByPlanes(eraseList, planeList);
+ breakDrawListByPlanes(drawList, planeList);
+ --_redrawAllCount;
+ decrementScreenItemArrayCounts(visiblePlane, true);
+ _screenItemList.pack();
+ if (visiblePlane != nullptr) {
+ visiblePlane->_screenItemList.pack();
+ }
+}
+
+void Plane::setType() {
+ if (_pictureId == kPlanePicOpaque) {
+ _type = kPlaneTypeOpaque;
+ } else if (_pictureId == kPlanePicTransparent) {
+ _type = kPlaneTypeTransparent;
+ } else if (_pictureId == kPlanePicColored) {
+ _type = kPlaneTypeColored;
+ } else {
+ _type = kPlaneTypePicture;
+ }
+}
+
+void Plane::sync(const Plane *other, const Common::Rect &screenRect) {
+ if (other == nullptr) {
+ if (_pictureChanged) {
+ deleteAllPics();
+ setType();
+ changePic();
+ _redrawAllCount = g_sci->_gfxFrameout->getScreenCount();
+ } else {
+ setType();
+ }
+ } else {
+ if (
+ _planeRect.top != other->_planeRect.top ||
+ _planeRect.left != other->_planeRect.left ||
+ _planeRect.right > other->_planeRect.right ||
+ _planeRect.bottom > other->_planeRect.bottom
+ ) {
+ _redrawAllCount = g_sci->_gfxFrameout->getScreenCount();
+ _updated = g_sci->_gfxFrameout->getScreenCount();
+ } else if (_planeRect != other->_planeRect) {
+ _updated = g_sci->_gfxFrameout->getScreenCount();
+ }
+
+ if (_priority != other->_priority) {
+ _priorityChanged = g_sci->_gfxFrameout->getScreenCount();
+ }
+
+ if (_pictureId != other->_pictureId || _mirrored != other->_mirrored || _pictureChanged) {
+ deleteAllPics();
+ setType();
+ changePic();
+ _redrawAllCount = g_sci->_gfxFrameout->getScreenCount();
+ }
+
+ if (_back != other->_back) {
+ _redrawAllCount = g_sci->_gfxFrameout->getScreenCount();
+ }
+ }
+
+ _deleted = 0;
+ if (_created == 0) {
+ _moved = g_sci->_gfxFrameout->getScreenCount();
+ }
+
+ convertGameRectToPlaneRect();
+ _width = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ _height = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ _screenRect = _planeRect;
+ // NOTE: screenRect originally was retrieved through globals
+ // instead of being passed into the function
+ clipScreenRect(screenRect);
+}
+
+void Plane::update(const reg_t object) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+ _vanishingPoint.x = readSelectorValue(segMan, object, SELECTOR(vanishingX));
+ _vanishingPoint.y = readSelectorValue(segMan, object, SELECTOR(vanishingY));
+ _gameRect.left = readSelectorValue(segMan, object, SELECTOR(inLeft));
+ _gameRect.top = readSelectorValue(segMan, object, SELECTOR(inTop));
+ _gameRect.right = readSelectorValue(segMan, object, SELECTOR(inRight)) + 1;
+ _gameRect.bottom = readSelectorValue(segMan, object, SELECTOR(inBottom)) + 1;
+ convertGameRectToPlaneRect();
+
+ _priority = readSelectorValue(segMan, object, SELECTOR(priority));
+ GuiResourceId pictureId = readSelectorValue(segMan, object, SELECTOR(picture));
+ if (_pictureId != pictureId) {
+ _pictureId = pictureId;
+ _pictureChanged = true;
+ }
+
+ _mirrored = readSelectorValue(segMan, object, SELECTOR(mirrored));
+ _back = readSelectorValue(segMan, object, SELECTOR(back));
+}
+
+void Plane::scrollScreenItems(const int16 deltaX, const int16 deltaY, const bool scrollPics) {
+ _redrawAllCount = g_sci->_gfxFrameout->getScreenCount();
+
+ for (ScreenItemList::iterator it = _screenItemList.begin(); it != _screenItemList.end(); ++it) {
+ if (*it != nullptr) {
+ ScreenItem &screenItem = **it;
+ if (!screenItem._deleted && (screenItem._celInfo.type != kCelTypePic || scrollPics)) {
+ screenItem._position.x += deltaX;
+ screenItem._position.y += deltaY;
+ }
+ }
+ }
+}
+
+void Plane::remapMarkRedraw() {
+ for (ScreenItemList::const_iterator screenItemPtr = _screenItemList.begin(); screenItemPtr != _screenItemList.end(); ++screenItemPtr) {
+ if (*screenItemPtr != nullptr) {
+ ScreenItem &screenItem = **screenItemPtr;
+ if (screenItem.getCelObj()._remap && !screenItem._deleted && !screenItem._created) {
+ screenItem._updated = g_sci->_gfxFrameout->getScreenCount();
+ }
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark PlaneList
+void PlaneList::add(Plane *plane) {
+ for (iterator it = begin(); it != end(); ++it) {
+ if ((*it)->_priority > plane->_priority) {
+ insert(it, plane);
+ return;
+ }
+ }
+
+ push_back(plane);
+}
+
+void PlaneList::clear() {
+ for (iterator it = begin(); it != end(); ++it) {
+ delete *it;
+ }
+
+ PlaneListBase::clear();
+}
+
+void PlaneList::erase(Plane *plane) {
+ for (iterator it = begin(); it != end(); ++it) {
+ if (*it == plane) {
+ erase(it);
+ break;
+ }
+ }
+}
+
+PlaneList::iterator PlaneList::erase(iterator it) {
+ delete *it;
+ return PlaneListBase::erase(it);
+}
+
+int PlaneList::findIndexByObject(const reg_t object) const {
+ for (size_type i = 0; i < size(); ++i) {
+ if ((*this)[i] != nullptr && (*this)[i]->_object == object) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+Plane *PlaneList::findByObject(const reg_t object) const {
+ const_iterator planeIt = Common::find_if(begin(), end(), FindByObject<Plane *>(object));
+
+ if (planeIt == end()) {
+ return nullptr;
+ }
+
+ return *planeIt;
+}
+
+int16 PlaneList::getTopPlanePriority() const {
+ if (size() > 0) {
+ return (*this)[size() - 1]->_priority;
+ }
+
+ return 0;
+}
+
+int16 PlaneList::getTopSciPlanePriority() const {
+ int16 priority = 0;
+
+ for (const_iterator it = begin(); it != end(); ++it) {
+ if ((*it)->_priority >= 10000) {
+ break;
+ }
+
+ priority = (*it)->_priority;
+ }
+
+ return priority;
+}
+
+void PlaneList::remove_at(size_type index) {
+ delete PlaneListBase::remove_at(index);
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/plane32.h b/engines/sci/graphics/plane32.h
new file mode 100644
index 0000000000..770a6fa445
--- /dev/null
+++ b/engines/sci/graphics/plane32.h
@@ -0,0 +1,485 @@
+/* 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 SCI_GRAPHICS_PLANE32_H
+#define SCI_GRAPHICS_PLANE32_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "sci/engine/vm_types.h"
+#include "sci/graphics/helpers.h"
+#include "sci/graphics/lists32.h"
+#include "sci/graphics/screen_item32.h"
+
+namespace Sci {
+enum PlaneType {
+ kPlaneTypeColored = 0,
+ kPlaneTypePicture = 1,
+ kPlaneTypeTransparent = 2,
+ kPlaneTypeOpaque = 3
+};
+
+enum PlanePictureCodes {
+ // NOTE: Any value at or below 65532 means the plane
+ // is a kPlaneTypePicture.
+ kPlanePic = 65532,
+ kPlanePicOpaque = 65533,
+ kPlanePicTransparent = 65534,
+ kPlanePicColored = 65535
+};
+
+#pragma mark -
+#pragma mark RectList
+
+typedef StablePointerArray<Common::Rect, 200> RectListBase;
+class RectList : public RectListBase {
+public:
+ void add(const Common::Rect &rect) {
+ RectListBase::add(new Common::Rect(rect));
+ }
+};
+
+#pragma mark -
+#pragma mark DrawList
+
+struct DrawItem {
+ ScreenItem *screenItem;
+ Common::Rect rect;
+
+ inline bool operator<(const DrawItem &other) const {
+ return *screenItem < *other.screenItem;
+ }
+};
+
+typedef StablePointerArray<DrawItem, 250> DrawListBase;
+class DrawList : public DrawListBase {
+private:
+ inline static bool sortHelper(const DrawItem *a, const DrawItem *b) {
+ return *a < *b;
+ }
+public:
+ void add(ScreenItem *screenItem, const Common::Rect &rect);
+ inline void sort() {
+ pack();
+ Common::sort(begin(), end(), sortHelper);
+ }
+};
+
+class PlaneList;
+
+#pragma mark -
+#pragma mark Plane
+
+/**
+ * A plane is a grouped layer of screen items.
+ */
+class Plane {
+private:
+ /**
+ * A serial used for planes that are generated inside
+ * the graphics engine, rather than the interpreter.
+ */
+ static uint16 _nextObjectId;
+
+ /**
+ * The dimensions of the plane, in game script
+ * coordinates.
+ * TODO: These are never used and are always
+ * scriptWidth x scriptHeight in SCI engine? The actual
+ * dimensions of the plane are always in
+ * gameRect/planeRect.
+ */
+ int16 _width, _height;
+
+ /**
+ * For planes that are used to render picture data, the
+ * resource ID of the picture to be displayed. This
+ * value may also be one of the special
+ * PlanePictureCodes, in which case the plane becomes a
+ * non-picture plane.
+ */
+ GuiResourceId _pictureId;
+
+ /**
+ * Whether or not the contents of picture planes should
+ * be drawn horizontally mirrored. Only applies to
+ * planes of type kPlaneTypePicture.
+ */
+ bool _mirrored;
+
+ /**
+ * Whether the picture ID for this plane has changed.
+ * This flag is set when the plane is created or updated
+ * from a VM object, and is cleared when the plane is
+ * synchronised to another plane (which calls
+ * changePic).
+ */
+ bool _pictureChanged;
+
+ // TODO: Are these ever actually used?
+ int _field_34, _field_38; // probably a point or ratio
+ int _field_3C, _field_40; // probably a point or ratio
+
+ /**
+ * Converts the dimensions of the game rect used by
+ * scripts to the dimensions of the plane rect used to
+ * render content to the screen. Coordinates with
+ * remainders are rounded up to the next whole pixel.
+ */
+ void convertGameRectToPlaneRect();
+
+ /**
+ * Sets the type of the plane according to its assigned
+ * picture resource ID.
+ */
+ void setType();
+
+public:
+ /**
+ * The color to use when erasing the plane. Only
+ * applies to planes of type kPlaneTypeColored.
+ */
+ byte _back;
+
+ /**
+ * Whether the priority of this plane has changed.
+ * This flag is set when the plane is updated from
+ * another plane and cleared when draw list calculation
+ * occurs.
+ */
+ int _priorityChanged;
+
+ /**
+ * A handle to the VM object corresponding to this
+ * plane. Some planes are generated purely within the
+ * graphics engine and have a numeric object value.
+ */
+ reg_t _object;
+
+ /**
+ * The rendering priority of the plane. Higher
+ * priorities are drawn above lower priorities.
+ */
+ int16 _priority;
+
+ /**
+ * Whether or not all screen items in this plane should
+ * be redrawn on the next frameout, instead of just
+ * the screen items marked as updated. This is set when
+ * visual changes to the plane itself are made that
+ * affect the rendering of the entire plane, and cleared
+ * once those changes are rendered by `redrawAll`.
+ */
+ int _redrawAllCount;
+
+ PlaneType _type;
+
+ /**
+ * Flags indicating the state of the plane.
+ * - `created` is set when the plane is first created,
+ * either from a VM object or from within the engine
+ * itself
+ * - `updated` is set when the plane is updated from
+ * another plane and the two planes' `planeRect`s do
+ * not match
+ * - `deleted` is set when the plane is deleted by a
+ * kernel call
+ * - `moved` is set when the plane is synchronised from
+ * another plane and is not already in the "created"
+ * state
+ */
+ int _created, _updated, _deleted, _moved;
+
+ /**
+ * The vanishing point for the plane. Used when
+ * calculating the correct scaling of the plane's screen
+ * items according to their position.
+ */
+ Common::Point _vanishingPoint;
+
+ /**
+ * The position & dimensions of the plane in screen
+ * coordinates. This rect is not clipped to the screen,
+ * so may include coordinates that are offscreen.
+ */
+ Common::Rect _planeRect;
+
+ /**
+ * The position & dimensions of the plane in game script
+ * coordinates.
+ */
+ Common::Rect _gameRect;
+
+ /**
+ * The position & dimensions of the plane in screen
+ * coordinates. This rect is clipped to the screen.
+ */
+ Common::Rect _screenRect;
+
+ /**
+ * The list of screen items grouped within this plane.
+ */
+ ScreenItemList _screenItemList;
+
+public:
+ /**
+ * Initialises static Plane members.
+ */
+ static void init();
+
+ // NOTE: This constructor signature originally did not accept a
+ // picture ID, but some calls to construct planes with this signature
+ // immediately set the picture ID and then called setType again, so
+ // it made more sense to just make the picture ID a parameter instead.
+ Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId = kPlanePicColored);
+
+ Plane(const reg_t object);
+
+ Plane(const Plane &other);
+
+ void operator=(const Plane &other);
+
+ inline bool operator<(const Plane &other) const {
+ if (_priority < other._priority) {
+ return true;
+ }
+
+ if (_priority == other._priority) {
+ return _object < other._object;
+ }
+
+ return false;
+ }
+
+ /**
+ * Clips the screen rect of this plane to fit within the
+ * given screen rect.
+ */
+ inline void clipScreenRect(const Common::Rect &screenRect) {
+ if (_screenRect.intersects(screenRect)) {
+ _screenRect.clip(screenRect);
+ } else {
+ _screenRect.left = 0;
+ _screenRect.top = 0;
+ _screenRect.right = 0;
+ _screenRect.bottom = 0;
+ }
+ }
+
+ void printDebugInfo(Console *con) const;
+
+ /**
+ * Compares the properties of the current plane against
+ * the properties of the `other` plane (which is the
+ * corresponding plane from the visible plane list) to
+ * discover which properties have been changed on this
+ * plane by a call to `update(reg_t)`.
+ *
+ * @note This method was originally called UpdatePlane
+ * in SCI engine.
+ */
+ void sync(const Plane *other, const Common::Rect &screenRect);
+
+ /**
+ * Updates the plane to match the state of the plane
+ * object from the virtual machine.
+ *
+ * @note This method was originally called UpdatePlane
+ * in SCI engine.
+ */
+ void update(const reg_t object);
+
+ /**
+ * Modifies the position of all non-pic screen items
+ * by the given delta. If `scrollPics` is true, pic
+ * items are also repositioned.
+ */
+ void scrollScreenItems(const int16 deltaX, const int16 deltaY, const bool scrollPics);
+
+#pragma mark -
+#pragma mark Plane - Pic
+private:
+ /**
+ * Adds all cels from the specified picture resource to
+ * the plane as screen items. If a position is provided,
+ * the screen items will be given that position;
+ * otherwise, the default relative positions for each
+ * cel will be taken from the picture resource data.
+ */
+ inline void addPicInternal(const GuiResourceId pictureId, const Common::Point *position, const bool mirrorX);
+
+ /**
+ * Marks all screen items to be deleted that are within
+ * this plane and match the given picture ID.
+ */
+ void deletePic(const GuiResourceId pictureId);
+
+ /**
+ * Marks all screen items to be deleted that are within
+ * this plane and match the given picture ID, then sets
+ * the picture ID of the plane to the new picture ID
+ * without adding any screen items.
+ */
+ void deletePic(const GuiResourceId oldPictureId, const GuiResourceId newPictureId);
+
+ /**
+ * Marks all screen items to be deleted that are within
+ * this plane and are picture cels.
+ */
+ void deleteAllPics();
+
+public:
+ /**
+ * Marks all existing screen items matching the current
+ * picture to be deleted, then adds all cels from the
+ * new picture resource to the plane at the given
+ * position.
+ */
+ void addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX);
+
+ /**
+ * If the plane is a picture plane, re-adds all cels
+ * from its picture resource to the plane. Otherwise,
+ * just clears the _pictureChanged flag.
+ */
+ void changePic();
+
+#pragma mark -
+#pragma mark Plane - Rendering
+private:
+ /**
+ * Splits all rects in the given draw list at the edges
+ * of all non-transparent planes above the current
+ * plane.
+ */
+ void breakDrawListByPlanes(DrawList &drawList, const PlaneList &planeList) const;
+
+ /**
+ * Splits all rects in the given erase list rects at the
+ * edges of all non-transparent planes above the current
+ * plane.
+ */
+ void breakEraseListByPlanes(RectList &eraseList, const PlaneList &planeList) const;
+
+ /**
+ * Synchronises changes to screen items from the current
+ * plane to the visible plane and deletes screen items
+ * from the current plane that have been marked as
+ * deleted. If `forceUpdate` is true, all screen items
+ * on the visible plane will be updated, even if they
+ * are not marked as having changed.
+ */
+ void decrementScreenItemArrayCounts(Plane *visiblePlane, const bool forceUpdate);
+
+ /**
+ * Merges the screen item from this plane at the given
+ * index into the given draw list, clipped to the given
+ * rect. TODO: Finish documenting
+ */
+ void mergeToDrawList(const DrawList::size_type index, const Common::Rect &rect, DrawList &drawList) const;
+
+ /**
+ * Adds the given rect into the given rect list,
+ * merging it with other rects already inside the list,
+ * if possible, to avoid overdraw. TODO: Finish
+ * documenting
+ */
+ void mergeToRectList(const Common::Rect &rect, RectList &rectList) const;
+
+public:
+ /**
+ * Calculates the location and dimensions of dirty rects
+ * of the screen items in this plane and adds them to
+ * the given draw and erase lists, and synchronises this
+ * plane's list of screen items to the given visible
+ * plane.
+ */
+ void calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList);
+
+ /**
+ * TODO: Documentation
+ */
+ void filterDownEraseRects(DrawList &drawList, RectList &eraseList, RectList &transparentEraseList) const;
+
+ /**
+ * TODO: Documentation
+ */
+ void filterUpEraseRects(DrawList &drawList, RectList &eraseList) const;
+
+ /**
+ * TODO: Documentation
+ */
+ void filterUpDrawRects(DrawList &transparentDrawList, const DrawList &drawList) const;
+
+ /**
+ * Updates all of the plane's non-deleted screen items
+ * and adds them to the given draw and erase lists.
+ */
+ void redrawAll(Plane *visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList);
+
+ void remapMarkRedraw();
+};
+
+#pragma mark -
+#pragma mark PlaneList
+
+typedef Common::Array<Plane *> PlaneListBase;
+class PlaneList : public PlaneListBase {
+private:
+ inline static bool sortHelper(const Plane *a, const Plane *b) {
+ return *a < *b;
+ }
+
+ using PlaneListBase::push_back;
+
+public:
+ // A method for finding the index of a plane inside a
+ // PlaneList is used because entries in the main plane
+ // list and visible plane list of GfxFrameout are
+ // synchronised by index
+ int findIndexByObject(const reg_t object) const;
+ Plane *findByObject(const reg_t object) const;
+
+ /**
+ * Gets the priority of the top plane in the plane list.
+ */
+ int16 getTopPlanePriority() const;
+
+ /**
+ * Gets the priority of the top plane in the plane list
+ * created by a game script.
+ */
+ int16 getTopSciPlanePriority() const;
+
+ void add(Plane *plane);
+ void clear();
+ iterator erase(iterator it);
+ void erase(Plane *plane);
+ inline void sort() {
+ Common::sort(begin(), end(), sortHelper);
+ }
+ void remove_at(size_type index);
+};
+
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/graphics/remap.cpp b/engines/sci/graphics/remap.cpp
new file mode 100644
index 0000000000..e331eaf971
--- /dev/null
+++ b/engines/sci/graphics/remap.cpp
@@ -0,0 +1,386 @@
+/* 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 "sci/sci.h"
+#include "sci/resource.h"
+#include "sci/graphics/palette.h"
+#include "sci/graphics/palette32.h"
+#include "sci/graphics/remap.h"
+#include "sci/graphics/screen.h"
+
+namespace Sci {
+
+#pragma mark -
+#pragma mark SCI16 remapping (QFG4 demo)
+
+GfxRemap::GfxRemap(GfxPalette *palette)
+ : _palette(palette) {
+ _remapOn = false;
+ resetRemapping();
+}
+
+GfxRemap::~GfxRemap() {
+}
+
+byte GfxRemap::remapColor(byte remappedColor, byte screenColor) {
+ assert(_remapOn);
+ if (_remappingType[remappedColor] == kRemappingByRange)
+ return _remappingByRange[screenColor];
+ else if (_remappingType[remappedColor] == kRemappingByPercent)
+ return _remappingByPercent[screenColor];
+ else
+ error("remapColor(): Color %d isn't remapped", remappedColor);
+
+ return 0; // should never reach here
+}
+
+void GfxRemap::resetRemapping() {
+ _remapOn = false;
+ _remappingPercentToSet = 0;
+
+ for (int i = 0; i < 256; i++) {
+ _remappingType[i] = kRemappingNone;
+ _remappingByPercent[i] = i;
+ _remappingByRange[i] = i;
+ }
+}
+
+void GfxRemap::setRemappingPercent(byte color, byte percent) {
+ _remapOn = true;
+
+ // We need to defer the setup of the remapping table every time the screen
+ // palette is changed, so that kernelFindColor() can find the correct
+ // colors. Set it once here, in case the palette stays the same and update
+ // it on each palette change by copySysPaletteToScreen().
+ _remappingPercentToSet = percent;
+
+ for (int i = 0; i < 256; i++) {
+ byte r = _palette->_sysPalette.colors[i].r * _remappingPercentToSet / 100;
+ byte g = _palette->_sysPalette.colors[i].g * _remappingPercentToSet / 100;
+ byte b = _palette->_sysPalette.colors[i].b * _remappingPercentToSet / 100;
+ _remappingByPercent[i] = _palette->kernelFindColor(r, g, b);
+ }
+
+ _remappingType[color] = kRemappingByPercent;
+}
+
+void GfxRemap::setRemappingRange(byte color, byte from, byte to, byte base) {
+ _remapOn = true;
+
+ for (int i = from; i <= to; i++) {
+ _remappingByRange[i] = i + base;
+ }
+
+ _remappingType[color] = kRemappingByRange;
+}
+
+void GfxRemap::updateRemapping() {
+ // Check if we need to reset remapping by percent with the new colors.
+ if (_remappingPercentToSet) {
+ for (int i = 0; i < 256; i++) {
+ byte r = _palette->_sysPalette.colors[i].r * _remappingPercentToSet / 100;
+ byte g = _palette->_sysPalette.colors[i].g * _remappingPercentToSet / 100;
+ byte b = _palette->_sysPalette.colors[i].b * _remappingPercentToSet / 100;
+ _remappingByPercent[i] = _palette->kernelFindColor(r, g, b);
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark SCI32 remapping
+
+#ifdef ENABLE_SCI32
+
+GfxRemap32::GfxRemap32(GfxPalette32 *palette) : _palette(palette) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _noMapStart = _noMapCount = 0;
+ _update = false;
+ _remapCount = 0;
+
+ // The remap range was 245 - 254 in SCI2, but was changed to 235 - 244 in SCI21 middle
+ _remapEndColor = (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) ? 244 : 254;
+}
+
+void GfxRemap32::remapOff(byte color) {
+ if (!color) {
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++)
+ _remaps[i] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+
+ _remapCount = 0;
+ } else {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ _remaps[index] = RemapParams(0, 0, 0, 0, 100, kRemappingNone);
+ _remapCount--;
+ }
+
+ _update = true;
+}
+
+void GfxRemap32::setRemappingRange(byte color, byte from, byte to, byte base) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(from, to, base, 0, 100, kRemappingByRange);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingPercent(byte color, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, 0, percent, kRemappingByPercent);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToGray(byte color, byte gray) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, 100, kRemappingToGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setRemappingToPercentGray(byte color, byte gray, byte percent) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ _remaps[_remapEndColor - color] = RemapParams(0, 0, 0, gray, percent, kRemappingToPercentGray);
+ initColorArrays(_remapEndColor - color);
+ _remapCount++;
+ _update = true;
+}
+
+void GfxRemap32::setNoMatchRange(byte from, byte count) {
+ _noMapStart = from;
+ _noMapCount = count;
+}
+
+bool GfxRemap32::remapEnabled(byte color) const {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ return (_remaps[index].type != kRemappingNone);
+}
+
+byte GfxRemap32::remapColor(byte color, byte target) {
+ assert(_remapEndColor - color >= 0 && _remapEndColor - color < REMAP_COLOR_COUNT);
+ const byte index = _remapEndColor - color;
+ if (_remaps[index].type != kRemappingNone)
+ return _remaps[index].remap[target];
+ else
+ return target;
+}
+
+void GfxRemap32::initColorArrays(byte index) {
+ Palette *curPalette = &_palette->_sysPalette;
+ RemapParams *curRemap = &_remaps[index];
+
+ memcpy(curRemap->curColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+ memcpy(curRemap->targetColor, curPalette->colors, NON_REMAPPED_COLOR_COUNT * sizeof(Color));
+}
+
+bool GfxRemap32::updateRemap(byte index, bool palChanged) {
+ int result;
+ RemapParams *curRemap = &_remaps[index];
+ const Palette *curPalette = &_palette->_sysPalette;
+ const Palette *nextPalette = _palette->getNextPalette();
+ bool changed = false;
+
+ if (!_update && !palChanged)
+ return false;
+
+ Common::fill(_targetChanged, _targetChanged + NON_REMAPPED_COLOR_COUNT, false);
+
+ switch (curRemap->type) {
+ case kRemappingNone:
+ return false;
+ case kRemappingByRange:
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (curRemap->from <= i && i <= curRemap->to)
+ result = i + curRemap->base;
+ else
+ result = i;
+
+ if (curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ }
+
+ curRemap->colorChanged[i] = true;
+ }
+ return changed;
+ case kRemappingByPercent:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ // NOTE: This method uses nextPalette instead of curPalette
+ Color color = nextPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->colorChanged[i]) {
+ byte red = CLIP<byte>(color.r * curRemap->percent / 100, 0, 255);
+ byte green = CLIP<byte>(color.g * curRemap->percent / 100, 0, 255);
+ byte blue = CLIP<byte>(color.b * curRemap->percent / 100, 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ return changed;
+ case kRemappingToGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ case kRemappingToPercentGray:
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color color = curPalette->colors[i];
+
+ if (curRemap->curColor[i] != color) {
+ curRemap->colorChanged[i] = true;
+ curRemap->curColor[i] = color;
+ }
+
+ if (curRemap->percent != curRemap->oldPercent || curRemap->gray != curRemap->oldGray || curRemap->colorChanged[i]) {
+ byte lumosity = ((color.r * 77) + (color.g * 151) + (color.b * 28)) >> 8;
+ lumosity = lumosity * curRemap->percent / 100;
+ byte red = CLIP<byte>(color.r - ((color.r - lumosity) * curRemap->gray / 100), 0, 255);
+ byte green = CLIP<byte>(color.g - ((color.g - lumosity) * curRemap->gray / 100), 0, 255);
+ byte blue = CLIP<byte>(color.b - ((color.b - lumosity) * curRemap->gray / 100), 0, 255);
+ byte used = curRemap->targetColor[i].used;
+
+ Color newColor = { used, red, green, blue };
+ if (curRemap->targetColor[i] != newColor) {
+ _targetChanged[i] = true;
+ curRemap->targetColor[i] = newColor;
+ }
+ }
+ }
+
+ changed = applyRemap(index);
+ Common::fill(curRemap->colorChanged, curRemap->colorChanged + NON_REMAPPED_COLOR_COUNT, false);
+ curRemap->oldPercent = curRemap->percent;
+ curRemap->oldGray = curRemap->gray;
+ return changed;
+ default:
+ return false;
+ }
+}
+
+static int colorDistance(Color a, Color b) {
+ int rDiff = (a.r - b.r) * (a.r - b.r);
+ int gDiff = (a.g - b.g) * (a.g - b.g);
+ int bDiff = (a.b - b.b) * (a.b - b.b);
+ return rDiff + gDiff + bDiff;
+}
+
+bool GfxRemap32::applyRemap(byte index) {
+ RemapParams *curRemap = &_remaps[index];
+ const bool *cycleMap = _palette->getCyclemap();
+ bool unmappedColors[NON_REMAPPED_COLOR_COUNT];
+ Color newColors[NON_REMAPPED_COLOR_COUNT];
+ bool changed = false;
+
+ Common::fill(unmappedColors, unmappedColors + NON_REMAPPED_COLOR_COUNT, false);
+ if (_noMapCount)
+ Common::fill(unmappedColors + _noMapStart, unmappedColors + _noMapStart + _noMapCount, true);
+
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (cycleMap[i])
+ unmappedColors[i] = true;
+ }
+
+ int curColor = 0;
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ if (curRemap->colorChanged[i] && !unmappedColors[i])
+ newColors[curColor++] = curRemap->curColor[i];
+ }
+
+ for (int i = 1; i < NON_REMAPPED_COLOR_COUNT; i++) {
+ Color targetColor = curRemap->targetColor[i];
+ bool colorChanged = curRemap->colorChanged[curRemap->remap[i]];
+
+ if (!_targetChanged[i] && !colorChanged)
+ continue;
+
+ if (_targetChanged[i] && colorChanged)
+ if (curRemap->distance[i] < 100 && colorDistance(targetColor, curRemap->curColor[curRemap->remap[i]]) <= curRemap->distance[i])
+ continue;
+
+ int diff = 0;
+ int16 result = _palette->matchColor(targetColor.r, targetColor.g, targetColor.b, curRemap->distance[i], diff, unmappedColors);
+ if (result != -1 && curRemap->remap[i] != result) {
+ changed = true;
+ curRemap->remap[i] = result;
+ curRemap->distance[i] = diff;
+ }
+ }
+
+ return changed;
+}
+
+bool GfxRemap32::remapAllTables(bool palChanged) {
+ bool changed = false;
+
+ for (int i = 0; i < REMAP_COLOR_COUNT; i++) {
+ changed |= updateRemap(i, palChanged);
+ }
+
+ _update = false;
+ return changed;
+}
+
+#endif
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/remap.h b/engines/sci/graphics/remap.h
new file mode 100644
index 0000000000..d012568f7f
--- /dev/null
+++ b/engines/sci/graphics/remap.h
@@ -0,0 +1,154 @@
+/* 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 SCI_GRAPHICS_REMAP_H
+#define SCI_GRAPHICS_REMAP_H
+
+#include "common/array.h"
+#include "sci/graphics/helpers.h"
+
+namespace Sci {
+
+class GfxScreen;
+
+enum ColorRemappingType {
+ kRemappingNone = 0,
+ kRemappingByRange = 1,
+ kRemappingByPercent = 2,
+ kRemappingToGray = 3,
+ kRemappingToPercentGray = 4
+};
+
+#define REMAP_COLOR_COUNT 9
+#define NON_REMAPPED_COLOR_COUNT 236
+
+/**
+ * Remap class, handles color remapping
+ */
+class GfxRemap {
+public:
+ GfxRemap(GfxPalette *_palette);
+ ~GfxRemap();
+
+ void resetRemapping();
+ void setRemappingPercent(byte color, byte percent);
+ void setRemappingRange(byte color, byte from, byte to, byte base);
+ bool isRemapped(byte color) const {
+ return _remapOn && (_remappingType[color] != kRemappingNone);
+ }
+ byte remapColor(byte remappedColor, byte screenColor);
+ void updateRemapping();
+
+private:
+ GfxScreen *_screen;
+ GfxPalette *_palette;
+
+ bool _remapOn;
+ ColorRemappingType _remappingType[256];
+ byte _remappingByPercent[256];
+ byte _remappingByRange[256];
+ uint16 _remappingPercentToSet;
+};
+
+#ifdef ENABLE_SCI32
+
+struct RemapParams {
+ byte from;
+ byte to;
+ byte base;
+ byte gray;
+ byte oldGray;
+ byte percent;
+ byte oldPercent;
+ ColorRemappingType type;
+ Color curColor[256];
+ Color targetColor[256];
+ byte distance[256];
+ byte remap[256];
+ bool colorChanged[256];
+
+ RemapParams() {
+ from = to = base = gray = oldGray = percent = oldPercent = 0;
+ type = kRemappingNone;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+
+ RemapParams(byte from_, byte to_, byte base_, byte gray_, byte percent_, ColorRemappingType type_) {
+ from = from_;
+ to = to_;
+ base = base_;
+ gray = oldGray = gray_;
+ percent = oldPercent = percent_;
+ type = type_;
+
+ // curColor and targetColor are initialized in GfxRemap32::initColorArrays
+ memset(curColor, 0, 256 * sizeof(Color));
+ memset(targetColor, 0, 256 * sizeof(Color));
+ memset(distance, 0, 256);
+ for (int i = 0; i < NON_REMAPPED_COLOR_COUNT; i++)
+ remap[i] = i;
+ Common::fill(colorChanged, colorChanged + ARRAYSIZE(colorChanged), true);
+ }
+};
+
+class GfxRemap32 {
+public:
+ GfxRemap32(GfxPalette32 *palette);
+ ~GfxRemap32() {}
+
+ void remapOff(byte color);
+ void setRemappingRange(byte color, byte from, byte to, byte base);
+ void setRemappingPercent(byte color, byte percent);
+ void setRemappingToGray(byte color, byte gray);
+ void setRemappingToPercentGray(byte color, byte gray, byte percent);
+ void setNoMatchRange(byte from, byte count);
+ bool remapEnabled(byte color) const;
+ byte remapColor(byte color, byte target);
+ bool remapAllTables(bool palChanged);
+ int getRemapCount() const { return _remapCount; }
+ int getStartColor() const { return _remapEndColor - REMAP_COLOR_COUNT + 1; }
+ int getEndColor() const { return _remapEndColor; }
+private:
+ GfxPalette32 *_palette;
+ RemapParams _remaps[REMAP_COLOR_COUNT];
+ bool _update;
+ byte _noMapStart, _noMapCount;
+ bool _targetChanged[NON_REMAPPED_COLOR_COUNT];
+ byte _remapEndColor;
+ int _remapCount;
+
+ void initColorArrays(byte index);
+ bool applyRemap(byte index);
+ bool updateRemap(byte index, bool palChanged);
+};
+#endif
+
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 4cd6344600..c977a93817 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -214,36 +214,6 @@ 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;
- case GFX_SCREEN_UPSCALED_DISABLED:
- break;
- }
}
GfxScreen::~GfxScreen() {
@@ -270,17 +240,26 @@ void GfxScreen::copyToScreen() {
}
void GfxScreen::copyFromScreen(byte *buffer) {
- // TODO this ignores the pitch
Graphics::Surface *screen = g_system->lockScreen();
- memcpy(buffer, screen->getPixels(), _displayPixels);
+
+ if (screen->pitch == _displayWidth) {
+ memcpy(buffer, screen->getPixels(), _displayPixels);
+ } else {
+ const byte *src = (const byte *)screen->getPixels();
+ uint height = _displayHeight;
+
+ while (height--) {
+ memcpy(buffer, src, _displayWidth);
+ buffer += _displayWidth;
+ src += screen->pitch;
+ }
+ }
+
g_system->unlockScreen();
}
void GfxScreen::kernelSyncWithFramebuffer() {
- // TODO this ignores the pitch
- Graphics::Surface *screen = g_system->lockScreen();
- memcpy(_displayScreen, screen->getPixels(), _displayPixels);
- g_system->unlockScreen();
+ copyFromScreen(_displayScreen);
}
void GfxScreen::copyRectToScreen(const Common::Rect &rect) {
@@ -325,40 +304,68 @@ byte GfxScreen::getDrawingMask(byte color, byte prio, byte control) {
return flag;
}
-void GfxScreen::vectorAdjustCoordinateNOP(int16 *x, int16 *y) {
+void GfxScreen::vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300: {
+ int16 displayLeft = (*left * 3) / 2;
+ int16 displayRight = (*right * 3) / 2;
+ int16 displayTop = (*top * 3) / 2;
+ int16 displayBottom = (*bottom * 3) / 2;
+
+ 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;
+ break;
+ }
+ default:
+ break;
+ }
}
-void GfxScreen::vectorAdjustCoordinate480x300Mac(int16 *x, int16 *y) {
- *x = _upscaledWidthMapping[*x];
- *y = _upscaledHeightMapping[*y];
+// This is called from vector drawing to put a pixel at a certain location
+void GfxScreen::vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
+ vectorPutLinePixel480x300(x, y, drawMask, color, priority, control);
+ return;
+ }
+
+ // For anything else forward to the regular putPixel
+ putPixel(x, y, drawMask, color, priority, control);
}
-void GfxScreen::vectorAdjustLineCoordinatesNOP(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control) {
+// Special 480x300 Mac putPixel for vector line drawing, also draws an additional pixel below the actual one
+void GfxScreen::vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ int offset = y * _width + x;
+
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ // also set pixel below actual pixel
+ _visualScreen[offset] = color;
+ _visualScreen[offset + _width] = color;
+ _displayScreen[offset] = color;
+ _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;
+ }
}
-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) {
+byte GfxScreen::vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA) {
int offset = y * _width + x;
byte match = 0;
@@ -388,132 +395,6 @@ byte GfxScreen::vectorIsFillMatchNormal(int16 x, int16 y, byte screenMask, byte
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(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 * _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:
- putScaledPixelOnScreen(_displayScreen, x, actualY, color);
- break;
- }
- }
-}
-
-/**
- * This will just change a pixel directly on displayscreen. It is supposed to be
- * 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(int16 x, int16 y, byte color) {
- int offset = y * _displayWidth + x;
- _displayScreen[offset] = 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;
- int widthOffsetBreak = _upscaledWidthMapping[x + 1] - _upscaledWidthMapping[x];
- do {
- int widthOffset = 0;
- do {
- screen[displayOffset + heightOffset + widthOffset] = data;
- widthOffset++;
- } while (widthOffset != widthOffsetBreak);
- heightOffset += _displayWidth;
- } while (heightOffset != heightOffsetBreak);
-}
-
/**
* Sierra's Bresenham line drawing.
* WARNING: Do not replace this with Graphics::drawLine(), as this causes issues
@@ -595,16 +476,6 @@ void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, u
commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0, -1, -1);
}
-byte GfxScreen::getPixelNormal(byte *screen, int16 x, int16 y) {
- return screen[y * _width + x];
-}
-
-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) {
int byteCount = sizeof(rect) + sizeof(mask);
int pixels = rect.width() * rect.height();
@@ -615,7 +486,7 @@ int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) {
} else {
int rectHeight = _upscaledHeightMapping[rect.bottom] - _upscaledHeightMapping[rect.top];
int rectWidth = _upscaledWidthMapping[rect.right] - _upscaledWidthMapping[rect.left];
- byteCount += rectHeight * rect.width() * rectWidth; // _displayScreen (upscaled hires)
+ byteCount += rectHeight * rectWidth; // _displayScreen (upscaled hires)
}
}
if (mask & GFX_SCREEN_MASK_PRIORITY) {
@@ -629,7 +500,6 @@ int GfxScreen::bitsGetDataSize(Common::Rect rect, byte mask) {
error("bitsGetDataSize() called w/o being in upscaled hires mode");
byteCount += pixels; // _displayScreen (coordinates actually are given to us for hires displayScreen)
}
-
return byteCount;
}
@@ -796,7 +666,7 @@ void GfxScreen::dither(bool addToFlag) {
*displayPtr = color;
break;
default:
- putScaledPixelOnScreen(_displayScreen, x, y, color);
+ putScaledPixelOnDisplay(x, y, color);
break;
}
*visualPtr = color;
@@ -828,7 +698,7 @@ void GfxScreen::dither(bool addToFlag) {
*displayPtr = ditheredColor;
break;
default:
- putScaledPixelOnScreen(_displayScreen, x, y, ditheredColor);
+ putScaledPixelOnDisplay(x, y, ditheredColor);
break;
}
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index 1c946ef02f..65416252f6 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -76,6 +76,11 @@ public:
byte getColorWhite() { return _colorWhite; }
byte getColorDefaultVectorData() { return _colorDefaultVectorData; }
+#ifdef ENABLE_SCI32
+ byte *getDisplayScreen() { return _displayScreen; }
+ byte *getPriorityScreen() { return _priorityScreen; }
+#endif
+
void clearForRestoreGame();
void copyToScreen();
void copyFromScreen(byte *buffer);
@@ -84,51 +89,16 @@ 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);
- }
+ // Vector drawing
+private:
+ void vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
+ void vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte 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);
- }
+public:
+ void vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
+ byte vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA);
byte getDrawingMask(byte color, byte prio, byte control);
- //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);
@@ -206,8 +176,8 @@ private:
byte *_controlScreen;
/**
- * This screen is the one that is actually displayed to the user. It may be
- * 640x400 for japanese SCI1 games. SCI0 games may be undithered in here.
+ * This screen is the one, where pixels are copied out of into the frame buffer.
+ * It may be 640x400 for japanese SCI1 games. SCI0 games may be undithered in here.
* Only read from this buffer for Save/ShowBits usage.
*/
byte *_displayScreen;
@@ -215,8 +185,8 @@ private:
ResourceManager *_resMan;
/**
- * Pointer to the currently active screen (changing it only required for
- * debug purposes).
+ * Pointer to the currently active screen (changing only required for
+ * debug purposes, to show for example the priority screen).
*/
byte *_activeScreen;
@@ -239,38 +209,241 @@ private:
*/
bool _fontIsUpscaled;
- // 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);
+ // pixel related code, in header so that it can be inlined for performance
+public:
+ void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
+ putPixel480x300(x, y, drawMask, color, priority, control);
+ return;
+ }
+
+ // Set pixel for visual, priority and control map directly, those are not upscaled
+ int offset = y * _width + x;
+
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ _visualScreen[offset] = color;
+
+ int displayOffset = 0;
+
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_DISABLED:
+ displayOffset = offset;
+ _displayScreen[displayOffset] = color;
+ break;
+
+ case GFX_SCREEN_UPSCALED_640x400:
+ case GFX_SCREEN_UPSCALED_640x440:
+ case GFX_SCREEN_UPSCALED_640x480:
+ putScaledPixelOnDisplay(x, y, color);
+ break;
+ default:
+ break;
+ }
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
+ _priorityScreen[offset] = priority;
+ }
+ if (drawMask & GFX_SCREEN_MASK_CONTROL) {
+ _controlScreen[offset] = control;
+ }
+ }
- 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 putPixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ int offset = ((y * 3) / 2 * _width) + ((x * 3) / 2);
+
+ // All maps are upscaled
+ // TODO: figure out, what Sierra exactly did on Mac for these games
+ if (drawMask & GFX_SCREEN_MASK_VISUAL) {
+ putPixel480x300Worker(x, y, offset, _visualScreen, color);
+ putPixel480x300Worker(x, y, offset, _displayScreen, color);
+ }
+ if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
+ putPixel480x300Worker(x, y, offset, _priorityScreen, priority);
+ }
+ if (drawMask & GFX_SCREEN_MASK_CONTROL) {
+ putPixel480x300Worker(x, y, offset, _controlScreen, control);
+ }
+ }
+ void putPixel480x300Worker(int16 x, int16 y, int offset, byte *screen, byte byteToSet) {
+ screen[offset] = byteToSet;
+ if (x & 1)
+ screen[offset + 1] = byteToSet;
+ if (y & 1)
+ screen[offset + _width] = byteToSet;
+ if ((x & 1) && (y & 1))
+ screen[offset + _width + 1] = byteToSet;
+ }
- 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);
+ // This is called from vector drawing to put a pixel at a certain location
+ void vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_640x400:
+ case GFX_SCREEN_UPSCALED_640x440:
+ case GFX_SCREEN_UPSCALED_640x480:
+ // For regular upscaled modes forward to the regular putPixel
+ putPixel(x, y, drawMask, color, priority, control);
+ return;
+ break;
+
+ default:
+ break;
+ }
+
+ // For non-upscaled mode and 480x300 Mac put pixels directly
+ 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;
+ }
+ }
- byte (GfxScreen::*_vectorGetPixelPtr) (byte *screen, int16 x, int16 y);
+ /**
+ * This will just change a pixel directly on displayscreen. It is supposed to be
+ * 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 putPixelOnDisplay(int16 x, int16 y, byte color) {
+ int offset = y * _displayWidth + x;
+ _displayScreen[offset] = color;
+ }
- 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);
+ // Upscales a pixel and puts it on display screen only
+ void putScaledPixelOnDisplay(int16 x, int16 y, byte color) {
+ int displayOffset = 0;
+
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_640x400:
+ displayOffset = (y * 2) * _displayWidth + x * 2; // straight 1 pixel -> 2 mapping
+
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ _displayScreen[displayOffset + _displayWidth] = color;
+ _displayScreen[displayOffset + _displayWidth + 1] = color;
+ break;
+
+ case GFX_SCREEN_UPSCALED_640x440: {
+ int16 startY = (y * 11) / 5;
+ int16 endY = ((y + 1) * 11) / 5;
+ displayOffset = (startY * _displayWidth) + x * 2;
+
+ for (int16 curY = startY; curY < endY; curY++) {
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ displayOffset += _displayWidth;
+ }
+ break;
+ }
+ case GFX_SCREEN_UPSCALED_640x480: {
+ int16 startY = (y * 12) / 5;
+ int16 endY = ((y + 1) * 12) / 5;
+ displayOffset = (startY * _displayWidth) + x * 2;
+
+ for (int16 curY = startY; curY < endY; curY++) {
+ _displayScreen[displayOffset] = color;
+ _displayScreen[displayOffset + 1] = color;
+ displayOffset += _displayWidth;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
- 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);
+ /**
+ * 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 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 * _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);
+ break;
+ }
+ }
+ }
- // pixel helper
- void putScaledPixelOnScreen(byte *screen, int16 x, int16 y, byte color);
+ byte getPixel(byte *screen, int16 x, int16 y) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300: {
+ int offset = ((y * 3) / 2) * _width + ((y * 3) / 2);
+
+ return screen[offset];
+ break;
+ }
+ default:
+ break;
+ }
+ return screen[y * _width + x];
+ }
+
+ byte getVisual(int16 x, int16 y) {
+ return getPixel(_visualScreen, x, y);
+ }
+ byte getPriority(int16 x, int16 y) {
+ return getPixel(_priorityScreen, x, y);
+ }
+ byte getControl(int16 x, int16 y) {
+ return getPixel(_controlScreen, x, y);
+ }
+
+ // Vector related public code - in here, so that it can be inlined
+ byte vectorGetPixel(byte *screen, int16 x, int16 y) {
+ return screen[y * _width + x];
+ }
+
+ byte vectorGetVisual(int16 x, int16 y) {
+ return vectorGetPixel(_visualScreen, x, y);
+ }
+ byte vectorGetPriority(int16 x, int16 y) {
+ return vectorGetPixel(_priorityScreen, x, y);
+ }
+ byte vectorGetControl(int16 x, int16 y) {
+ return vectorGetPixel(_controlScreen, x, y);
+ }
+
+ void vectorAdjustCoordinate(int16 *x, int16 *y) {
+ switch (_upscaledHires) {
+ case GFX_SCREEN_UPSCALED_480x300:
+ *x = (*x * 3) / 2;
+ *y = (*y * 3) / 2;
+ break;
+ default:
+ break;
+ }
+ }
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp
new file mode 100644
index 0000000000..c3fdbb6845
--- /dev/null
+++ b/engines/sci/graphics/screen_item32.cpp
@@ -0,0 +1,647 @@
+/* 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 "sci/console.h"
+#include "sci/resource.h"
+#include "sci/engine/kernel.h"
+#include "sci/engine/selector.h"
+#include "sci/engine/state.h"
+#include "sci/graphics/celobj32.h"
+#include "sci/graphics/frameout.h"
+#include "sci/graphics/screen_item32.h"
+#include "sci/graphics/view.h"
+
+namespace Sci {
+#pragma mark ScreenItem
+
+uint16 ScreenItem::_nextObjectId = 20000;
+
+ScreenItem::ScreenItem(const reg_t object) :
+_celObj(nullptr),
+_object(object),
+_pictureId(-1),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_mirrorX(false) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+
+ setFromObject(segMan, object, true, true);
+ _plane = readSelector(segMan, object, SELECTOR(plane));
+}
+
+ScreenItem::ScreenItem(const reg_t plane, const CelInfo32 &celInfo) :
+_plane(plane),
+_useInsetRect(false),
+_z(0),
+_celInfo(celInfo),
+_celObj(nullptr),
+_fixPriority(false),
+_position(0, 0),
+_object(make_reg(0, _nextObjectId++)),
+_pictureId(-1),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_mirrorX(false) {}
+
+ScreenItem::ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect) :
+_plane(plane),
+_useInsetRect(false),
+_z(0),
+_celInfo(celInfo),
+_celObj(nullptr),
+_fixPriority(false),
+_position(rect.left, rect.top),
+_object(make_reg(0, _nextObjectId++)),
+_pictureId(-1),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_mirrorX(false) {
+ if (celInfo.type == kCelTypeColor) {
+ _insetRect = rect;
+ }
+}
+
+ScreenItem::ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo) :
+_plane(plane),
+_scale(scaleInfo),
+_useInsetRect(false),
+_z(0),
+_celInfo(celInfo),
+_celObj(nullptr),
+_fixPriority(false),
+_position(position),
+_object(make_reg(0, _nextObjectId++)),
+_pictureId(-1),
+_created(g_sci->_gfxFrameout->getScreenCount()),
+_updated(0),
+_deleted(0),
+_mirrorX(false) {}
+
+ScreenItem::ScreenItem(const ScreenItem &other) :
+_plane(other._plane),
+_scale(other._scale),
+_useInsetRect(other._useInsetRect),
+_celInfo(other._celInfo),
+_celObj(nullptr),
+_object(other._object),
+_mirrorX(other._mirrorX),
+_scaledPosition(other._scaledPosition),
+_screenRect(other._screenRect) {
+ if (other._useInsetRect) {
+ _insetRect = other._insetRect;
+ }
+}
+
+void ScreenItem::operator=(const ScreenItem &other) {
+ // NOTE: The original engine did not check for differences in `_celInfo`
+ // to clear `_celObj` here; instead, it unconditionally set `_celInfo`,
+ // didn't clear `_celObj`, and did hacky stuff in `kIsOnMe` to avoid
+ // testing a mismatched `_celObj`. See `GfxFrameout::kernelIsOnMe` for
+ // more detail.
+ if (_celInfo != other._celInfo) {
+ _celInfo = other._celInfo;
+ delete _celObj;
+ _celObj = nullptr;
+ }
+
+ _screenRect = other._screenRect;
+ _mirrorX = other._mirrorX;
+ _useInsetRect = other._useInsetRect;
+ if (other._useInsetRect) {
+ _insetRect = other._insetRect;
+ }
+ _scale = other._scale;
+ _scaledPosition = other._scaledPosition;
+}
+
+ScreenItem::~ScreenItem() {
+ delete _celObj;
+}
+
+void ScreenItem::init() {
+ _nextObjectId = 20000;
+}
+
+void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const bool updateCel, const bool updateBitmap) {
+ _position.x = readSelectorValue(segMan, object, SELECTOR(x));
+ _position.y = readSelectorValue(segMan, object, SELECTOR(y));
+ _scale.x = readSelectorValue(segMan, object, SELECTOR(scaleX));
+ _scale.y = readSelectorValue(segMan, object, SELECTOR(scaleY));
+ _scale.max = readSelectorValue(segMan, object, SELECTOR(maxScale));
+ _scale.signal = (ScaleSignals32)(readSelectorValue(segMan, object, SELECTOR(scaleSignal)) & 3);
+
+ if (updateCel) {
+ _celInfo.resourceId = (GuiResourceId)readSelectorValue(segMan, object, SELECTOR(view));
+ _celInfo.loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
+ _celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel));
+
+ if (_celInfo.resourceId <= kPlanePic) {
+ // TODO: Enhance GfxView or ResourceManager to allow
+ // metadata for resources to be retrieved once, from a
+ // single location
+ Resource *view = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, _celInfo.resourceId), false);
+ if (!view) {
+ error("Failed to load resource %d", _celInfo.resourceId);
+ }
+
+ // NOTE: +2 because the header size field itself is excluded from
+ // the header size in the data
+ const uint16 headerSize = READ_SCI11ENDIAN_UINT16(view->data) + 2;
+ const uint8 loopCount = view->data[2];
+ const uint8 loopSize = view->data[12];
+
+ if (_celInfo.loopNo >= loopCount) {
+ const int maxLoopNo = loopCount - 1;
+ _celInfo.loopNo = maxLoopNo;
+ writeSelectorValue(segMan, object, SELECTOR(loop), maxLoopNo);
+ }
+
+ byte *loopData = view->data + headerSize + (_celInfo.loopNo * loopSize);
+ const int8 seekEntry = loopData[0];
+ if (seekEntry != -1) {
+ loopData = view->data + headerSize + (seekEntry * loopSize);
+ }
+ const uint8 celCount = loopData[2];
+ if (_celInfo.celNo >= celCount) {
+ const int maxCelNo = celCount - 1;
+ _celInfo.celNo = maxCelNo;
+ writeSelectorValue(segMan, object, SELECTOR(cel), maxCelNo);
+ }
+ }
+ }
+
+ if (updateBitmap) {
+ const reg_t bitmap = readSelector(segMan, object, SELECTOR(bitmap));
+ if (!bitmap.isNull()) {
+ _celInfo.bitmap = bitmap;
+ _celInfo.type = kCelTypeMem;
+ } else {
+ _celInfo.bitmap = NULL_REG;
+ _celInfo.type = kCelTypeView;
+ }
+ }
+
+ if (updateCel || updateBitmap) {
+ delete _celObj;
+ _celObj = nullptr;
+ }
+
+ if (readSelectorValue(segMan, object, SELECTOR(fixPriority))) {
+ _fixPriority = true;
+ _priority = readSelectorValue(segMan, object, SELECTOR(priority));
+ } else {
+ _fixPriority = false;
+ writeSelectorValue(segMan, object, SELECTOR(priority), _position.y);
+ }
+
+ _z = readSelectorValue(segMan, object, SELECTOR(z));
+ _position.y -= _z;
+
+ if (readSelectorValue(segMan, object, SELECTOR(useInsetRect))) {
+ _useInsetRect = true;
+ _insetRect.left = readSelectorValue(segMan, object, SELECTOR(inLeft));
+ _insetRect.top = readSelectorValue(segMan, object, SELECTOR(inTop));
+ _insetRect.right = readSelectorValue(segMan, object, SELECTOR(inRight)) + 1;
+ _insetRect.bottom = readSelectorValue(segMan, object, SELECTOR(inBottom)) + 1;
+ } else {
+ _useInsetRect = false;
+ }
+
+ segMan->getObject(object)->clearInfoSelectorFlag(kInfoFlagViewVisible);
+}
+
+void ScreenItem::calcRects(const Plane &plane) {
+ const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
+ const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+
+ const CelObj &celObj = getCelObj();
+
+ Common::Rect celRect(celObj._width, celObj._height);
+ if (_useInsetRect) {
+ if (_insetRect.intersects(celRect)) {
+ _insetRect.clip(celRect);
+ } else {
+ _insetRect = Common::Rect();
+ }
+ } else {
+ _insetRect = celRect;
+ }
+
+ Ratio scaleX, scaleY;
+
+ if (_scale.signal & kScaleSignalDoScaling32) {
+ if (_scale.signal & kScaleSignalUseVanishingPoint) {
+ int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y);
+ scaleX = Ratio(num, 128);
+ scaleY = Ratio(num, 128);
+ } else {
+ scaleX = Ratio(_scale.x, 128);
+ scaleY = Ratio(_scale.y, 128);
+ }
+ }
+
+ if (scaleX.getNumerator() && scaleY.getNumerator()) {
+ _screenItemRect = _insetRect;
+
+ const Ratio celToScreenX(screenWidth, celObj._scaledWidth);
+ const Ratio celToScreenY(screenHeight, celObj._scaledHeight);
+
+ // Cel may use a coordinate system that is not the same size as the
+ // script coordinate system (usually this means high-resolution
+ // pictures with low-resolution scripts)
+ if (celObj._scaledWidth != scriptWidth || celObj._scaledHeight != scriptHeight) {
+ if (_useInsetRect) {
+ const Ratio scriptToCelX(celObj._scaledWidth, scriptWidth);
+ const Ratio scriptToCelY(celObj._scaledHeight, scriptHeight);
+ mulru(_screenItemRect, scriptToCelX, scriptToCelY, 0);
+
+ if (_screenItemRect.intersects(celRect)) {
+ _screenItemRect.clip(celRect);
+ } else {
+ _screenItemRect = Common::Rect();
+ }
+ }
+
+ int displaceX = celObj._displace.x;
+ int displaceY = celObj._displace.y;
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ displaceX = celObj._width - celObj._displace.x - 1;
+ }
+
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(_screenItemRect, scaleX, scaleY);
+ displaceX = (displaceX * scaleX).toInt();
+ displaceY = (displaceY * scaleY).toInt();
+ }
+
+ mulinc(_screenItemRect, celToScreenX, celToScreenY);
+ displaceX = (displaceX * celToScreenX).toInt();
+ displaceY = (displaceY * celToScreenY).toInt();
+
+ const Ratio scriptToScreenX = Ratio(screenWidth, scriptWidth);
+ const Ratio scriptToScreenY = Ratio(screenHeight, scriptHeight);
+
+ if (/* TODO: dword_C6288 */ false && _celInfo.type == kCelTypePic) {
+ _scaledPosition.x = _position.x;
+ _scaledPosition.y = _position.y;
+ } else {
+ _scaledPosition.x = (_position.x * scriptToScreenX).toInt() - displaceX;
+ _scaledPosition.y = (_position.y * scriptToScreenY).toInt() - displaceY;
+ }
+
+ _screenItemRect.translate(_scaledPosition.x, _scaledPosition.y);
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type == kCelTypePic) {
+ Common::Rect temp(_insetRect);
+
+ if (!scaleX.isOne()) {
+ mulinc(temp, scaleX, Ratio());
+ }
+
+ mulinc(temp, celToScreenX, Ratio());
+
+ CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
+ temp.translate((celObjPic->_relativePosition.x * scriptToScreenX).toInt() - displaceX, 0);
+
+ // TODO: This is weird.
+ int deltaX = plane._planeRect.width() - temp.right - 1 - temp.left;
+
+ _scaledPosition.x += deltaX;
+ _screenItemRect.translate(deltaX, 0);
+ }
+
+ _scaledPosition.x += plane._planeRect.left;
+ _scaledPosition.y += plane._planeRect.top;
+ _screenItemRect.translate(plane._planeRect.left, plane._planeRect.top);
+
+ _ratioX = scaleX * celToScreenX;
+ _ratioY = scaleY * celToScreenY;
+ } else {
+ int displaceX = celObj._displace.x;
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ displaceX = celObj._width - celObj._displace.x - 1;
+ }
+
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(_screenItemRect, scaleX, scaleY);
+ // TODO: This was in the original code, baked into the
+ // multiplication though it is not immediately clear
+ // why this is the only one that reduces the BR corner
+ _screenItemRect.right -= 1;
+ _screenItemRect.bottom -= 1;
+ }
+
+ _scaledPosition.x = _position.x - (displaceX * scaleX).toInt();
+ _scaledPosition.y = _position.y - (celObj._displace.y * scaleY).toInt();
+ _screenItemRect.translate(_scaledPosition.x, _scaledPosition.y);
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type == kCelTypePic) {
+ Common::Rect temp(_insetRect);
+
+ if (!scaleX.isOne()) {
+ mulinc(temp, scaleX, Ratio());
+ temp.right -= 1;
+ }
+
+ CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
+ temp.translate(celObjPic->_relativePosition.x - (displaceX * scaleX).toInt(), celObjPic->_relativePosition.y - (celObj._displace.y * scaleY).toInt());
+
+ // TODO: This is weird.
+ int deltaX = plane._gameRect.width() - temp.right - 1 - temp.left;
+
+ _scaledPosition.x += deltaX;
+ _screenItemRect.translate(deltaX, 0);
+ }
+
+ _scaledPosition.x += plane._gameRect.left;
+ _scaledPosition.y += plane._gameRect.top;
+ _screenItemRect.translate(plane._gameRect.left, plane._gameRect.top);
+
+ if (celObj._scaledWidth != screenWidth || celObj._scaledHeight != screenHeight) {
+ mulru(_scaledPosition, celToScreenX, celToScreenY);
+ mulru(_screenItemRect, celToScreenX, celToScreenY, 1);
+ }
+
+ _ratioX = scaleX * celToScreenX;
+ _ratioY = scaleY * celToScreenY;
+ }
+
+ _screenRect = _screenItemRect;
+
+ if (_screenRect.intersects(plane._screenRect)) {
+ _screenRect.clip(plane._screenRect);
+ } else {
+ _screenRect.right = 0;
+ _screenRect.bottom = 0;
+ _screenRect.left = 0;
+ _screenRect.top = 0;
+ }
+
+ if (!_fixPriority) {
+ _priority = _z + _position.y;
+ }
+ } else {
+ _screenRect.left = 0;
+ _screenRect.top = 0;
+ _screenRect.right = 0;
+ _screenRect.bottom = 0;
+ }
+}
+
+CelObj &ScreenItem::getCelObj() const {
+ if (_celObj == nullptr) {
+ switch (_celInfo.type) {
+ case kCelTypeView:
+ _celObj = new CelObjView(_celInfo.resourceId, _celInfo.loopNo, _celInfo.celNo);
+ break;
+ case kCelTypePic:
+ error("Internal error, pic screen item with no cel.");
+ break;
+ case kCelTypeMem:
+ _celObj = new CelObjMem(_celInfo.bitmap);
+ break;
+ case kCelTypeColor:
+ _celObj = new CelObjColor(_celInfo.color, _insetRect.width(), _insetRect.height());
+ break;
+ }
+ }
+
+ return *_celObj;
+}
+
+void ScreenItem::printDebugInfo(Console *con) const {
+ con->debugPrintf("%04x:%04x (%s), prio %d, x %d, y %d, z: %d, scaledX: %d, scaledY: %d flags: %d\n",
+ _object.getSegment(), _object.getOffset(),
+ g_sci->getEngineState()->_segMan->getObjectName(_object),
+ _priority,
+ _position.x,
+ _position.y,
+ _z,
+ _scaledPosition.x,
+ _scaledPosition.y,
+ _created | (_updated << 1) | (_deleted << 2)
+ );
+ con->debugPrintf(" screen rect (%d, %d, %d, %d)\n", PRINT_RECT(_screenRect));
+ if (_useInsetRect) {
+ con->debugPrintf(" inset rect: (%d, %d, %d, %d)\n", PRINT_RECT(_insetRect));
+ }
+
+ Common::String celType;
+ switch (_celInfo.type) {
+ case kCelTypePic:
+ celType = "pic";
+ break;
+ case kCelTypeView:
+ celType = "view";
+ break;
+ case kCelTypeColor:
+ celType = "color";
+ break;
+ case kCelTypeMem:
+ celType = "mem";
+ break;
+ }
+
+ con->debugPrintf(" type: %s, res %d, loop %d, cel %d, bitmap %04x:%04x, color: %d\n",
+ celType.c_str(),
+ _celInfo.resourceId,
+ _celInfo.loopNo,
+ _celInfo.celNo,
+ PRINT_REG(_celInfo.bitmap),
+ _celInfo.color
+ );
+ if (_celObj != nullptr) {
+ con->debugPrintf(" width %d, height %d, scaledWidth %d, scaledHeight %d\n",
+ _celObj->_width,
+ _celObj->_height,
+ _celObj->_scaledWidth,
+ _celObj->_scaledHeight
+ );
+ }
+}
+
+void ScreenItem::update(const reg_t object) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+
+ const GuiResourceId view = readSelectorValue(segMan, object, SELECTOR(view));
+ const int16 loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
+ const int16 celNo = readSelectorValue(segMan, object, SELECTOR(cel));
+
+ const bool updateCel = (
+ _celInfo.resourceId != view ||
+ _celInfo.loopNo != loopNo ||
+ _celInfo.celNo != celNo
+ );
+
+ const bool updateBitmap = !readSelector(segMan, object, SELECTOR(bitmap)).isNull();
+
+ setFromObject(segMan, object, updateCel, updateBitmap);
+
+ if (!_created) {
+ _updated = g_sci->_gfxFrameout->getScreenCount();
+ }
+
+ _deleted = 0;
+}
+
+// TODO: This code is quite similar to calcRects, so try to deduplicate
+// if possible
+Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
+ CelObj &celObj = getCelObj();
+
+ Common::Rect celObjRect(celObj._width, celObj._height);
+ Common::Rect nsRect;
+
+ if (_useInsetRect) {
+ // TODO: This is weird. Checking to see if the inset rect is
+ // fully inside the bounds of the celObjRect, and then
+ // clipping to the celObjRect, is pretty useless.
+ if (_insetRect.right > 0 && _insetRect.bottom > 0 && _insetRect.left < celObj._width && _insetRect.top < celObj._height) {
+ nsRect = _insetRect;
+ nsRect.clip(celObjRect);
+ } else {
+ nsRect = Common::Rect();
+ }
+ } else {
+ nsRect = celObjRect;
+ }
+
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ Ratio scaleX, scaleY;
+ if (_scale.signal & kScaleSignalDoScaling32) {
+ if (_scale.signal & kScaleSignalUseVanishingPoint) {
+ int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y);
+ scaleX = Ratio(num, 128);
+ scaleY = Ratio(num, 128);
+ } else {
+ scaleX = Ratio(_scale.x, 128);
+ scaleY = Ratio(_scale.y, 128);
+ }
+ }
+
+ if (scaleX.getNumerator() == 0 || scaleY.getNumerator() == 0) {
+ return Common::Rect();
+ }
+
+ int16 displaceX = celObj._displace.x;
+ int16 displaceY = celObj._displace.y;
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ displaceX = celObj._width - displaceX - 1;
+ }
+
+ if (celObj._scaledWidth != scriptWidth || celObj._scaledHeight != scriptHeight) {
+ if (_useInsetRect) {
+ Ratio scriptToCelX(celObj._scaledWidth, scriptWidth);
+ Ratio scriptToCelY(celObj._scaledHeight, scriptHeight);
+ mulru(nsRect, scriptToCelX, scriptToCelY, 0);
+
+ // TODO: This is weird. Checking to see if the inset rect is
+ // fully inside the bounds of the celObjRect, and then
+ // clipping to the celObjRect, is pretty useless.
+ if (nsRect.right > 0 && nsRect.bottom > 0 && nsRect.left < celObj._width && nsRect.top < celObj._height) {
+ nsRect.clip(celObjRect);
+ } else {
+ nsRect = Common::Rect();
+ }
+ }
+
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(nsRect, scaleX, scaleY);
+ // TODO: This was in the original code, baked into the
+ // multiplication though it is not immediately clear
+ // why this is the only one that reduces the BR corner
+ nsRect.right -= 1;
+ nsRect.bottom -= 1;
+ }
+
+ Ratio celToScriptX(scriptWidth, celObj._scaledWidth);
+ Ratio celToScriptY(scriptHeight, celObj._scaledHeight);
+
+ displaceX = (displaceX * scaleX * celToScriptX).toInt();
+ displaceY = (displaceY * scaleY * celToScriptY).toInt();
+
+ mulinc(nsRect, celToScriptX, celToScriptY);
+ nsRect.translate(_position.x - displaceX, _position.y - displaceY);
+ } else {
+ if (!scaleX.isOne() || !scaleY.isOne()) {
+ mulinc(nsRect, scaleX, scaleY);
+ // TODO: This was in the original code, baked into the
+ // multiplication though it is not immediately clear
+ // why this is the only one that reduces the BR corner
+ nsRect.right -= 1;
+ nsRect.bottom -= 1;
+ }
+
+ displaceX = (displaceX * scaleX).toInt();
+ displaceY = (displaceY * scaleY).toInt();
+ nsRect.translate(_position.x - displaceX, _position.y - displaceY);
+
+ if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
+ nsRect.translate(plane._gameRect.width() - nsRect.width(), 0);
+ }
+ }
+
+ return nsRect;
+}
+
+#pragma mark -
+#pragma mark ScreenItemList
+ScreenItem *ScreenItemList::findByObject(const reg_t object) const {
+ const_iterator screenItemIt = Common::find_if(begin(), end(), FindByObject<ScreenItem *>(object));
+
+ if (screenItemIt == end()) {
+ return nullptr;
+ }
+
+ return *screenItemIt;
+}
+void ScreenItemList::sort() {
+ // TODO: SCI engine used _unsorted as an array of indexes into the
+ // list itself and then performed the same swap operations on the
+ // _unsorted array as the _storage array during sorting, but the
+ // only reason to do this would be if some of the pointers in the
+ // list were replaced so the pointer values themselves couldn’t
+ // simply be recorded and then restored later. It is not yet
+ // verified whether this simplification of the sort/unsort is
+ // safe.
+ for (size_type i = 0; i < size(); ++i) {
+ _unsorted[i] = (*this)[i];
+ }
+
+ Common::sort(begin(), end(), sortHelper);
+}
+void ScreenItemList::unsort() {
+ for (size_type i = 0; i < size(); ++i) {
+ (*this)[i] = _unsorted[i];
+ }
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h
new file mode 100644
index 0000000000..977d80ebad
--- /dev/null
+++ b/engines/sci/graphics/screen_item32.h
@@ -0,0 +1,288 @@
+/* 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 SCI_GRAPHICS_SCREEN_ITEM32_H
+#define SCI_GRAPHICS_SCREEN_ITEM32_H
+
+#include "common/rect.h"
+#include "sci/graphics/celobj32.h"
+#include "sci/graphics/lists32.h"
+
+namespace Sci {
+
+enum ScaleSignals32 {
+ kScaleSignalNone = 0,
+ kScaleSignalDoScaling32 = 1, // enables scaling when drawing that cel (involves scaleX and scaleY)
+ kScaleSignalUseVanishingPoint = 2,
+ // TODO: Is this actually a thing? I have not seen it and
+ // the original engine masks &3 where it uses scale signals.
+ kScaleSignalDisableGlobalScaling32 = 4
+};
+
+struct ScaleInfo {
+ int x, y, max;
+ ScaleSignals32 signal;
+ ScaleInfo() : x(128), y(128), max(100), signal(kScaleSignalNone) {}
+};
+
+class CelObj;
+class Plane;
+class SegManager;
+
+#pragma mark -
+#pragma mark ScreenItem
+
+/**
+ * A ScreenItem is the engine-side representation of a
+ * game script View.
+ */
+class ScreenItem {
+private:
+ /**
+ * A serial used for screen items that are generated
+ * inside the graphics engine, rather than the
+ * interpreter.
+ */
+ static uint16 _nextObjectId;
+
+ /**
+ * The parent plane of this screen item.
+ */
+ reg_t _plane;
+
+public:
+ /**
+ * Scaling data used to calculate the final screen
+ * dimensions of the screen item as well as the scaling
+ * ratios used when drawing the item to screen.
+ */
+ ScaleInfo _scale;
+
+private:
+ /**
+ * The position & dimensions of the screen item in
+ * screen coordinates. This rect includes the offset
+ * of the parent plane, but is not clipped to the
+ * screen, so may include coordinates that are
+ * offscreen.
+ */
+ Common::Rect _screenItemRect;
+
+ /**
+ * TODO: Document
+ */
+ bool _useInsetRect;
+
+ /**
+ * TODO: Documentation
+ * The insetRect is also used to describe the fill
+ * rectangle of a screen item that is drawn using
+ * CelObjColor.
+ */
+ Common::Rect _insetRect;
+
+ /**
+ * The z-index of the screen item in pseudo-3D space.
+ * Higher values are drawn on top of lower values.
+ */
+ int _z;
+
+ /**
+ * Sets the common properties of a screen item that must
+ * be set both during creation and update of a screen
+ * item.
+ */
+ void setFromObject(SegManager *segMan, const reg_t object, const bool updateCel, const bool updateBitmap);
+
+public:
+ /**
+ * A descriptor for the cel object represented by the
+ * screen item.
+ */
+ CelInfo32 _celInfo;
+
+ /**
+ * The cel object used to actually render the screen
+ * item. This member is populated by calling
+ * `getCelObj`.
+ */
+ mutable CelObj *_celObj;
+
+ /**
+ * If set, the priority for this screen item is fixed
+ * in place. Otherwise, the priority of the screen item
+ * is calculated from its y-position + z-index.
+ */
+ bool _fixPriority;
+
+ /**
+ * The rendering priority of the screen item, relative
+ * only to the other screen items within the same plane.
+ * Higher priorities are drawn above lower priorities.
+ */
+ int16 _priority;
+
+ /**
+ * The top-left corner of the screen item, in game
+ * script coordinates, relative to the parent plane.
+ */
+ Common::Point _position;
+
+ /**
+ * The associated View script object that was
+ * used to create the ScreenItem, or a numeric
+ * value in the case of a ScreenItem that was
+ * generated outside of the VM.
+ */
+ reg_t _object;
+
+ /**
+ * For screen items representing picture resources,
+ * the resource ID of the picture.
+ */
+ GuiResourceId _pictureId;
+
+ /**
+ * Flags indicating the state of the screen item.
+ * - `created` is set when the screen item is first
+ * created, either from a VM object or from within the
+ * engine itself
+ * - `updated` is set when `created` is not already set
+ * and the screen item is updated from a VM object
+ * - `deleted` is set by the parent plane, if the parent
+ * plane is a pic type and its picture resource ID has
+ * changed
+ */
+ int _created, _updated, _deleted; // ?
+
+ /**
+ * For screen items that represent picture cels, this
+ * value is set to match the `_mirrorX` property of the
+ * parent plane and indicates that the cel should be
+ * drawn horizontally mirrored. For final drawing, it is
+ * XORed with the `_mirrorX` property of the cel object.
+ * The cel object's `_mirrorX` property comes from the
+ * resource data itself.
+ */
+ bool _mirrorX;
+
+ /**
+ * The scaling ratios to use when drawing this screen
+ * item. These values are calculated according to the
+ * scale info whenever the screen item is updated.
+ */
+ Ratio _ratioX, _ratioY;
+
+ /**
+ * The top-left corner of the screen item, in screen
+ * coordinates.
+ */
+ Common::Point _scaledPosition;
+
+ /**
+ * The position & dimensions of the screen item in
+ * screen coordinates. This rect includes the offset of
+ * the parent plane and is clipped to the screen.
+ */
+ Common::Rect _screenRect;
+
+ /**
+ * Initialises static Plane members.
+ */
+ static void init();
+
+ ScreenItem(const reg_t screenItem);
+ ScreenItem(const reg_t plane, const CelInfo32 &celInfo);
+ ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect);
+ ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo);
+ ScreenItem(const ScreenItem &other);
+ ~ScreenItem();
+ void operator=(const ScreenItem &);
+
+ inline bool operator<(const ScreenItem &other) const {
+ if (_priority < other._priority) {
+ return true;
+ }
+
+ if (_priority == other._priority) {
+ if (_position.y + _z < other._position.y + other._z) {
+ return true;
+ }
+
+ if (_position.y + _z == other._position.y + other._z) {
+ return _object < other._object;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Calculates the dimensions and scaling parameters for
+ * the screen item, using the given plane as the parent
+ * plane for screen rect positioning.
+ *
+ * @note This method was called Update in SCI engine.
+ */
+ void calcRects(const Plane &plane);
+
+ /**
+ * Retrieves the corresponding cel object for this
+ * screen item. If a cel object does not already exist,
+ * one will be created and assigned.
+ */
+ CelObj &getCelObj() const;
+
+ void printDebugInfo(Console *con) const;
+
+ /**
+ * Updates the properties of the screen item from a
+ * VM object.
+ */
+ void update(const reg_t object);
+
+ /**
+ * Gets the "now seen" rect for the screen item, which
+ * represents the current size and position of the
+ * screen item on the screen in script coordinates.
+ */
+ Common::Rect getNowSeenRect(const Plane &plane) const;
+};
+
+#pragma mark -
+#pragma mark ScreenItemList
+
+typedef StablePointerArray<ScreenItem, 250> ScreenItemListBase;
+class ScreenItemList : public ScreenItemListBase {
+ static bool inline sortHelper(const ScreenItem *a, const ScreenItem *b) {
+ return *a < *b;
+ }
+public:
+ ScreenItem *_unsorted[250];
+
+ ScreenItem *findByObject(const reg_t object) const;
+ void sort();
+ void unsort();
+};
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index 56ce73e8fa..99ffc6e328 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -29,363 +29,629 @@
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
+#include "sci/graphics/celobj32.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/font.h"
+#include "sci/graphics/frameout.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/text32.h"
namespace Sci {
-#define BITMAP_HEADER_SIZE 46
+int16 GfxText32::_defaultFontId = 0;
+
+GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) :
+ _segMan(segMan),
+ _cache(fonts),
+ _scaledWidth(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),
+ _scaledHeight(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight),
+ // Not a typo, the original engine did not initialise height, only width
+ _width(0),
+ _text(""),
+ _field_20(0),
+ _field_2C(2),
+ _field_30(0),
+ _field_34(0),
+ _field_38(0),
+ _field_3C(0),
+ _bitmap(NULL_REG) {
+ _fontId = _defaultFontId;
+ _font = _cache->getFont(_defaultFontId);
+ }
-#define SCI_TEXT32_ALIGNMENT_RIGHT -1
-#define SCI_TEXT32_ALIGNMENT_CENTER 1
-#define SCI_TEXT32_ALIGNMENT_LEFT 0
+reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling) {
-GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen)
- : _segMan(segMan), _cache(fonts), _screen(screen) {
-}
+ _field_22 = 0;
+ _borderColor = borderColor;
+ _text = text;
+ _textRect = rect;
+ _width = width;
+ _height = height;
+ _foreColor = foreColor;
+ _backColor = backColor;
+ _skipColor = skipColor;
+ _alignment = alignment;
+ _dimmed = dimmed;
-GfxText32::~GfxText32() {
-}
+ setFont(fontId);
-reg_t GfxText32::createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
- return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk);
+ if (doScaling) {
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
-}
-reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
- reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text));
- // The object in the text selector of the item can be either a raw string
- // or a Str object. In the latter case, we need to access the object's data
- // selector to get the raw string.
- if (_segMan->isHeapObject(stringObject))
- stringObject = readSelector(_segMan, stringObject, SELECTOR(data));
+ Ratio scaleX(_scaledWidth, scriptWidth);
+ Ratio scaleY(_scaledHeight, scriptHeight);
- Common::String text = _segMan->getString(stringObject);
+ _width = (_width * scaleX).toInt();
+ _height = (_height * scaleY).toInt();
+ mulinc(_textRect, scaleX, scaleY);
+ }
- return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk);
-}
+ // _textRect represents where text is drawn inside the
+ // bitmap; clipRect is the entire bitmap
+ Common::Rect bitmapRect(_width, _height);
-reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
- // HACK: The character offsets of the up and down arrow buttons are off by one
- // in GK1, for some unknown reason. Fix them here.
- if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) {
- text.setChar(text[0] + 1, 0);
- }
- GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font));
- GfxFont *font = _cache->getFont(fontId);
- bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed));
- int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode));
- uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore));
- uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back));
-
- Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject);
- uint16 width = nsRect.width() + 1;
- uint16 height = nsRect.height() + 1;
-
- // Limit rectangle dimensions, if requested
- if (maxWidth > 0)
- width = maxWidth;
- if (maxHeight > 0)
- height = maxHeight;
-
- // Upscale the coordinates/width if the fonts are already upscaled
- if (_screen->fontIsUpscaled()) {
- width = width * _screen->getDisplayWidth() / _screen->getWidth();
- height = height * _screen->getDisplayHeight() / _screen->getHeight();
+ if (_textRect.intersects(bitmapRect)) {
+ _textRect.clip(bitmapRect);
+ } else {
+ _textRect = Common::Rect();
}
- int entrySize = width * height + BITMAP_HEADER_SIZE;
- reg_t memoryId = NULL_REG;
- if (prevHunk.isNull()) {
- memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize);
+ BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);
+ _bitmap = bitmap.getObject();
- // Scroll text objects have no bitmap selector!
- ObjVarRef varp;
- if (lookupSelector(_segMan, textObject, SELECTOR(bitmap), &varp, NULL) == kSelectorVariable)
- writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId);
- } else {
- memoryId = prevHunk;
+ erase(bitmapRect, false);
+
+ if (_borderColor > -1) {
+ drawFrame(bitmapRect, 1, _borderColor, false);
}
- byte *memoryPtr = _segMan->getHunkPointer(memoryId);
- if (prevHunk.isNull())
- memset(memoryPtr, 0, BITMAP_HEADER_SIZE);
+ drawTextBox();
+ return _bitmap;
+}
- byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
- memset(bitmap, backColor, width * height);
+reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed) {
+ _field_22 = 0;
+ _borderColor = borderColor;
+ _text = text;
+ _textRect = rect;
+ _foreColor = foreColor;
+ _dimmed = dimmed;
- // Save totalWidth, totalHeight
- WRITE_LE_UINT16(memoryPtr, width);
- WRITE_LE_UINT16(memoryPtr + 2, height);
+ setFont(fontId);
- int16 charCount = 0;
- uint16 curX = 0, curY = 0;
- const char *txt = text.c_str();
- int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0;
- uint16 start = 0;
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- // Calculate total text height
- while (*txt) {
- charCount = GetLongest(txt, width, font);
- if (charCount == 0)
- break;
+ int borderSize = 1;
+ mulinc(_textRect, Ratio(_scaledWidth, scriptWidth), Ratio(_scaledHeight, scriptHeight));
- Width(txt, 0, (int16)strlen(txt), fontId, textWidth, textHeight, true);
+ CelObjView view(celInfo.resourceId, celInfo.loopNo, celInfo.celNo);
+ _skipColor = view._transparentColor;
+ _width = view._width * _scaledWidth / view._scaledWidth;
+ _height = view._height * _scaledHeight / view._scaledHeight;
- totalHeight += textHeight;
- txt += charCount;
- while (*txt == ' ')
- txt++; // skip over breaking spaces
+ Common::Rect bitmapRect(_width, _height);
+ if (_textRect.intersects(bitmapRect)) {
+ _textRect.clip(bitmapRect);
+ } else {
+ _textRect = Common::Rect();
}
- txt = text.c_str();
-
- // Draw text in buffer
- while (*txt) {
- charCount = GetLongest(txt, width, font);
- if (charCount == 0)
- break;
- Width(txt, start, charCount, fontId, textWidth, textHeight, true);
-
- switch (alignment) {
- case SCI_TEXT32_ALIGNMENT_RIGHT:
- offsetX = width - textWidth;
- break;
- case SCI_TEXT32_ALIGNMENT_CENTER:
- // Center text both horizontally and vertically
- offsetX = (width - textWidth) / 2;
- offsetY = (height - totalHeight) / 2;
- break;
- case SCI_TEXT32_ALIGNMENT_LEFT:
- offsetX = 0;
- break;
-
- default:
- warning("Invalid alignment %d used in TextBox()", alignment);
- }
+ BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);
+ _bitmap = bitmap.getObject();
+ Buffer buffer(_width, _height, bitmap.getPixels());
+
+ // NOTE: The engine filled the bitmap pixels with 11 here, which is silly
+ // because then it just erased the bitmap using the skip color. So we don't
+ // fill the bitmap redundantly here.
- byte curChar;
-
- for (int i = 0; i < charCount; i++) {
- curChar = txt[i];
-
- switch (curChar) {
- case 0x0A:
- case 0x0D:
- case 0:
- break;
- case 0x7C:
- warning("Code processing isn't implemented in SCI32");
- break;
- default:
- font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height);
- curX += font->getCharWidth(curChar);
- break;
+ _backColor = _skipColor;
+ erase(bitmapRect, false);
+ _backColor = backColor;
+
+ view.draw(buffer, bitmapRect, Common::Point(0, 0), false, Ratio(_scaledWidth, view._scaledWidth), Ratio(_scaledHeight, view._scaledHeight));
+
+ if (_backColor != skipColor && _foreColor != skipColor) {
+ erase(_textRect, false);
+ }
+
+ if (text.size() > 0) {
+ if (_foreColor == skipColor) {
+ error("TODO: Implement transparent text");
+ } else {
+ if (borderColor != -1) {
+ drawFrame(bitmapRect, borderSize, _borderColor, false);
}
- }
- curX = 0;
- curY += font->getHeight();
- txt += charCount;
- while (*txt == ' ')
- txt++; // skip over breaking spaces
+ drawTextBox();
+ }
}
- return memoryId;
+ return _bitmap;
}
-void GfxText32::disposeTextBitmap(reg_t hunkId) {
- _segMan->freeHunkEntry(hunkId);
+reg_t GfxText32::createTitledBitmap(const int16 width, const int16 height, const Common::Rect &textRect, const Common::String &text, const int16 foreColor, const int16 backColor, const int16 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, Common::String &title, const int16 titleForeColor, const int16 titleBackColor, const GuiResourceId titleFontId, const bool doScaling) {
+ warning("TODO: createTitledBitmap incomplete !");
+ return createFontBitmap(width, height, textRect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, false, doScaling);
}
-void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) {
- reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap));
- drawTextBitmapInternal(x, y, planeRect, textObject, hunkId);
+void GfxText32::setFont(const GuiResourceId fontId) {
+ // NOTE: In SCI engine this calls FontMgr::BuildFontTable and then a font
+ // table is built on the FontMgr directly; instead, because we already have
+ // font resources, this code just grabs a font out of GfxCache.
+ if (fontId != _fontId) {
+ _fontId = fontId == -1 ? _defaultFontId : fontId;
+ _font = _cache->getFont(_fontId);
+ }
}
-void GfxText32::drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y) {
- /*reg_t plane = readSelector(_segMan, textObject, SELECTOR(plane));
- Common::Rect planeRect;
- planeRect.top = readSelectorValue(_segMan, plane, SELECTOR(top));
- planeRect.left = readSelectorValue(_segMan, plane, SELECTOR(left));
- planeRect.bottom = readSelectorValue(_segMan, plane, SELECTOR(bottom));
- planeRect.right = readSelectorValue(_segMan, plane, SELECTOR(right));
+void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling) {
+ Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;
- drawTextBitmapInternal(x, y, planeRect, textObject, hunkId);*/
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28) + rect.top * _width + rect.left;
- // HACK: we pretty much ignore the plane rect and x, y...
- drawTextBitmapInternal(0, 0, Common::Rect(20, 390, 600, 460), textObject, hunkId);
+ // NOTE: Not fully disassembled, but this should be right
+ int16 rectWidth = targetRect.width();
+ int16 sidesHeight = targetRect.height() - size * 2;
+ int16 centerWidth = rectWidth - size * 2;
+ int16 stride = _width - rectWidth;
+
+ for (int16 y = 0; y < size; ++y) {
+ memset(pixels, color, rectWidth);
+ pixels += _width;
+ }
+ for (int16 y = 0; y < sidesHeight; ++y) {
+ for (int16 x = 0; x < size; ++x) {
+ *pixels++ = color;
+ }
+ pixels += centerWidth;
+ for (int16 x = 0; x < size; ++x) {
+ *pixels++ = color;
+ }
+ pixels += stride;
+ }
+ for (int16 y = 0; y < size; ++y) {
+ memset(pixels, color, rectWidth);
+ pixels += _width;
+ }
}
-void GfxText32::drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId) {
- int16 backColor = (int16)readSelectorValue(_segMan, textObject, SELECTOR(back));
- // Sanity check: Check if the hunk is set. If not, either the game scripts
- // didn't set it, or an old saved game has been loaded, where it wasn't set.
- if (hunkId.isNull())
- return;
+void GfxText32::drawChar(const char charIndex) {
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
- // Negative coordinates indicate that text shouldn't be displayed
- if (x < 0 || y < 0)
- return;
+ _font->drawToBuffer(charIndex, _drawPosition.y, _drawPosition.x, _foreColor, _dimmed, pixels, _width, _height);
+ _drawPosition.x += _font->getCharWidth(charIndex);
+}
- byte *memoryPtr = _segMan->getHunkPointer(hunkId);
+uint16 GfxText32::getCharWidth(const char charIndex, const bool doScaling) const {
+ uint16 width = _font->getCharWidth(charIndex);
+ if (doScaling) {
+ width = scaleUpWidth(width);
+ }
+ return width;
+}
- if (!memoryPtr) {
- // Happens when restoring in some SCI32 games (e.g. SQ6).
- // Commented out to reduce console spam
- //warning("Attempt to draw an invalid text bitmap");
+void GfxText32::drawTextBox() {
+ if (_text.size() == 0) {
return;
}
- byte *surface = memoryPtr + BITMAP_HEADER_SIZE;
+ const char *text = _text.c_str();
+ const char *sourceText = text;
+ int16 textRectWidth = _textRect.width();
+ _drawPosition.y = _textRect.top;
+ uint charIndex = 0;
+ if (getLongest(&charIndex, textRectWidth) == 0) {
+ error("DrawTextBox GetLongest=0");
+ }
+
+ charIndex = 0;
+ uint nextCharIndex = 0;
+ while (*text != '\0') {
+ _drawPosition.x = _textRect.left;
+
+ uint length = getLongest(&nextCharIndex, textRectWidth);
+ int16 textWidth = getTextWidth(charIndex, length);
+
+ if (_alignment == kTextAlignCenter) {
+ _drawPosition.x += (textRectWidth - textWidth) / 2;
+ } else if (_alignment == kTextAlignRight) {
+ _drawPosition.x += textRectWidth - textWidth;
+ }
+
+ drawText(charIndex, length);
+ charIndex = nextCharIndex;
+ text = sourceText + charIndex;
+ _drawPosition.y += _font->getHeight();
+ }
+}
+
+void GfxText32::drawTextBox(const Common::String &text) {
+ _text = text;
+ drawTextBox();
+}
+
+void GfxText32::drawText(const uint index, uint length) {
+ assert(index + length <= _text.size());
+
+ // NOTE: This draw loop implementation is somewhat different than the
+ // implementation in the actual engine, but should be accurate. Primarily
+ // the changes revolve around eliminating some extra temporaries and
+ // fixing the logic to match.
+ const char *text = _text.c_str() + index;
+ while (length-- > 0) {
+ char currentChar = *text++;
+
+ if (currentChar == '|') {
+ const char controlChar = *text++;
+ --length;
+
+ if (length == 0) {
+ return;
+ }
+
+ if (controlChar == 'a' || controlChar == 'c' || controlChar == 'f') {
+ uint16 value = 0;
+
+ while (length > 0) {
+ const char valueChar = *text;
+ if (valueChar < '0' || valueChar > '9') {
+ break;
+ }
+
+ ++text;
+ --length;
+ value = 10 * value + (valueChar - '0');
+ }
+
+ if (length == 0) {
+ return;
+ }
+
+ if (controlChar == 'a') {
+ _alignment = (TextAlign)value;
+ } else if (controlChar == 'c') {
+ _foreColor = value;
+ } else if (controlChar == 'f') {
+ setFont(value);
+ }
+ }
+
+ while (length > 0 && *text != '|') {
+ ++text;
+ --length;
+ }
+ } else {
+ drawChar(currentChar);
+ }
+ }
+}
+
+void GfxText32::invertRect(const reg_t bitmap, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) {
+ Common::Rect targetRect = rect;
+ if (doScaling) {
+ bitmapStride = bitmapStride * _scaledWidth / g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ targetRect = scaleRect(rect);
+ }
+
+ byte *bitmapData = _segMan->getHunkPointer(bitmap);
- int curByte = 0;
- int16 skipColor = (int16)readSelectorValue(_segMan, textObject, SELECTOR(skip));
- uint16 textX = planeRect.left + x;
- uint16 textY = planeRect.top + y;
- // Get totalWidth, totalHeight
- uint16 width = READ_LE_UINT16(memoryPtr);
- uint16 height = READ_LE_UINT16(memoryPtr + 2);
+ // NOTE: SCI code is super weird here; it seems to be trying to look at the
+ // entire size of the bitmap including the header, instead of just the pixel
+ // data size. We just look at the pixel size. This function generally is an
+ // odd duck since the stride dimension for a bitmap is built in to the bitmap
+ // header, so perhaps it was once an unheadered bitmap format and this
+ // function was never updated to match? Or maybe they exploit the
+ // configurable stride length somewhere else to do stair stepping inverts...
+ uint32 invertSize = targetRect.height() * bitmapStride + targetRect.width();
+ uint32 bitmapSize = READ_SCI11ENDIAN_UINT32(bitmapData + 12);
- // Upscale the coordinates/width if the fonts are already upscaled
- if (_screen->fontIsUpscaled()) {
- textX = textX * _screen->getDisplayWidth() / _screen->getWidth();
- textY = textY * _screen->getDisplayHeight() / _screen->getHeight();
+ if (invertSize >= bitmapSize) {
+ error("InvertRect too big: %u >= %u", invertSize, bitmapSize);
}
- bool translucent = (skipColor == -1 && backColor == -1);
+ // NOTE: Actual engine just added the bitmap header size hardcoded here
+ byte *pixel = bitmapData + READ_SCI11ENDIAN_UINT32(bitmapData + 28) + bitmapStride * targetRect.top + targetRect.left;
- for (int curY = 0; curY < height; curY++) {
- for (int curX = 0; curX < width; curX++) {
- byte pixel = surface[curByte++];
- if ((!translucent && pixel != skipColor && pixel != backColor) ||
- (translucent && pixel != 0xFF))
- _screen->putFontPixel(textY, curX + textX, curY, pixel);
+ int16 stride = bitmapStride - targetRect.width();
+ int16 targetHeight = targetRect.height();
+ int16 targetWidth = targetRect.width();
+
+ for (int16 y = 0; y < targetHeight; ++y) {
+ for (int16 x = 0; x < targetWidth; ++x) {
+ if (*pixel == foreColor) {
+ *pixel = backColor;
+ } else if (*pixel == backColor) {
+ *pixel = foreColor;
+ }
+
+ ++pixel;
}
+
+ pixel += stride;
}
}
-int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) {
- uint16 curChar = 0;
- int16 maxChars = 0, curCharCount = 0;
- uint16 width = 0;
-
- while (width <= maxWidth) {
- curChar = (*(const byte *)text++);
-
- switch (curChar) {
- // 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)
- // 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++;
- // it's meant to pass through here
- case 0xA:
- curCharCount++;
- // and it's also meant to pass through here
- case 0:
- return curCharCount;
- case ' ':
- maxChars = curCharCount; // return count up to (but not including) breaking space
- break;
+uint GfxText32::getLongest(uint *charIndex, const int16 width) {
+ assert(width > 0);
+
+ uint testLength = 0;
+ uint length = 0;
+
+ const uint initialCharIndex = *charIndex;
+
+ // The index of the next word after the last word break
+ uint lastWordBreakIndex = *charIndex;
+
+ const char *text = _text.c_str() + *charIndex;
+
+ char currentChar;
+ while ((currentChar = *text++) != '\0') {
+ // NOTE: In the original engine, the font, color, and alignment were
+ // reset here to their initial values
+
+ // The text to render contains a line break; stop at the line break
+ if (currentChar == '\r' || currentChar == '\n') {
+ // Skip the rest of the line break if it is a Windows-style
+ // \r\n or non-standard \n\r
+ // NOTE: In the original engine, the `text` pointer had not been
+ // advanced yet so the indexes used to access characters were
+ // one higher
+ if (
+ (currentChar == '\r' && text[0] == '\n') ||
+ (currentChar == '\n' && text[0] == '\r' && text[1] != '\n')
+ ) {
+ ++*charIndex;
+ }
+
+ // We are at the end of a line but the last word in the line made
+ // it too wide to fit in the text area; return up to the previous
+ // word
+ if (length && getTextWidth(initialCharIndex, testLength) > width) {
+ *charIndex = lastWordBreakIndex;
+ return length;
+ }
+
+ // Skip the line break and return all text seen up to now
+ // NOTE: In original engine, the font, color, and alignment were
+ // reset, then getTextWidth was called to use its side-effects to
+ // set font, color, and alignment according to the text from
+ // `initialCharIndex` to `testLength`
+ ++*charIndex;
+ return testLength;
+ } else if (currentChar == ' ') {
+ // The last word in the line made it too wide to fit in the text area;
+ // return up to the previous word, then collapse the whitespace
+ // between that word and its next sibling word into the line break
+ if (getTextWidth(initialCharIndex, testLength) > width) {
+ *charIndex = lastWordBreakIndex;
+ const char *nextChar = _text.c_str() + lastWordBreakIndex;
+ while (*nextChar++ == ' ') {
+ ++*charIndex;
+ }
+
+ // NOTE: In original engine, the font, color, and alignment were
+ // set here to the values that were seen at the last space character
+ return length;
+ }
+
+ // NOTE: In the original engine, the values of _fontId, _foreColor,
+ // and _alignment were stored for use in the return path mentioned
+ // just above here
+
+ // We found a word break that was within the text area, memorise it
+ // and continue processing. +1 on the character index because it has
+ // not been incremented yet so currently points to the word break
+ // and not the word after the break
+ length = testLength;
+ lastWordBreakIndex = *charIndex + 1;
+ }
+
+ // In the middle of a line, keep processing
+ ++*charIndex;
+ ++testLength;
+
+ // NOTE: In the original engine, the font, color, and alignment were
+ // reset here to their initial values
+
+ // The text to render contained no word breaks yet but is already too
+ // wide for the text area; just split the word in half at the point
+ // where it overflows
+ if (length == 0 && getTextWidth(initialCharIndex, testLength) > width) {
+ *charIndex = --testLength + lastWordBreakIndex;
+ return testLength;
}
- if (width + font->getCharWidth(curChar) > maxWidth)
- break;
- width += font->getCharWidth(curChar);
- curCharCount++;
}
- return maxChars;
+ // The complete text to render was a single word, or was narrower than
+ // the text area, so return the entire line
+ if (length == 0 || getTextWidth(initialCharIndex, testLength) <= width) {
+ // NOTE: In original engine, the font, color, and alignment were
+ // reset, then getTextWidth was called to use its side-effects to
+ // set font, color, and alignment according to the text from
+ // `initialCharIndex` to `testLength`
+ return testLength;
+ }
+
+ // The last word in the line made it wider than the text area, so return
+ // up to the penultimate word
+ *charIndex = lastWordBreakIndex;
+ return length;
}
-void GfxText32::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
- Common::Rect rect(0, 0, 0, 0);
- Size(rect, text, font, maxWidth);
- *textWidth = rect.width();
- *textHeight = rect.height();
+int16 GfxText32::getTextWidth(const uint index, uint length) const {
+ int16 width = 0;
+
+ const char *text = _text.c_str() + index;
+
+ GfxFont *font = _font;
+
+ char currentChar = *text++;
+ while (length > 0 && currentChar != '\0') {
+ // Control codes are in the format `|<code><value>|`
+ if (currentChar == '|') {
+ // NOTE: Original engine code changed the global state of the
+ // FontMgr here upon encountering any color, alignment, or
+ // font control code.
+ // To avoid requiring all callers to manually restore these
+ // values on every call, we ignore control codes other than
+ // font change (since alignment and color do not change the
+ // width of characters), and simply update the font pointer
+ // on stack instead of the member property font.
+ currentChar = *text++;
+ --length;
+
+ if (length > 0 && currentChar == 'f') {
+ GuiResourceId fontId = 0;
+ do {
+ currentChar = *text++;
+ --length;
+
+ fontId = fontId * 10 + currentChar - '0';
+ } while (length > 0 && currentChar >= '0' && currentChar <= '9');
+
+ if (length > 0) {
+ font = _cache->getFont(fontId);
+ }
+ }
+
+ // Forward through any more unknown control character data
+ while (length > 0 && currentChar != '|') {
+ ++text;
+ --length;
+ }
+ } else {
+ width += font->getCharWidth(currentChar);
+ }
+
+ currentChar = *text++;
+ --length;
+ }
+
+ return width;
}
-void GfxText32::StringWidth(const char *str, GuiResourceId fontId, int16 &textWidth, int16 &textHeight) {
- Width(str, 0, (int16)strlen(str), fontId, textWidth, textHeight, true);
+int16 GfxText32::getTextWidth(const Common::String &text, const uint index, const uint length) {
+ _text = text;
+ return scaleUpWidth(getTextWidth(index, length));
}
-void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fontId, int16 &textWidth, int16 &textHeight, bool restoreFont) {
- byte curChar;
- textWidth = 0; textHeight = 0;
-
- GfxFont *font = _cache->getFont(fontId);
-
- if (font) {
- text += from;
- while (len--) {
- curChar = (*(const byte *)text++);
- switch (curChar) {
- case 0x0A:
- case 0x0D:
- textHeight = MAX<int16> (textHeight, font->getHeight());
- break;
- case 0x7C:
- warning("Code processing isn't implemented in SCI32");
- break;
- default:
- textHeight = MAX<int16> (textHeight, font->getHeight());
- textWidth += font->getCharWidth(curChar);
- break;
+Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth, bool doScaling) {
+ // NOTE: Like most of the text rendering code, this function was pretty
+ // weird in the original engine. The initial result rectangle was actually
+ // a 1x1 rectangle (0, 0, 0, 0), which was then "fixed" after the main
+ // text size loop finished running by subtracting 1 from the right and
+ // bottom edges. Like other functions in SCI32, this has been converted
+ // to use exclusive rects with inclusive rounding.
+
+ Common::Rect result;
+
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ maxWidth = maxWidth * _scaledWidth / scriptWidth;
+
+ _text = text;
+
+ if (maxWidth >= 0) {
+ if (maxWidth == 0) {
+ // TODO: This was hardcoded to 192, but guessing
+ // that it was originally 60% of the scriptWidth
+ // before the compiler took over.
+ // Verify this by looking at a game that uses a
+ // scriptWidth other than 320, like LSL7
+ maxWidth = _scaledWidth * (scriptWidth * 0.6) / scriptWidth;
+ }
+
+ result.right = maxWidth;
+
+ int16 textWidth = 0;
+ if (_text.size() > 0) {
+ const char *rawText = _text.c_str();
+ const char *sourceText = rawText;
+ uint charIndex = 0;
+ uint nextCharIndex = 0;
+ while (*rawText != '\0') {
+ uint length = getLongest(&nextCharIndex, result.width());
+ textWidth = MAX(textWidth, getTextWidth(charIndex, length));
+ charIndex = nextCharIndex;
+ rawText = sourceText + charIndex;
+ // TODO: Due to getLongest and getTextWidth not having side
+ // effects, it is possible that the currently loaded font's
+ // height is wrong for this line if it was changed inline
+ result.bottom += _font->getHeight();
}
}
+
+ if (textWidth < maxWidth) {
+ result.right = textWidth;
+ }
+ } else {
+ result.right = getTextWidth(0, 10000);
+ // NOTE: In the original engine code, the bottom was not decremented
+ // by 1, which means that the rect was actually a pixel taller than
+ // the height of the font. This was not the case in the other branch,
+ // which decremented the bottom by 1 at the end of the loop.
+ result.bottom = _font->getHeight() + 1;
}
+
+ if (doScaling) {
+ // NOTE: The original engine code also scaled top/left but these are
+ // always zero so there is no reason to do that.
+ result.right = ((result.right - 1) * scriptWidth + _scaledWidth - 1) / _scaledWidth + 1;
+ result.bottom = ((result.bottom - 1) * scriptHeight + _scaledHeight - 1) / _scaledHeight + 1;
+ }
+
+ return result;
}
-int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth) {
- int16 charCount;
- int16 maxTextWidth = 0, textWidth;
- int16 totalHeight = 0, textHeight;
+void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {
+ Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;
- // Adjust maxWidth if we're using an upscaled font
- if (_screen->fontIsUpscaled())
- maxWidth = maxWidth * _screen->getDisplayWidth() / _screen->getWidth();
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
- rect.top = rect.left = 0;
- GfxFont *font = _cache->getFont(fontId);
+ // NOTE: There is an extra optimisation within the SCI code to
+ // do a single memset if the scaledRect is the same size as
+ // the bitmap, not implemented here.
+ Buffer buffer(_width, _height, pixels);
+ buffer.fillRect(targetRect, _backColor);
+}
- if (maxWidth < 0) { // force output as single line
- StringWidth(text, fontId, textWidth, textHeight);
- rect.bottom = textHeight;
- rect.right = textWidth;
- } else {
- // 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, font);
- if (charCount == 0)
- break;
- Width(curPos, 0, charCount, fontId, textWidth, textHeight, false);
- maxTextWidth = MAX(textWidth, maxTextWidth);
- totalHeight += textHeight;
- curPos += charCount;
- while (*curPos == ' ')
- curPos++; // skip over breaking spaces
- }
- rect.bottom = totalHeight;
- rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth);
+int16 GfxText32::getStringWidth(const Common::String &text) {
+ return getTextWidth(text, 0, 10000);
+}
+
+int16 GfxText32::getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling) {
+ const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ Common::Rect scaledRect(textRect);
+ if (doScaling) {
+ mulinc(scaledRect, Ratio(_scaledWidth, scriptWidth), Ratio(_scaledHeight, scriptHeight));
}
- // Adjust the width/height if we're using an upscaled font
- // for the scripts
- if (_screen->fontIsUpscaled()) {
- rect.right = rect.right * _screen->getWidth() / _screen->getDisplayWidth();
- rect.bottom = rect.bottom * _screen->getHeight() / _screen->getDisplayHeight();
+ Common::String oldText = _text;
+ _text = text;
+
+ uint charIndex = index;
+ int16 maxWidth = scaledRect.width();
+ int16 lineCount = (scaledRect.height() - 2) / _font->getHeight();
+ while (lineCount--) {
+ getLongest(&charIndex, maxWidth);
}
- return rect.right;
+ _text = oldText;
+ return charIndex - index;
}
+int16 GfxText32::getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling) {
+ setFont(fontId);
+ return getTextCount(text, index, textRect, doScaling);
+}
+
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index 7ba7df50e4..5768ea0c59 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -23,34 +23,455 @@
#ifndef SCI_GRAPHICS_TEXT32_H
#define SCI_GRAPHICS_TEXT32_H
+#include "sci/graphics/celobj32.h"
+#include "sci/graphics/frameout.h"
+
namespace Sci {
+enum TextAlign {
+ kTextAlignLeft = 0,
+ kTextAlignCenter = 1,
+ kTextAlignRight = 2
+};
+
+enum BitmapFlags {
+ kBitmapRemap = 2
+};
+
+#define BITMAP_PROPERTY(size, property, offset)\
+inline uint##size get##property() const {\
+ return READ_SCI11ENDIAN_UINT##size(_bitmap + (offset));\
+}\
+inline void set##property(uint##size value) {\
+ WRITE_SCI11ENDIAN_UINT##size(_bitmap + (offset), (value));\
+}
+
/**
- * Text32 class, handles text calculation and displaying of text for SCI2, SCI21 and SCI3 games
+ * A convenience class for creating and modifying in-memory
+ * bitmaps.
*/
-class GfxText32 {
+class BitmapResource {
+ byte *_bitmap;
+ reg_t _object;
+
+ /**
+ * Gets the size of the bitmap header for the current
+ * engine version.
+ */
+ static inline uint16 getBitmapHeaderSize() {
+ // TODO: These values are accurate for each engine, but there may be no reason
+ // to not simply just always use size 40, since SCI2.1mid does not seem to
+ // actually store any data above byte 40, and SCI2 did not allow bitmaps with
+ // scaling resolutions other than the default (320x200). Perhaps SCI3 used
+ // the extra bytes, or there is some reason why they tried to align the header
+ // size with other headers like pic headers?
+// uint32 bitmapHeaderSize;
+// if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
+// bitmapHeaderSize = 46;
+// } else if (getSciVersion() == SCI_VERSION_2_1_EARLY) {
+// bitmapHeaderSize = 40;
+// } else {
+// bitmapHeaderSize = 36;
+// }
+// return bitmapHeaderSize;
+ return 46;
+ }
+
+ /**
+ * Gets the byte size of a bitmap with the given width
+ * and height.
+ */
+ static inline uint32 getBitmapSize(const uint16 width, const uint16 height) {
+ return width * height + getBitmapHeaderSize();
+ }
+
public:
- GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen);
- ~GfxText32();
- reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG);
- reg_t createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG);
- void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject);
- void drawScrollTextBitmap(reg_t textObject, reg_t hunkId, uint16 x, uint16 y);
- void disposeTextBitmap(reg_t hunkId);
- int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font);
+ /**
+ * Create a bitmap resource for an existing bitmap.
+ * Ownership of the bitmap is retained by the caller.
+ */
+ inline BitmapResource(reg_t bitmap) :
+ _bitmap(g_sci->getEngineState()->_segMan->getHunkPointer(bitmap)),
+ _object(bitmap) {
+ if (_bitmap == nullptr || getUncompressedDataOffset() != getBitmapHeaderSize()) {
+ error("Invalid Text bitmap %04x:%04x", PRINT_REG(bitmap));
+ }
+ }
- void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+ /**
+ * Allocates and initialises a new bitmap in the given
+ * segment manager.
+ */
+ inline BitmapResource(SegManager *segMan, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 hunkPaletteOffset, const bool remap) {
-private:
- reg_t createTextBitmapInternal(Common::String &text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t hunkId);
- void drawTextBitmapInternal(int16 x, int16 y, Common::Rect planeRect, reg_t textObject, reg_t hunkId);
- int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth);
- 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);
+ _object = segMan->allocateHunkEntry("Bitmap()", getBitmapSize(width, height));
+ _bitmap = segMan->getHunkPointer(_object);
+
+ const uint16 bitmapHeaderSize = getBitmapHeaderSize();
+
+ setWidth(width);
+ setHeight(height);
+ setDisplace(Common::Point(displaceX, displaceY));
+ setSkipColor(skipColor);
+ _bitmap[9] = 0;
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 10, 0);
+ setRemap(remap);
+ setDataSize(width * height);
+ WRITE_SCI11ENDIAN_UINT32(_bitmap + 16, 0);
+ setHunkPaletteOffset(hunkPaletteOffset);
+ setDataOffset(bitmapHeaderSize);
+ setUncompressedDataOffset(bitmapHeaderSize);
+ setControlOffset(0);
+ setScaledWidth(scaledWidth);
+ setScaledHeight(scaledHeight);
+ }
+
+ reg_t getObject() const {
+ return _object;
+ }
+
+ BITMAP_PROPERTY(16, Width, 0);
+ BITMAP_PROPERTY(16, Height, 2);
+
+ inline Common::Point getDisplace() const {
+ return Common::Point(
+ (int16)READ_SCI11ENDIAN_UINT16(_bitmap + 4),
+ (int16)READ_SCI11ENDIAN_UINT16(_bitmap + 6)
+ );
+ }
+
+ inline void setDisplace(const Common::Point &displace) {
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 4, (uint16)displace.x);
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 6, (uint16)displace.y);
+ }
+
+ inline uint8 getSkipColor() const {
+ return _bitmap[8];
+ }
+
+ inline void setSkipColor(const uint8 skipColor) {
+ _bitmap[8] = skipColor;
+ }
+
+ inline bool getRemap() const {
+ return READ_SCI11ENDIAN_UINT16(_bitmap + 10) & kBitmapRemap;
+ }
+
+ inline void setRemap(const bool remap) {
+ uint16 flags = READ_SCI11ENDIAN_UINT16(_bitmap + 10);
+ if (remap) {
+ flags |= kBitmapRemap;
+ } else {
+ flags &= ~kBitmapRemap;
+ }
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 10, flags);
+ }
+ BITMAP_PROPERTY(32, DataSize, 12);
+
+ inline uint32 getHunkPaletteOffset() const {
+ return READ_SCI11ENDIAN_UINT32(_bitmap + 20);
+ }
+
+ void setHunkPaletteOffset(uint32 hunkPaletteOffset) {
+ if (hunkPaletteOffset) {
+ hunkPaletteOffset += getBitmapHeaderSize();
+ }
+
+ WRITE_SCI11ENDIAN_UINT32(_bitmap + 20, hunkPaletteOffset);
+ }
+
+ BITMAP_PROPERTY(32, DataOffset, 24);
+
+ // NOTE: This property is used as a "magic number" for
+ // validating that a block of memory is a valid bitmap,
+ // and so is always set to the size of the header.
+ BITMAP_PROPERTY(32, UncompressedDataOffset, 28);
+
+ // NOTE: This property always seems to be zero
+ BITMAP_PROPERTY(32, ControlOffset, 32);
+
+ inline uint16 getScaledWidth() const {
+ if (getDataOffset() >= 40) {
+ return READ_SCI11ENDIAN_UINT16(_bitmap + 36);
+ }
+
+ // SCI2 bitmaps did not have scaling ability
+ return 320;
+ }
+
+ inline void setScaledWidth(uint16 scaledWidth) {
+ if (getDataOffset() >= 40) {
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 36, scaledWidth);
+ }
+ }
+
+ inline uint16 getScaledHeight() const {
+ if (getDataOffset() >= 40) {
+ return READ_SCI11ENDIAN_UINT16(_bitmap + 38);
+ }
+
+ // SCI2 bitmaps did not have scaling ability
+ return 200;
+ }
+
+ inline void setScaledHeight(uint16 scaledHeight) {
+ if (getDataOffset() >= 40) {
+ WRITE_SCI11ENDIAN_UINT16(_bitmap + 38, scaledHeight);
+ }
+ }
+
+ inline byte *getPixels() {
+ return _bitmap + getUncompressedDataOffset();
+ }
+};
+
+class GfxFont;
+
+/**
+ * This class handles text calculation and rendering for
+ * SCI32 games. The text calculation system in SCI32 is
+ * nearly the same as SCI16, which means this class behaves
+ * similarly. Notably, GfxText32 maintains drawing
+ * parameters across multiple calls.
+ */
+class GfxText32 {
+private:
SegManager *_segMan;
GfxCache *_cache;
- GfxScreen *_screen;
+
+ /**
+ * The resource ID of the default font used by the game.
+ *
+ * @todo Check all SCI32 games to learn what their
+ * default font is.
+ */
+ static int16 _defaultFontId;
+
+ /**
+ * The width and height of the currently active text
+ * bitmap, in text-system coordinates.
+ *
+ * @note These are unsigned in the actual engine.
+ */
+ int16 _width, _height;
+
+ /**
+ * The color used to draw text.
+ */
+ uint8 _foreColor;
+
+ /**
+ * The background color of the text box.
+ */
+ uint8 _backColor;
+
+ /**
+ * The transparent color of the text box. Used when
+ * compositing the bitmap onto the screen.
+ */
+ uint8 _skipColor;
+
+ /**
+ * The rect where the text is drawn within the bitmap.
+ * This rect is clipped to the dimensions of the bitmap.
+ */
+ Common::Rect _textRect;
+
+ /**
+ * The text being drawn to the currently active text
+ * bitmap.
+ */
+ Common::String _text;
+
+ /**
+ * The font being used to draw the text.
+ */
+ GuiResourceId _fontId;
+
+ /**
+ * The color of the text box border.
+ */
+ int16 _borderColor;
+
+ /**
+ * TODO: Document
+ */
+ bool _dimmed;
+
+ /**
+ * The text alignment for the drawn text.
+ */
+ TextAlign _alignment;
+
+ int16 _field_20;
+
+ /**
+ * TODO: Document
+ */
+ int16 _field_22;
+
+ int _field_2C, _field_30, _field_34, _field_38;
+
+ int16 _field_3C;
+
+ /**
+ * The position of the text draw cursor.
+ */
+ Common::Point _drawPosition;
+
+ void drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling);
+
+ void drawChar(const char charIndex);
+ void drawText(const uint index, uint length);
+
+ /**
+ * Gets the length of the longest run of text available
+ * within the currently loaded text, starting from the
+ * given `charIndex` and running for up to `maxWidth`
+ * pixels. Returns the number of characters that can be
+ * written, and mutates the value pointed to by
+ * `charIndex` to point to the index of the next
+ * character to render.
+ */
+ uint getLongest(uint *charIndex, const int16 maxWidth);
+
+ /**
+ * Gets the pixel width of a substring of the currently
+ * loaded text, without scaling.
+ */
+ int16 getTextWidth(const uint index, uint length) const;
+
+ inline Common::Rect scaleRect(const Common::Rect &rect) {
+ Common::Rect scaledRect(rect);
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ Ratio scaleX(_scaledWidth, scriptWidth);
+ Ratio scaleY(_scaledHeight, scriptHeight);
+ mulinc(scaledRect, scaleX, scaleY);
+ return scaledRect;
+ }
+
+public:
+ GfxText32(SegManager *segMan, GfxCache *fonts);
+
+ /**
+ * The memory handle of the currently active bitmap.
+ */
+ reg_t _bitmap;
+
+ /**
+ * The size of the x-dimension of the coordinate system
+ * used by the text renderer.
+ */
+ int16 _scaledWidth;
+
+ /**
+ * The size of the y-dimension of the coordinate system
+ * used by the text renderer.
+ */
+ int16 _scaledHeight;
+
+ /**
+ * The currently active font resource used to write text
+ * into the bitmap.
+ *
+ * @note SCI engine builds the font table directly
+ * inside of FontMgr; we use GfxFont instead.
+ */
+ GfxFont *_font;
+
+ /**
+ * Creates a plain font bitmap with a flat color
+ * background.
+ */
+ reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling);
+
+ /**
+ * Creates a font bitmap with a view background.
+ */
+ reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed);
+
+ /**
+ * Creates a font bitmap with a title.
+ */
+ reg_t createTitledBitmap(const int16 width, const int16 height, const Common::Rect &textRect, const Common::String &text, const int16 foreColor, const int16 backColor, const int16 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, Common::String &title, const int16 titleForeColor, const int16 titleBackColor, const GuiResourceId titleFontId, const bool doScaling);
+
+ inline int scaleUpWidth(int value) const {
+ const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ return (value * scriptWidth + _scaledWidth - 1) / _scaledWidth;
+ }
+
+ inline int scaleUpHeight(int value) const {
+ const int scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ return (value * scriptHeight + _scaledHeight - 1) / _scaledHeight;
+ }
+
+ /**
+ * Draws the text to the bitmap.
+ */
+ void drawTextBox();
+
+ /**
+ * Draws the given text to the bitmap.
+ *
+ * @note The original engine holds a reference to a
+ * shared string which lets the text be updated from
+ * outside of the font manager. Instead, we give this
+ * extra signature to send the text to draw.
+ *
+ * TODO: Use shared string instead?
+ */
+ void drawTextBox(const Common::String &text);
+
+ /**
+ * Erases the given rect by filling with the background
+ * color.
+ */
+ void erase(const Common::Rect &rect, const bool doScaling);
+
+ void invertRect(const reg_t bitmap, const int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling);
+
+ /**
+ * Sets the font to be used for rendering and
+ * calculation of text dimensions.
+ */
+ void setFont(const GuiResourceId fontId);
+
+ /**
+ * Gets the width of a character.
+ */
+ uint16 getCharWidth(const char charIndex, const bool doScaling) const;
+
+ /**
+ * Retrieves the width and height of a block of text.
+ */
+ Common::Rect getTextSize(const Common::String &text, const int16 maxWidth, bool doScaling);
+
+ /**
+ * Gets the pixel width of a substring of the currently
+ * loaded text, with scaling.
+ */
+ int16 getTextWidth(const Common::String &text, const uint index, const uint length);
+
+ /**
+ * Retrieves the width of a line of text.
+ */
+ int16 getStringWidth(const Common::String &text);
+
+ /**
+ * Gets the number of characters of `text`, starting
+ * from `index`, that can be safely rendered into
+ * `textRect`.
+ */
+ int16 getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling);
+
+ /**
+ * Gets the number of characters of `text`, starting
+ * from `index`, that can be safely rendered into
+ * `textRect` using the given font.
+ */
+ int16 getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling);
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index 2ee18b5c9a..1939e66179 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -25,6 +25,7 @@
#include "sci/engine/state.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
@@ -833,19 +834,6 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left);
- // WORKAROUND: EcoQuest French and German draw the fish and anemone sprites
- // with priority 15 in scene 440. Afterwards, a dialog is shown on top of
- // these sprites with priority 15 as well. This is undefined behavior
- // actually, as the sprites and dialog share the same priority, so in our
- // implementation the sprites get drawn incorrectly on top of the dialog.
- // Perhaps this worked by mistake in SSCI because of subtle differences in
- // how sprites are drawn. We compensate for this by resetting the priority
- // of all sprites that have a priority of 15 in scene 440 to priority 14,
- // so that the speech bubble can be drawn correctly on top of them. Fixes
- // bug #3040625.
- if (g_sci->getGameId() == GID_ECOQUEST && g_sci->getEngineState()->currentRoomNumber() == 440 && priority == 15)
- priority = 14;
-
if (!_EGAmapping) {
for (y = 0; y < height; y++, bitmap += celWidth) {
for (x = 0; x < width; x++) {
@@ -855,12 +843,11 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const
const int y2 = clipRectTranslated.top + y;
if (!upscaledHires) {
if (priority >= _screen->getPriority(x2, y2)) {
- if (!_palette->isRemapped(palette->mapping[color])) {
- _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
- } else {
- byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2));
- _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0);
- }
+ byte outputColor = palette->mapping[color];
+ // SCI16 remapping (QFG4 demo)
+ if (g_sci->_gfxRemap16 && g_sci->_gfxRemap16->isRemapped(outputColor))
+ outputColor = g_sci->_gfxRemap16->remapColor(outputColor, _screen->getVisual(x2, y2));
+ _screen->putPixel(x2, y2, drawMask, outputColor, priority, 0);
}
} else {
// UpscaledHires means view is hires and is supposed to
@@ -970,12 +957,11 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect,
const int x2 = clipRectTranslated.left + x;
const int y2 = clipRectTranslated.top + y;
if (color != clearKey && priority >= _screen->getPriority(x2, y2)) {
- if (!_palette->isRemapped(palette->mapping[color])) {
- _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
- } else {
- byte remappedColor = _palette->remapColor(palette->mapping[color], _screen->getVisual(x2, y2));
- _screen->putPixel(x2, y2, drawMask, remappedColor, priority, 0);
- }
+ byte outputColor = palette->mapping[color];
+ // SCI16 remapping (QFG4 demo)
+ if (g_sci->_gfxRemap16 && g_sci->_gfxRemap16->isRemapped(outputColor))
+ outputColor = g_sci->_gfxRemap16->remapColor(outputColor, _screen->getVisual(x2, y2));
+ _screen->putPixel(x2, y2, drawMask, outputColor, priority, 0);
}
}
}
@@ -989,13 +975,4 @@ void GfxView::adjustBackUpscaledCoordinates(int16 &y, int16 &x) {
_screen->adjustBackUpscaledCoordinates(y, x, _sci2ScaleRes);
}
-byte GfxView::getColorAtCoordinate(int16 loopNo, int16 celNo, int16 x, int16 y) {
- const CelInfo *celInfo = getCelInfo(loopNo, celNo);
- const byte *bitmap = getBitmap(loopNo, celNo);
- const int16 celWidth = celInfo->width;
-
- bitmap += (celWidth * y);
- return bitmap[x];
-}
-
} // End of namespace Sci
diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h
index d8803db208..91590208c1 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -85,8 +85,6 @@ public:
void adjustToUpscaledCoordinates(int16 &y, int16 &x);
void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
- byte getColorAtCoordinate(int16 loopNo, int16 celNo, int16 x, int16 y);
-
private:
void initData(GuiResourceId resourceId);
void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount);
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 08e5ea84d8..a02147e4d0 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -57,6 +57,7 @@ MODULE_OBJS := \
graphics/picture.o \
graphics/portrait.o \
graphics/ports.o \
+ graphics/remap.o \
graphics/screen.o \
graphics/text16.o \
graphics/transitions.o \
@@ -81,10 +82,13 @@ MODULE_OBJS := \
ifdef ENABLE_SCI32
MODULE_OBJS += \
engine/kgraphics32.o \
+ graphics/celobj32.o \
graphics/controls32.o \
graphics/frameout.o \
graphics/paint32.o \
+ graphics/plane32.o \
graphics/palette32.o \
+ graphics/screen_item32.o \
graphics/text32.o \
video/robot_decoder.o
endif
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 828a57abeb..a09ba8f3ce 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -121,7 +121,7 @@ bool Vocabulary::loadParserWords() {
}
}
- unsigned int seeker;
+ uint32 seeker;
if (resourceType == kVocabularySCI1)
seeker = 255 * 2; // vocab.900 starts with 255 16-bit pointers which we don't use
else
@@ -202,7 +202,7 @@ bool Vocabulary::loadSuffixes() {
if (!resource)
return false; // No vocabulary found
- unsigned int seeker = 1;
+ uint32 seeker = 1;
while ((seeker < resource->size - 1) && (resource->data[seeker + 1] != 0xff)) {
suffix_t suffix;
@@ -288,7 +288,7 @@ bool Vocabulary::loadAltInputs() {
AltInput t;
t._input = data;
- unsigned int l = strlen(data);
+ uint32 l = strlen(data);
t._inputLength = l;
data += l + 1;
@@ -325,15 +325,15 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) {
return false;
bool ret = false;
- unsigned int loopCount = 0;
+ uint32 loopCount = 0;
bool changed;
do {
changed = false;
const char* t = text.c_str();
- unsigned int tlen = text.size();
+ uint32 tlen = text.size();
- for (unsigned int p = 0; p < tlen && !changed; ++p) {
+ for (uint32 p = 0; p < tlen && !changed; ++p) {
unsigned char s = t[p];
if (s >= _altInputs.size() || _altInputs[s].empty())
continue;
@@ -351,7 +351,7 @@ bool Vocabulary::checkAltInput(Common::String& text, uint16& cursorPos) {
cursorPos = p + strlen(i->_replacement);
}
- for (unsigned int j = 0; j < i->_inputLength; ++j)
+ for (uint32 j = 0; j < i->_inputLength; ++j)
text.deleteChar(p);
const char *r = i->_replacement;
while (*r)
diff --git a/engines/sci/parser/vocabulary.h b/engines/sci/parser/vocabulary.h
index f4adee6e55..59558ce18a 100644
--- a/engines/sci/parser/vocabulary.h
+++ b/engines/sci/parser/vocabulary.h
@@ -156,7 +156,7 @@ typedef Common::Array<synonym_t> SynonymList;
struct AltInput {
const char *_input;
const char *_replacement;
- unsigned int _inputLength;
+ uint32 _inputLength;
bool _prefix;
};
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 54ef4b3363..6a5af1a6d6 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -307,7 +307,7 @@ bool Resource::loadPatch(Common::SeekableReadStream *file) {
error("Can't allocate %d bytes needed for loading %s", res->size + res->_headerSize, res->_id.toString().c_str());
}
- unsigned int really_read;
+ uint32 really_read;
if (res->_headerSize > 0) {
really_read = file->read(res->_header, res->_headerSize);
if (really_read != res->_headerSize)
@@ -565,12 +565,11 @@ Resource *ResourceManager::testResource(ResourceId id) {
}
int ResourceManager::addAppropriateSources() {
- Common::ArchiveMemberList files;
-
if (Common::File::exists("resource.map")) {
// SCI0-SCI2 file naming scheme
ResourceSource *map = addExternalMap("resource.map");
+ Common::ArchiveMemberList files;
SearchMan.listMatchingMembers(files, "resource.0??");
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
@@ -587,20 +586,20 @@ int ResourceManager::addAppropriateSources() {
#endif
} else if (Common::MacResManager::exists("Data1")) {
// Mac SCI1.1+ file naming scheme
- SearchMan.listMatchingMembers(files, "Data?*");
+ Common::StringArray files;
+ Common::MacResManager::listFiles(files, "Data?");
- for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
- Common::String filename = (*x)->getName();
- addSource(new MacResourceForkResourceSource(filename, atoi(filename.c_str() + 4)));
+ for (Common::StringArray::const_iterator x = files.begin(); x != files.end(); ++x) {
+ addSource(new MacResourceForkResourceSource(*x, atoi(x->c_str() + 4)));
}
#ifdef ENABLE_SCI32
// There can also be a "Patches" resource fork with patches
- if (Common::File::exists("Patches"))
+ if (Common::MacResManager::exists("Patches"))
addSource(new MacResourceForkResourceSource("Patches", 100));
} else {
// SCI2.1-SCI3 file naming scheme
- Common::ArchiveMemberList mapFiles;
+ Common::ArchiveMemberList mapFiles, files;
SearchMan.listMatchingMembers(mapFiles, "resmap.0??");
SearchMan.listMatchingMembers(files, "ressci.0??");
@@ -865,6 +864,7 @@ ResourceManager::ResourceManager() {
}
void ResourceManager::init() {
+ _maxMemoryLRU = 256 * 1024; // 256KiB
_memoryLocked = 0;
_memoryLRU = 0;
_LRU.clear();
@@ -918,6 +918,14 @@ void ResourceManager::init() {
debugC(1, kDebugLevelResMan, "resMan: Detected %s", getSciVersionDesc(getSciVersion()));
+ // Resources in SCI32 games are significantly larger than SCI16
+ // games and can cause immediate exhaustion of the LRU resource
+ // cache, leading to constant decompression of picture resources
+ // and making the renderer very slow.
+ if (getSciVersion() >= SCI_VERSION_2) {
+ _maxMemoryLRU = 2048 * 1024; // 2MiB
+ }
+
switch (_viewType) {
case kViewEga:
debugC(1, kDebugLevelResMan, "resMan: Detected EGA graphic resources");
@@ -935,35 +943,14 @@ void ResourceManager::init() {
debugC(1, kDebugLevelResMan, "resMan: Detected SCI1.1 VGA graphic resources");
break;
default:
-#ifdef ENABLE_SCI32
- error("resMan: Couldn't determine view type");
-#else
- if (getSciVersion() >= SCI_VERSION_2) {
- // SCI support isn't built in, thus the view type won't be determined for
- // SCI2+ games. This will be handled further up, so throw no error here
- } else {
- error("resMan: Couldn't determine view type");
- }
-#endif
+ // Throw a warning, but do not error out here, because this is called from the
+ // fallback detector, and the user could be pointing to a folder with a non-SCI
+ // game, but with SCI-like file names (e.g. Pinball Creep)
+ warning("resMan: Couldn't determine view type");
+ break;
}
}
-void ResourceManager::initForDetection() {
- assert(!g_sci);
-
- _memoryLocked = 0;
- _memoryLRU = 0;
- _LRU.clear();
- _resMap.clear();
- _audioMapSCI1 = NULL;
-
- _mapVersion = detectMapVersion();
- _volVersion = detectVolVersion();
-
- scanNewSources();
- detectSciVersion();
-}
-
ResourceManager::~ResourceManager() {
// freeing resources
ResourceMap::iterator itr = _resMap.begin();
@@ -998,9 +985,9 @@ void ResourceManager::addToLRU(Resource *res) {
_LRU.push_front(res);
_memoryLRU += res->size;
#if SCI_VERBOSE_RESMAN
- debug("Adding %s.%03d (%d bytes) to lru control: %d bytes total",
- getResourceTypeName(res->type), res->number, res->size,
- mgr->_memoryLRU);
+ debug("Adding %s (%d bytes) to lru control: %d bytes total",
+ res->_id.toString().c_str(), res->size,
+ _memoryLRU);
#endif
res->_status = kResStatusEnqueued;
}
@@ -1023,13 +1010,13 @@ void ResourceManager::printLRU() {
}
void ResourceManager::freeOldResources() {
- while (MAX_MEMORY < _memoryLRU) {
+ while (_maxMemoryLRU < _memoryLRU) {
assert(!_LRU.empty());
Resource *goner = *_LRU.reverse_begin();
removeFromLRU(goner);
goner->unalloc();
#ifdef SCI_VERBOSE_RESMAN
- debug("resMan-debug: LRU: Freeing %s.%03d (%d bytes)", getResourceTypeName(goner->type), goner->number, goner->size);
+ debug("resMan-debug: LRU: Freeing %s (%d bytes)", goner->_id.toString().c_str(), goner->size);
#endif
}
}
@@ -2474,7 +2461,9 @@ bool ResourceManager::hasOldScriptHeader() {
Resource *res = findResource(ResourceId(kResourceTypeScript, 0), 0);
if (!res) {
- error("resMan: Failed to find script.000");
+ // Script 0 missing -> corrupted / non-SCI resource files.
+ // Don't error out here, because this might have been called
+ // from the fallback detector
return false;
}
@@ -2679,7 +2668,9 @@ Common::String ResourceManager::findSierraGameId() {
return "";
// Seek to the name selector of the first export
- byte *seeker = heap->data + READ_UINT16(heap->data + gameObjectOffset + nameSelector * 2);
+ byte *offsetPtr = heap->data + gameObjectOffset + nameSelector * 2;
+ uint16 offset = !isSci11Mac() ? READ_LE_UINT16(offsetPtr) : READ_BE_UINT16(offsetPtr);
+ byte *seeker = heap->data + offset;
Common::String sierraId;
sierraId += (const char *)seeker;
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index eb5b508254..ef474d97c2 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -315,11 +315,6 @@ public:
void init();
/**
- * Similar to the function above, only called from the fallback detector
- */
- void initForDetection();
-
- /**
* Adds all of the resource files for a game
*/
int addAppropriateSources();
@@ -426,9 +421,7 @@ protected:
// Note: maxMemory will not be interpreted as a hard limit, only as a restriction
// for resources which are not explicitly locked. However, a warning will be
// issued whenever this limit is exceeded.
- enum {
- MAX_MEMORY = 256 * 1024 // 256KB
- };
+ int _maxMemoryLRU;
ViewType _viewType; // Used to determine if the game has EGA or VGA graphics
Common::List<ResourceSource *> _sources;
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 6869e6379e..5717a09121 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -139,7 +139,7 @@ bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) {
error("Can't allocate %d bytes needed for loading %s", size, _id.toString().c_str());
}
- unsigned int really_read = file->read(data, size);
+ uint32 really_read = file->read(data, size);
if (really_read != size)
warning("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size);
@@ -688,6 +688,12 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
channel->data = resource->data + dataOffset;
channel->size = READ_LE_UINT16(data + 4);
+
+ if (dataOffset + channel->size > resource->size) {
+ warning("Invalid size inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr);
+ channel->size = resource->size - dataOffset;
+ }
+
channel->curPos = 0;
channel->number = *channel->data;
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 1232b6559b..e14d12b918 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -58,6 +58,7 @@
#include "sci/graphics/picture.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/remap.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/text16.h"
#include "sci/graphics/transitions.h"
@@ -163,6 +164,7 @@ SciEngine::~SciEngine() {
delete _gfxText32;
delete _robotDecoder;
delete _gfxFrameout;
+ delete _gfxRemap32;
#endif
delete _gfxMenu;
delete _gfxControls16;
@@ -175,6 +177,7 @@ SciEngine::~SciEngine() {
delete _gfxPorts;
delete _gfxCache;
delete _gfxPalette16;
+ delete _gfxRemap16;
delete _gfxCursor;
delete _gfxScreen;
@@ -238,13 +241,7 @@ Common::Error SciEngine::run() {
// Only DOS+Windows
switch (_gameId) {
case GID_KQ6:
- if (isCD())
- _forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics");
- break;
case GID_GK1:
- if ((isCD()) && (!isDemo()))
- _forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics");
- break;
case GID_PQ4:
if (isCD())
_forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics");
@@ -316,6 +313,7 @@ Common::Error SciEngine::run() {
if (directSaveSlotLoading >= 0) {
_gamestate->_delayedRestoreGame = true;
_gamestate->_delayedRestoreGameId = directSaveSlotLoading;
+ _gamestate->_delayedRestoreFromLauncher = true;
// Jones only initializes its menus when restarting/restoring, thus set
// the gameIsRestarting flag here before initializing. Fixes bug #6536.
@@ -529,7 +527,7 @@ void SciEngine::patchGameSaveRestore() {
byte kernelIdSave = 0;
switch (_gameId) {
- case GID_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all
+ case GID_HOYLE1: // gets confused, although the game doesn't support saving/restoring at all
case GID_HOYLE2: // gets confused, see hoyle1
case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required
case GID_MOTHERGOOSE: // mother goose EGA saves/restores directly and has no save/restore dialogs
@@ -576,17 +574,29 @@ void SciEngine::patchGameSaveRestore() {
}
}
+ const Object *patchObjectSave = nullptr;
+
+ if (getSciVersion() < SCI_VERSION_2) {
+ // Patch gameobject ::save for now for SCI0 - SCI1.1
+ // TODO: It seems this was never adjusted to superclass, but adjusting it now may cause
+ // issues with some game. Needs to get checked and then possibly changed.
+ patchObjectSave = gameObject;
+ } else {
+ // Patch superclass ::save for SCI32
+ patchObjectSave = gameSuperObject;
+ }
+
// Search for gameobject ::save, if there is one patch that one too
- uint16 gameObjectMethodCount = gameObject->getMethodCount();
- for (uint16 methodNr = 0; methodNr < gameObjectMethodCount; methodNr++) {
- uint16 selectorId = gameObject->getFuncSelector(methodNr);
+ uint16 patchObjectMethodCount = patchObjectSave->getMethodCount();
+ for (uint16 methodNr = 0; methodNr < patchObjectMethodCount; methodNr++) {
+ uint16 selectorId = patchObjectSave->getFuncSelector(methodNr);
Common::String methodName = _kernel->getSelectorName(selectorId);
if (methodName == "save") {
if (_gameId != GID_FAIRYTALES) { // Fairy Tales saves automatically without a dialog
if (kernelIdSave != kernelIdRestore)
- patchGameSaveRestoreCode(segMan, gameObject->getFunction(methodNr), kernelIdSave);
+ patchGameSaveRestoreCode(segMan, patchObjectSave->getFunction(methodNr), kernelIdSave);
else
- patchGameSaveRestoreCodeSci21(segMan, gameObject->getFunction(methodNr), kernelIdSave, false);
+ patchGameSaveRestoreCodeSci21(segMan, patchObjectSave->getFunction(methodNr), kernelIdSave, false);
}
break;
}
@@ -653,6 +663,7 @@ void SciEngine::initGraphics() {
_gfxPaint = 0;
_gfxPaint16 = 0;
_gfxPalette16 = 0;
+ _gfxRemap16 = 0;
_gfxPorts = 0;
_gfxText16 = 0;
_gfxTransitions = 0;
@@ -663,6 +674,7 @@ void SciEngine::initGraphics() {
_gfxFrameout = 0;
_gfxPaint32 = 0;
_gfxPalette32 = 0;
+ _gfxRemap32 = 0;
#endif
if (hasMacIconBar())
@@ -672,9 +684,12 @@ void SciEngine::initGraphics() {
if (getSciVersion() >= SCI_VERSION_2) {
_gfxPalette32 = new GfxPalette32(_resMan, _gfxScreen);
_gfxPalette16 = _gfxPalette32;
+ _gfxRemap32 = new GfxRemap32(_gfxPalette32);
} else {
#endif
_gfxPalette16 = new GfxPalette(_resMan, _gfxScreen);
+ if (getGameId() == GID_QFG4DEMO)
+ _gfxRemap16 = new GfxRemap(_gfxPalette16);
#ifdef ENABLE_SCI32
}
#endif
@@ -690,10 +705,11 @@ void SciEngine::initGraphics() {
_gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
_gfxPaint32 = new GfxPaint32(_resMan, _gfxCoordAdjuster, _gfxScreen, _gfxPalette32);
_gfxPaint = _gfxPaint32;
- _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen);
- _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
_robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);
_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette32, _gfxPaint32);
+ _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache);
+ _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
+ _gfxFrameout->run();
} else {
#endif
// SCI0-SCI1.1 graphic objects creation
@@ -704,7 +720,7 @@ void SciEngine::initGraphics() {
_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette16);
_gfxPaint16 = new GfxPaint16(_resMan, _gamestate->_segMan, _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette16, _gfxTransitions, _audio);
_gfxPaint = _gfxPaint16;
- _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions);
+ _gfxAnimate = new GfxAnimate(_gamestate, _scriptPatcher, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette16, _gfxCursor, _gfxTransitions);
_gfxText16 = new GfxText16(_gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen);
_gfxControls16 = new GfxControls16(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
_gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
@@ -820,7 +836,7 @@ Console *SciEngine::getSciDebugger() {
}
const char *SciEngine::getGameIdStr() const {
- return _gameDescription->gameid;
+ return _gameDescription->gameId;
}
Common::Language SciEngine::getLanguage() const {
@@ -897,12 +913,30 @@ int SciEngine::inQfGImportRoom() const {
void SciEngine::setLauncherLanguage() {
if (_gameDescription->flags & ADGF_ADDENGLISH) {
// If game is multilingual
- if (Common::parseLanguage(ConfMan.get("language")) == Common::EN_ANY) {
+ Common::Language chosenLanguage = Common::parseLanguage(ConfMan.get("language"));
+ uint16 languageToSet = 0;
+
+ switch (chosenLanguage) {
+ case Common::EN_ANY:
// and English was selected as language
- if (SELECTOR(printLang) != -1) // set text language to English
- writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(printLang), K_LANG_ENGLISH);
- if (SELECTOR(parseLang) != -1) // and set parser language to English as well
- writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(parseLang), K_LANG_ENGLISH);
+ languageToSet = K_LANG_ENGLISH;
+ break;
+ case Common::JA_JPN: {
+ // Set Japanese for FM-Towns games
+ // KQ5 on FM-Towns has no initial language set
+ if (g_sci->getPlatform() == Common::kPlatformFMTowns) {
+ languageToSet = K_LANG_JAPANESE;
+ }
+ }
+ default:
+ break;
+ }
+
+ if (languageToSet) {
+ if (SELECTOR(printLang) != -1) // set text language
+ writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(printLang), languageToSet);
+ if (SELECTOR(parseLang) != -1) // and set parser language as well
+ writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(parseLang), languageToSet);
}
}
}
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 5c86d92355..7df3d38163 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -71,6 +71,8 @@ class GfxPaint16;
class GfxPaint32;
class GfxPalette;
class GfxPalette32;
+class GfxRemap;
+class GfxRemap32;
class GfxPorts;
class GfxScreen;
class GfxText16;
@@ -128,6 +130,7 @@ enum SciGameId {
GID_FAIRYTALES,
GID_FREDDYPHARKAS,
GID_FUNSEEKER,
+ GID_GK1DEMO, // We have a separate ID for GK1 demo, because it's actually a completely different game (SCI1.1 vs SCI2/SCI2.1)
GID_GK1,
GID_GK2,
GID_HOYLE1,
@@ -165,12 +168,14 @@ enum SciGameId {
GID_PQ2,
GID_PQ3,
GID_PQ4,
+ GID_PQ4DEMO, // We have a separate ID for PQ4 demo, because it's actually a completely different game (SCI1.1 vs SCI2/SCI2.1)
GID_PQSWAT,
GID_QFG1,
GID_QFG1VGA,
GID_QFG2,
GID_QFG3,
GID_QFG4,
+ GID_QFG4DEMO, // We have a separate ID for QFG4 demo, because it's actually a completely different game (SCI1.1 vs SCI2/SCI2.1)
GID_RAMA,
GID_SHIVERS,
//GID_SHIVERS2, // Not SCI
@@ -201,8 +206,8 @@ enum SciVersion {
SCI_VERSION_1_LATE, // Dr. Brain 1, EcoQuest 1, Longbow, PQ3, SQ1, LSL5, KQ5 CD
SCI_VERSION_1_1, // Dr. Brain 2, EcoQuest 1 CD, EcoQuest 2, KQ6, QFG3, SQ4CD, XMAS 1992 and many more
SCI_VERSION_2, // GK1, PQ4 floppy, QFG4 floppy
- SCI_VERSION_2_1_EARLY, // GK2 demo, KQ7, LSL6 hires, PQ4, QFG4 floppy
- SCI_VERSION_2_1_MIDDLE, // GK2, KQ7, MUMG Deluxe, Phantasmagoria 1, PQ4CD, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
+ SCI_VERSION_2_1_EARLY, // GK2 demo, KQ7 1.4/1.51, LSL6 hires, PQ4CD, QFG4 floppy
+ SCI_VERSION_2_1_MIDDLE, // GK2, KQ7 2.00b, MUMG Deluxe, Phantasmagoria 1, PQ:SWAT, QFG4CD, Shivers 1, SQ6, Torin
SCI_VERSION_2_1_LATE, // demos of LSL7, Lighthouse, RAMA
SCI_VERSION_3 // LSL7, Lighthouse, RAMA, Phantasmagoria 2
};
@@ -282,7 +287,7 @@ public:
inline EngineState *getEngineState() const { return _gamestate; }
inline Vocabulary *getVocabulary() const { return _vocabulary; }
inline EventManager *getEventManager() const { return _eventMan; }
- inline reg_t getGameObject() const { return _gameObjectAddress; }
+ inline reg_t getGameObject() const { return _gameObjectAddress; } // Gets the game object VM address
Common::RandomSource &getRNG() { return _rng; }
@@ -349,6 +354,8 @@ public:
GfxMenu *_gfxMenu; // Menu for 16-bit gfx
GfxPalette *_gfxPalette16;
GfxPalette32 *_gfxPalette32; // Palette for 32-bit gfx
+ GfxRemap *_gfxRemap16; // Remapping for the QFG4 demo
+ GfxRemap32 *_gfxRemap32; // Remapping for 32-bit gfx
GfxPaint *_gfxPaint;
GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx
GfxPaint32 *_gfxPaint32; // Painting in 32-bit gfx
diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp
index 5ce49086ca..0f93b19e7c 100644
--- a/engines/sci/sound/drivers/amigamac.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -497,7 +497,7 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
}
instrument->samples = (int8 *) malloc(size + 1);
- if (file.read(instrument->samples, size) < (unsigned int)size) {
+ if (file.read(instrument->samples, size) < (uint32)size) {
warning("Amiga/Mac driver: failed to read instrument samples");
free(instrument->samples);
delete instrument;
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index ee5903fda2..e7b25eb1fc 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -44,7 +44,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM
// resource number, but it's totally unrelated to the menu music).
// The GK1 demo (very late SCI1.1) does the same thing
// TODO: Check the QFG4 demo
- _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || ConfMan.getBool("prefer_digitalsfx"));
+ _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1DEMO || ConfMan.getBool("prefer_digitalsfx"));
_music = new SciMusic(_soundVersion, _useDigitalSFX);
_music->init();
diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp
index c72d3beb19..ccec41a1ab 100644
--- a/engines/sci/util.cpp
+++ b/engines/sci/util.cpp
@@ -69,4 +69,13 @@ void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) {
WRITE_LE_UINT16(ptr, val);
}
+#ifdef ENABLE_SCI32
+void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val) {
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
+ WRITE_BE_UINT32(ptr, val);
+ else
+ WRITE_LE_UINT32(ptr, val);
+}
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/util.h b/engines/sci/util.h
index 378030939c..b0fee5151e 100644
--- a/engines/sci/util.h
+++ b/engines/sci/util.h
@@ -37,6 +37,9 @@ void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val);
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr);
uint32 READ_SCI11ENDIAN_UINT32(const void *ptr);
void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val);
+#ifdef ENABLE_SCI32
+void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val);
+#endif
// Wrappers for reading integer values in resources that are
// LE in SCI1.1 Mac, but BE in SCI32 Mac
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 0d7ea39ec2..3a69b5f03c 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -861,7 +861,7 @@ L2C36:;
stopActorMoving();
return;
}
- // 2C98: Yes, an exact copy of what just occured.. the original does this, so im doing it...
+ // 2C98: Yes, an exact copy of what just occurred.. the original does this, so im doing it...
// Just to keep me sane when going over it :)
if (A == 0xFF) {
setActorFromTmp();
diff --git a/engines/scumm/charset-fontdata.cpp b/engines/scumm/charset-fontdata.cpp
index 23e89b1878..a1e92a9950 100644
--- a/engines/scumm/charset-fontdata.cpp
+++ b/engines/scumm/charset-fontdata.cpp
@@ -591,35 +591,40 @@ CharsetRendererV2::CharsetRendererV2(ScummEngine *vm, Common::Language language)
_fontHeight = 8;
_curId = 0;
- const byte *replacementData = NULL;
+ const byte *replacementMap = NULL, *replacementData = NULL;
int replacementChars = 0;
switch (language) {
case Common::DE_DEU:
if (_vm->_game.version == 0) {
- replacementData = germanCharsetDataV0;
+ replacementMap = germanCharsetDataV0;
replacementChars = sizeof(germanCharsetDataV0) / 2;
} else {
- replacementData = germanCharsetDataV2;
+ replacementMap = germanCharsetDataV2;
replacementChars = sizeof(germanCharsetDataV2) / 2;
}
+ replacementData = specialCharsetData;
break;
case Common::FR_FRA:
- replacementData = frenchCharsetDataV2;
+ replacementMap = frenchCharsetDataV2;
replacementChars = sizeof(frenchCharsetDataV2) / 2;
+ replacementData = specialCharsetData;
break;
case Common::IT_ITA:
- replacementData = italianCharsetDataV2;
+ replacementMap = italianCharsetDataV2;
replacementChars = sizeof(italianCharsetDataV2) / 2;
+ replacementData = specialCharsetData;
break;
case Common::ES_ESP:
- replacementData = spanishCharsetDataV2;
+ replacementMap = spanishCharsetDataV2;
replacementChars = sizeof(spanishCharsetDataV2) / 2;
+ replacementData = specialCharsetData;
break;
case Common::RU_RUS:
if (((_vm->_game.id == GID_MANIAC) || (_vm->_game.id == GID_ZAK)) && (_vm->_game.version == 2)) {
- replacementData = russCharsetDataV2;
+ replacementMap = russCharsetDataV2;
replacementChars = sizeof(russCharsetDataV2) / 2;
+ replacementData = russianCharsetDataV2;
} else {
_fontPtr = russianCharsetDataV2;
}
@@ -629,20 +634,16 @@ CharsetRendererV2::CharsetRendererV2(ScummEngine *vm, Common::Language language)
break;
}
- if (replacementData) {
+ if (replacementMap && replacementData) {
_fontPtr = new byte[sizeof(englishCharsetDataV2)];
_deleteFontPtr = true;
memcpy(const_cast<byte *>(_fontPtr), englishCharsetDataV2, sizeof(englishCharsetDataV2));
for (int i = 0; i < replacementChars; i++) {
- int ch1 = replacementData[2 * i];
- int ch2 = replacementData[2 * i + 1];
+ int ch1 = replacementMap[2 * i];
+ int ch2 = replacementMap[2 * i + 1];
- if (((_vm->_game.id == GID_MANIAC) || (_vm->_game.id == GID_ZAK)) && (_vm->_game.version == 2)) {
- memcpy(const_cast<byte *>(_fontPtr) + 8 * ch1, russianCharsetDataV2 + 8 * ch2, 8);
- } else {
- memcpy(const_cast<byte *>(_fontPtr) + 8 * ch1, specialCharsetData + 8 * ch2, 8);
- }
+ memcpy(const_cast<byte *>(_fontPtr) + 8 * ch1, replacementData + 8 * ch2, 8);
}
} else
_deleteFontPtr = false;
diff --git a/engines/scumm/configure.engine b/engines/scumm/configure.engine
index e1de788061..e8962a371e 100644
--- a/engines/scumm/configure.engine
+++ b/engines/scumm/configure.engine
@@ -2,4 +2,4 @@
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
add_engine scumm "SCUMM" yes "scumm_7_8 he" "v0-v6 games"
add_engine scumm_7_8 "v7 & v8 games" yes
-add_engine he "HE71+ games" yes
+add_engine he "HE71+ games" yes "" "" "highres"
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index e5bbad15e6..9264a6443b 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -1271,7 +1271,6 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
pattern += ".s##";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -1288,6 +1287,8 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index a78aff96f8..b806a9f3cc 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -636,7 +636,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
if (heFlags & 1) {
_heChannel[heChannel].timer = 0;
} else {
- _heChannel[heChannel].timer = size * 1000 / rate;
+ _heChannel[heChannel].timer = size * 1000 / (rate * blockAlign);
}
_mixer->stopHandle(_heSoundChannels[heChannel]);
@@ -658,7 +658,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
_heChannel[heChannel].rate = rate;
if (_heChannel[heChannel].timer)
- _heChannel[heChannel].timer = size * 1000 / rate;
+ _heChannel[heChannel].timer = size * 1000 / (rate * blockAlign);
// makeADPCMStream returns a stream in native endianness, but RawMemoryStream
// defaults to big endian. If we're on a little endian system, set the LE flag.
diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp
index b7abdd074e..28ad64670c 100644
--- a/engines/scumm/imuse_digi/dimuse_track.cpp
+++ b/engines/scumm/imuse_digi/dimuse_track.cpp
@@ -352,9 +352,9 @@ Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDelay) {
// leaving bug number for now #1635361
ImuseDigiSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
if (!soundDesc) {
- // it fail load open old song after switch to diffrent CDs
+ // it fail load open old song after switch to different CDs
// so gave up
- error("Game not supported while playing on 2 diffrent CDs");
+ error("Game not supported while playing on 2 different CDs");
}
track->soundDesc = soundDesc;
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 4d4be2c3c2..55bbeeef98 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -50,7 +50,7 @@ Player_AD::Player_AD(ScummEngine *scumm)
writeReg(0x01, 0x20);
_engineMusicTimer = 0;
- _soundPlaying = -1;
+ _musicResource = -1;
_curOffset = 0;
@@ -104,8 +104,8 @@ void Player_AD::startSound(int sound) {
stopMusic();
// Lock the new music resource
- _soundPlaying = sound;
- _vm->_res->lock(rtSound, _soundPlaying);
+ _musicResource = sound;
+ _vm->_res->lock(rtSound, _musicResource);
// Start the new music resource
_musicData = res;
@@ -150,7 +150,7 @@ void Player_AD::startSound(int sound) {
void Player_AD::stopSound(int sound) {
Common::StackLock lock(_mutex);
- if (sound == _soundPlaying) {
+ if (sound == _musicResource) {
stopMusic();
} else {
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
@@ -178,7 +178,17 @@ int Player_AD::getMusicTimer() {
}
int Player_AD::getSoundStatus(int sound) const {
- return (sound == _soundPlaying);
+ if (sound == _musicResource) {
+ return true;
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == sound) {
+ return true;
+ }
+ }
+
+ return false;
}
void Player_AD::saveLoadWithSerializer(Serializer *ser) {
@@ -193,7 +203,7 @@ void Player_AD::saveLoadWithSerializer(Serializer *ser) {
if (ser->getVersion() >= VER(96)) {
int32 res[4] = {
- _soundPlaying, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource
+ _musicResource, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource
};
// The first thing we save is a list of sound resources being played
@@ -461,13 +471,13 @@ void Player_AD::startMusic() {
}
void Player_AD::stopMusic() {
- if (_soundPlaying == -1) {
+ if (_musicResource == -1) {
return;
}
// Unlock the music resource if present
- _vm->_res->unlock(rtSound, _soundPlaying);
- _soundPlaying = -1;
+ _vm->_res->unlock(rtSound, _musicResource);
+ _musicResource = -1;
// Stop the music playback
_curOffset = 0;
@@ -510,7 +520,7 @@ void Player_AD::updateMusic() {
// important to note that we need to parse a command directly
// at the new position, i.e. there is no time value we need to
// parse.
- if (_soundPlaying == -1) {
+ if (_musicResource == -1) {
return;
} else {
continue;
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 63fda3cc7c..9cd1a06261 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -68,7 +68,7 @@ private:
OPL::OPL *_opl2;
- int _soundPlaying;
+ int _musicResource;
int32 _engineMusicTimer;
struct SfxSlot;
diff --git a/engines/scumm/players/player_v4a.cpp b/engines/scumm/players/player_v4a.cpp
index bd8ce3f7ad..58f53a6d7f 100644
--- a/engines/scumm/players/player_v4a.cpp
+++ b/engines/scumm/players/player_v4a.cpp
@@ -174,7 +174,7 @@ int Player_V4A::getMusicTimer() {
return 2000;
if (_musicId) {
// The titlesong (and a few others) is running with ~70 ticks per second and the scale seems to be based on that.
- // The Game itself doesnt get the timing from the Tfmx Player however, so we just use the elapsed time
+ // The Game itself doesn't get the timing from the Tfmx Player however, so we just use the elapsed time
// 357 ~ 1000 * 25 * (1 / 70)
return _mixer->getSoundElapsedTime(_musicHandle) / 357;
}
@@ -183,7 +183,7 @@ int Player_V4A::getMusicTimer() {
int Player_V4A::getSoundStatus(int nr) const {
// For music the game queues a variable the Tfmx Player sets through a special command.
- // For sfx there seems to be no way to queue them, and the game doesnt try to.
+ // For sfx there seems to be no way to queue them, and the game doesn't try to.
return (nr == _musicId) ? _signal : 0;
}
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index e5673c1803..f3df24ff51 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1303,7 +1303,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
if (hasTownsData) {
// Skip FM-Towns specific data
- for (int i = 69 * sizeof(uint8) + 44 * sizeof(int16); i; i--)
+ for (i = 69 * sizeof(uint8) + 44 * sizeof(int16); i; i--)
s->loadByte();
}
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 24d676a1ff..89d2d3dc72 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2611,8 +2611,12 @@ bool ScummEngine::startManiac() {
Common::String path = dom.getVal("path");
if (path.hasPrefix(currentPath)) {
- path.erase(0, currentPath.size() + 1);
- if (path.equalsIgnoreCase("maniac")) {
+ path.erase(0, currentPath.size());
+ // Do a case-insensitive non-path-mode match of the remainder.
+ // While strictly speaking it's too broad, this matchString
+ // ignores the presence or absence of trailing path separators
+ // in either currentPath or path.
+ if (path.matchString("*maniac*", true, false)) {
maniacTarget = iter->_key;
break;
}
diff --git a/engines/scumm/scumm_v4.h b/engines/scumm/scumm_v4.h
index 28f619ceaa..a008023ff9 100644
--- a/engines/scumm/scumm_v4.h
+++ b/engines/scumm/scumm_v4.h
@@ -35,7 +35,7 @@ class ScummEngine_v4 : public ScummEngine_v5 {
public:
/**
- * Prepared savegame used by the orginal save/load dialog.
+ * Prepared savegame used by the original save/load dialog.
* Must be valid as long as the savescreen is active. As we are not
* notified when the savescreen is closed, memory is only freed on a game
* reset, at the destruction of the engine or when the original save/load
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 84d2b37f96..4d70ee8482 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -240,7 +240,7 @@ void Sound::playSound(int soundID) {
// mentioned in the bug report above; in case it is, I put a check here.
assert(soundID == 39);
- // The samplerate is copied from the sound resouce 39 of the PC CD/VGA
+ // The samplerate is copied from the sound resource 39 of the PC CD/VGA
// version of Monkey Island.
// Read info from the header
diff --git a/engines/sherlock/POTFILES b/engines/sherlock/POTFILES
new file mode 100644
index 0000000000..b9f1c1249f
--- /dev/null
+++ b/engines/sherlock/POTFILES
@@ -0,0 +1,3 @@
+engines/sherlock/detection.cpp
+engines/sherlock/scalpel/scalpel.cpp
+engines/sherlock/tattoo/widget_files.cpp
diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index 681e71d0f6..4442c1da85 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -23,6 +23,8 @@
#include "sherlock/animation.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+
#include "common/algorithm.h"
namespace Sherlock {
@@ -89,7 +91,7 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
// since we don't want the offsets in the image file to be used, just the explicit position we specify
- screen.transBlitFrom(images[imageFrame]._frame, pt);
+ screen.SHtransBlitFrom(images[imageFrame]._frame, pt);
} else {
// At this point, either the sprites for the frame has been complete, or there weren't any sprites
// at all to draw for the frame
@@ -201,7 +203,7 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
// since we don't want the offsets in the image file to be used, just the explicit position we specify
- screen._backBuffer1.transBlitFrom(images[imageFrame]._frame, pt);
+ screen._backBuffer1.SHtransBlitFrom(images[imageFrame]._frame, pt);
if (!fadeActive)
screen.slamArea(pt.x, pt.y, images[imageFrame]._frame.w, images[imageFrame]._frame.h);
} else {
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 4b0b7dfb3f..6cfee5d822 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -143,7 +143,7 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
// Form a single surface containing both frames
Surface s(r.width(), r.height());
- s.fill(TRANSPARENCY);
+ s.clear(TRANSPARENCY);
// Draw the passed image
Common::Point drawPos;
@@ -151,11 +151,11 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
drawPos.x = -cursorPt.x;
if (cursorPt.y < 0)
drawPos.y = -cursorPt.y;
- s.blitFrom(surface, Common::Point(drawPos.x, drawPos.y));
+ s.SHblitFrom(surface, Common::Point(drawPos.x, drawPos.y));
// Draw the cursor image
drawPos = Common::Point(MAX(cursorPt.x, (int16)0), MAX(cursorPt.y, (int16)0));
- s.transBlitFrom(cursorImg, Common::Point(drawPos.x, drawPos.y));
+ s.SHtransBlitFrom(cursorImg, Common::Point(drawPos.x, drawPos.y));
// Set up hotspot position for cursor, adjusting for cursor image's position within the surface
Common::Point hotspot;
@@ -163,7 +163,7 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
hotspot = Common::Point(8, 8);
hotspot += drawPos;
// Set the cursor
- setCursor(s.getRawSurface(), hotspot.x, hotspot.y);
+ setCursor(s, hotspot.x, hotspot.y);
}
void Events::animateCursorIfNeeded() {
diff --git a/engines/sherlock/fixed_text.cpp b/engines/sherlock/fixed_text.cpp
index cbee944120..4679fe58b8 100644
--- a/engines/sherlock/fixed_text.cpp
+++ b/engines/sherlock/fixed_text.cpp
@@ -27,6 +27,183 @@
namespace Sherlock {
+static const char *const fixedJournalTextEN[] = {
+ // Holmes asked/said...
+ "Holmes asked me, ",
+ "Holmes asked the Inspector, ",
+ "Holmes asked %s, ",
+ "Holmes said to me, ",
+ "Holmes said to the Inspector, ",
+ "Holmes said to %s, ",
+ // I asked/said...
+ "I replied, ",
+ "The reply was, ",
+ // Holmes/I/The Inspector/Person asked/said (without "Then" prefix)
+ "Holmes asked, ",
+ "Holmes said, ",
+ "I asked, ",
+ "I said, ",
+ "The Inspector asked, ",
+ "The Inspector said, ",
+ "%s asked, ",
+ "%s said, ",
+ // Then Holmes/I/The Inspector/Person asked/said
+ "Then Holmes asked, ",
+ "Then Holmes said, ",
+ "Then I asked, ",
+ "Then I said, ",
+ "Then the Inspector asked, ",
+ "Then the Inspector said, ",
+ "Then %s asked, ",
+ "Then %s said, "
+};
+
+static const char *const fixedJournalTextDE[] = {
+ // Holmes asked/said...
+ "Holmes fragte mich, ",
+ "Holmes fragte Inspektor Lestrade, ",
+ "Holmes fragte %s, ",
+ "Holmes sagte mir, ",
+ "Holmes sagte Inspektor Lestrade, ",
+ "Holmes sagte %s, ",
+ // I asked/said...
+ "Ich antwortete, ",
+ "Die Antwort lautete, ",
+ // Holmes/I/The Inspector/Person asked/said (without "Then" prefix)
+ "Holmes fragte, ", // original: "fragte Holmes"
+ "Holmes sagte, ", // original: "sagte Holmes"
+ "Ich fragte, ", // original: "fragte Ich"
+ "Ich sagte, ", // original: "sagte Ich"
+ "Der Inspektor fragte, ",
+ "Der Inspektor sagte, ",
+ "%s fragte, ",
+ "%s sagte, ",
+ // Then Holmes/I/The Inspector/Person asked/said
+ "Dann fragte Holmes, ",
+ "Dann sagte Holmes, ",
+ "Dann fragte ich, ", // original: "Dann sagte Ich"
+ "Dann sagte ich, ", // original: "Dann sagte Ich"
+ "Dann fragte der Inspektor, ",
+ "Dann sagte der Inspektor, ",
+ "Dann fragte %s, ",
+ "Dann sagte %s, "
+};
+
+// Only used for Sherlock Holmes 2, so special characters should use the SH2 charset
+// small a w/ accent grave: 0x85 / octal 205
+// small e w/ accent acute: 0x82 / octal 202
+// small e w/ accent grave: 0x8A / octal 212
+// small e w/ circonflexe: 0x88 / octal 210
+// small cedilla: 0x87 / octal 207
+static const char *const fixedJournalTextFR[] = {
+ // Holmes asked/said...
+ "Holmes me demanda, ", // original: "Holmes m'a demand\202, "
+ "Holmes demanda \205 l'inspecteur, ", // original: "Holmes a demand\202 \205 l'inspecteur, "
+ "Holmes demanda \205 %s, ", // original: "Holmes a demand\202 \205 %s, "
+ "Holmes me dit, ", // original: "Holmes m'a dit, "
+ "Holmes dit \205 l'inspecteur, ", // original: "Holmes a dit \205 l'inspecteur, "
+ "Holmes dit \205 %s, ", // original: "Holmes a dit \205 %s, "
+ // I asked/said...
+ "Je r\202pondis, ", // original: "J'ai r\202pondu, ",
+ "La r\202ponse fut, ",
+ // Holmes/I/The Inspector/Person asked/said (without "Then" prefix)
+ "Holmes demanda, ", // original: "Holmes a demand\202, "
+ "Holmes dit, ",
+ "Je demandai, ", // original: "J'ai demand\202, "
+ "Je dis, ", // original: "J'ai dit, "
+ "L'inspecteur demanda, ", // original: ""L'inspecteur a demand\202, "
+ "L'inspecteur dit, ",
+ "%s demanda, ", // original: "%s a demand\202, "
+ "%s dit, ",
+ // Then Holmes/I/The Inspector/Person asked/said
+ "Alors Holmes demanda, ", // original: it seems "puis"/"then" was not used/removed. They instead added a space character, so sentences looked weird
+ "Alors Holmes dit, ",
+ "Alors je demandai, ",
+ "Alors je dis, ",
+ "Alors l'inspecteur demanda, ",
+ "Alors l'inspecteur dit, ",
+ "Alors %s demanda, ",
+ "Alors %s dit, "
+};
+
+// Sherlock Holmes 1+2:
+// small e w/ accent bottom to top : 0x82 / octal 202
+// big E w/ accent bottom to top : 0x90 / octal 220
+// small a w/ accent bottom to top : 0xA0 / octal 240
+// small i w/ accent bottom to top : 0xA1 / octal 241
+// small o w/ accent bottom to top : 0xA2 / octal 242
+// small u w/ accent bottom to top : 0xA3 / octal 243
+// small n w/ wavy line : 0xA4 / octal 244
+// big N w/ wavy line : 0xA5 / octal 245
+// small a w/ under line : 0xA6 / octal 246
+// small o w/ under line : 0xA7 / octal 247
+// inverted question mark : 0xA8 / octal 250
+static const char *const fixedJournalTextES[] = {
+ // Holmes asked/said...
+ "Holmes me pregunt\242, ", // original: "Holmes me pidi\242, ",
+ "Holmes pregunt\242 al Inspector, ", // original: "el inspector"?
+ "Holmes pregunt\242 %s, ",
+ "Holmes me dijo, ",
+ "Holmes dijo al Inspector, ", // original: "el inspector"?
+ "Holmes dijo a %s, ", // original: "Holmes dijo a %s, "
+ // I asked/said...
+ "Yo content\202, ", // original: "Yo respond\241, ",
+ "La respuesta fue, ",
+ // Holmes/I/The Inspector/Person asked/said (without "Then" prefix)
+ "Holmes pregunt\242, ",
+ "Holmes dijo, ",
+ "Yo pregunt\202, ", // original: "Yo pregunt\242, ",
+ "Yo dije, ",
+ "El Inspector pregunt\242, ",
+ "El Inspector dijo, ",
+ "%s pregunt\242, ",
+ "%s dijo, ",
+ // Then Holmes/I/The Inspector/Person asked/said
+ "Despu\202s Holmes pregunt\242, ", // original: added "Entonces" instead of "Despues"
+ "Despu\202s Holmes dijo, ",
+ "Despu\202s yo pregunt\202, ", // "pregunt\242, "
+ "Despu\202s yo dije, ",
+ "Despu\202s el Inspector pregunt\242, ",
+ "Despu\202s el Inspector dijo, ",
+ "Despu\202s %s pregunt\242, ",
+ "Despu\202s %s dijo, "
+};
+
+FixedText::FixedText(SherlockEngine *vm) {
+ _vm = vm;
+
+ // Figure out which fixed texts to use
+ Common::Language curLanguage = _vm->getLanguage();
+
+ switch (curLanguage) {
+ case Common::EN_ANY:
+ // Used by Sherlock Holmes 1+2
+ _fixedJournalTextArray = fixedJournalTextEN;
+ _fixedObjectPickedUpText = "Picked up %s";
+ break;
+ case Common::DE_DEU:
+ // Used by Sherlock Holmes 1+2
+ _fixedJournalTextArray = fixedJournalTextDE;
+ _fixedObjectPickedUpText = "%s eingesteckt";
+ break;
+ case Common::FR_FRA:
+ // Used by Sherlock Holmes 2
+ _fixedJournalTextArray = fixedJournalTextFR;
+ _fixedObjectPickedUpText = ""; // Not used, because there is no French Sherlock Holmes 1
+ break;
+ case Common::ES_ESP:
+ // Used by Sherlock Holmes 1+2
+ _fixedJournalTextArray = fixedJournalTextES;
+ _fixedObjectPickedUpText = "Cogido/a %s";
+ break;
+ default:
+ // Default to English
+ _fixedJournalTextArray = fixedJournalTextEN;
+ _fixedObjectPickedUpText = "Picked up %s";
+ break;
+ }
+}
+
FixedText *FixedText::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
return new Scalpel::ScalpelFixedText(vm);
@@ -34,5 +211,12 @@ FixedText *FixedText::init(SherlockEngine *vm) {
return new Tattoo::TattooFixedText(vm);
}
+const char *FixedText::getJournalText(int fixedJournalTextId) {
+ return _fixedJournalTextArray[fixedJournalTextId];
+}
+
+const char *FixedText::getObjectPickedUpText() {
+ return _fixedObjectPickedUpText;
+}
} // End of namespace Sherlock
diff --git a/engines/sherlock/fixed_text.h b/engines/sherlock/fixed_text.h
index 40444f4052..3eae60e1c3 100644
--- a/engines/sherlock/fixed_text.h
+++ b/engines/sherlock/fixed_text.h
@@ -39,13 +39,44 @@ enum FixedTextActionId {
kFixedTextAction_Use
};
+enum FixedJournalTextId {
+ // Holmes asked/said...
+ kFixedJournalText_HolmesAskedMe = 0,
+ kFixedJournalText_HolmesAskedTheInspector,
+ kFixedJournalText_HolmesAskedPerson,
+ kFixedJournalText_HolmesSaidToMe,
+ kFixedJournalText_HolmesSaidToTheInspector,
+ kFixedJournalText_HolmesSaidToPerson,
+ // I asked/said
+ kFixedJournalText_IReplied,
+ kFixedJournalText_TheReplyWas,
+ // Holmes/I/The Inspector/Person asked/said (without "Then" prefix)
+ kFixedJournalText_HolmesAsked,
+ kFixedJournalText_HolmesSaid,
+ kFixedJournalText_IAsked,
+ kFixedJournalText_ISaid,
+ kFixedJournalText_TheInspectorAsked,
+ kFixedJournalText_TheInspectorSaid,
+ kFixedJournalText_PersonAsked,
+ kFixedJournalText_PersonSaid,
+ // Then Holmes/I/The Inspector/Person asked/said
+ kFixedJournalText_ThenHolmesAsked,
+ kFixedJournalText_ThenHolmesSaid,
+ kFixedJournalText_ThenIAsked,
+ kFixedJournalText_ThenISaid,
+ kFixedJournalText_ThenTheInspectorAsked,
+ kFixedJournalText_ThenTheInspectorSaid,
+ kFixedJournalText_ThenPersonAsked,
+ kFixedJournalText_ThenPersonSaid
+};
+
class SherlockEngine;
class FixedText {
protected:
SherlockEngine *_vm;
- FixedText(SherlockEngine *vm) : _vm(vm) {}
+ FixedText(SherlockEngine *vm);
public:
static FixedText *init(SherlockEngine *vm);
virtual ~FixedText() {}
@@ -59,6 +90,20 @@ public:
* Get action message
*/
virtual const Common::String getActionMessage(FixedTextActionId actionId, int messageIndex) = 0;
+
+ /**
+ * Gets journal text
+ */
+ const char *getJournalText(int fixedJournalTextId);
+
+ /**
+ * Gets object "Picked Up" text
+ */
+ const char *getObjectPickedUpText();
+
+private:
+ const char *const *_fixedJournalTextArray;
+ const char *_fixedObjectPickedUpText;
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 8e36c3908a..5a14881f1c 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -43,7 +43,7 @@ void Fonts::setVm(SherlockEngine *vm) {
_charCount = 0;
}
-void Fonts::free() {
+void Fonts::freeFont() {
delete _font;
}
@@ -213,7 +213,7 @@ void Fonts::writeString(Surface *surface, const Common::String &str,
if (curChar < _charCount) {
ImageFrame &frame = (*_font)[curChar];
- surface->transBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
+ surface->SHtransBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
charPos.x += frame._frame.w + 1;
} else {
warning("Invalid character encountered - %d", (int)curChar);
diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h
index a527cc73c0..3594d466c2 100644
--- a/engines/sherlock/fonts.h
+++ b/engines/sherlock/fonts.h
@@ -57,7 +57,7 @@ public:
/**
* Frees the font manager
*/
- static void free();
+ static void freeFont();
/**
* Set the font to use for writing text on the screen
diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h
index da260ab30b..778332b726 100644
--- a/engines/sherlock/image_file.h
+++ b/engines/sherlock/image_file.h
@@ -46,6 +46,11 @@ struct ImageFrame {
Graphics::Surface _frame;
/**
+ * Converts an ImageFrame record to a surface for convenience in passing to drawing methods
+ */
+ operator const Graphics::Surface &() { return _frame; }
+
+ /**
* Decompress a single frame for the sprite
*/
void decompressFrame(const byte *src, bool isRoseTattoo);
diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp
index a30734c4f5..8763af31dd 100644
--- a/engines/sherlock/journal.cpp
+++ b/engines/sherlock/journal.cpp
@@ -299,6 +299,7 @@ bool Journal::drawJournal(int direction, int howFar) {
}
void Journal::loadJournalFile(bool alreadyLoaded) {
+ FixedText &fixedText = *_vm->_fixedText;
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
@@ -381,20 +382,34 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// If Holmes has something to say first, then take care of it
if (!replyOnly) {
// Handle the grammar
- journalString += "Holmes ";
+ bool asked = false;
+
if (talk[journalEntry._statementNum]._statement.hasSuffix("?"))
- journalString += "asked ";
- else
- journalString += "said to ";
+ asked = true;
if (talk._talkTo == 1) {
- journalString += "me";
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesAskedMe);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesSaidToTheInspector);
+
} else if ((talk._talkTo == 2 && IS_SERRATED_SCALPEL) || (talk._talkTo == 18 && IS_ROSE_TATTOO)) {
- journalString += "the Inspector";
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesAskedTheInspector);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesSaidToMe);
+
} else {
- journalString += people._characters[talk._talkTo]._name;
+ const char *text = nullptr;
+ if (asked)
+ text = fixedText.getJournalText(kFixedJournalText_HolmesAskedPerson);
+ else
+ text = fixedText.getJournalText(kFixedJournalText_HolmesSaidToPerson);
+
+ journalString += Common::String::format(text, people._characters[talk._talkTo]._name);
}
- journalString += ", \"";
+
+ journalString += "\"";
// Add the statement
journalString += statement._statement;
@@ -457,29 +472,46 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
journalString += "\"\n";
if (talk._talkTo == 1)
- journalString += "I replied, \"";
+ journalString += fixedText.getJournalText(kFixedJournalText_IReplied);
else
- journalString += "The reply was, \"";
+ journalString += fixedText.getJournalText(kFixedJournalText_TheReplyWas);
} else {
- if (talk._talkTo == 1)
- journalString += "I";
- else if (talk._talkTo == inspectorId)
- journalString += "The Inspector";
- else
- journalString += people._characters[talk._talkTo]._name;
-
const byte *strP = replyP + 1;
byte v;
do {
v = *strP++;
} while (v && (v < opcodes[0]) && (v != '.') && (v != '!') && (v != '?'));
+ bool asked = false;
+
if (v == '?')
- journalString += " asked, \"";
- else
- journalString += " said, \"";
+ asked = true;
+
+ if (talk._talkTo == 1) {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_IAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_ISaid);
+
+ } else if (talk._talkTo == inspectorId) {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_TheInspectorAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_TheInspectorSaid);
+
+ } else {
+ const char *text = nullptr;
+ if (asked)
+ text = fixedText.getJournalText(kFixedJournalText_PersonAsked);
+ else
+ text = fixedText.getJournalText(kFixedJournalText_PersonSaid);
+
+ journalString += Common::String::format(text, people._characters[talk._talkTo]._name);
+ }
}
+ journalString += "\"";
+
startOfReply = false;
}
@@ -502,11 +534,13 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
justChangedSpeaker = true;
}
+ bool addPrefixThen = false;
+
if (!startOfReply) {
if (!commentFlag && !commentJustPrinted)
journalString += "\"\n";
- journalString += "Then ";
+ addPrefixThen = true; // "Then" should get added to the sentence
commentFlag = false;
} else if (!replyOnly) {
journalString += "\"\n";
@@ -517,15 +551,6 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
if (IS_ROSE_TATTOO)
replyP++;
- if (c == 0)
- journalString += "Holmes";
- else if (c == 1)
- journalString += "I";
- else if (c == inspectorId)
- journalString += "the Inspector";
- else
- journalString += people._characters[c]._name;
-
if (IS_SERRATED_SCALPEL && _vm->getLanguage() == Common::DE_DEU)
Scalpel::ScalpelTalk::skipBadText(replyP);
@@ -535,10 +560,70 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
v = *strP++;
} while (v && v < opcodes[0] && v != '.' && v != '!' && v != '?');
+ bool asked = false;
+
if (v == '?')
- journalString += " asked, \"";
- else
- journalString += " said, \"";
+ asked = true;
+
+ if (c == 0) {
+ // Holmes
+ if (addPrefixThen) {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenHolmesAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenHolmesSaid);
+ } else {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_HolmesSaid);
+ }
+ } else if (c == 1) {
+ // I (Watson)
+ if (addPrefixThen) {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenIAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenISaid);
+ } else {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_IAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_ISaid);
+ }
+ } else if (c == inspectorId) {
+ // The Inspector
+ if (addPrefixThen) {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenTheInspectorAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_ThenTheInspectorSaid);
+ } else {
+ if (asked)
+ journalString += fixedText.getJournalText(kFixedJournalText_TheInspectorAsked);
+ else
+ journalString += fixedText.getJournalText(kFixedJournalText_TheInspectorSaid);
+ }
+ } else {
+ // Person
+ const char *text = nullptr;
+ if (addPrefixThen) {
+ if (asked)
+ text = fixedText.getJournalText(kFixedJournalText_ThenPersonAsked);
+ else
+ text = fixedText.getJournalText(kFixedJournalText_ThenPersonSaid);
+ } else {
+ if (asked)
+ text = fixedText.getJournalText(kFixedJournalText_PersonAsked);
+ else
+ text = fixedText.getJournalText(kFixedJournalText_PersonSaid);
+ }
+
+ journalString += Common::String::format(text, people._characters[c]._name);
+ }
+
+ journalString += "\"";
+
} else {
if (IS_SERRATED_SCALPEL) {
// Control code, so move past it and any parameters
@@ -718,8 +803,7 @@ bool Journal::isPrintable(byte ch) const {
if (ch < opcodes[0])
return true;
- if (_vm->getGameID() == GType_SerratedScalpel && _vm->getLanguage() == Common::DE_DEU
- && ch >= 0xe0)
+ if (_vm->getLanguage() == Common::DE_DEU && ch == 0xe1) // accept German Sharp-S character
return true;
return false;
diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 7fa7896691..0d17d0b249 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/sherlock
MODULE_OBJS = \
scalpel/scalpel.o \
scalpel/3do/movie_decoder.o \
+ scalpel/3do/scalpel_3do_screen.o \
scalpel/drivers/adlib.o \
scalpel/drivers/mt32.o \
scalpel/tsage/logo.o \
@@ -30,6 +31,7 @@ MODULE_OBJS = \
tattoo/tattoo_people.o \
tattoo/tattoo_resources.o \
tattoo/tattoo_scene.o \
+ tattoo/tattoo_screen.o \
tattoo/tattoo_talk.o \
tattoo/tattoo_user_interface.o \
tattoo/widget_base.o \
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index e70b707404..644c0c74c9 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -365,8 +365,8 @@ bool BaseObject::checkEndOfSequence() {
if (seq == 99) {
--_frameNumber;
- screen._backBuffer1.transBlitFrom(*_imageFrame, _position);
- screen._backBuffer2.transBlitFrom(*_imageFrame, _position);
+ screen._backBuffer1.SHtransBlitFrom(*_imageFrame, _position);
+ screen._backBuffer2.SHtransBlitFrom(*_imageFrame, _position);
_type = INVALID;
} else if (IS_ROSE_TATTOO && _talkSeq && seq == 0) {
setObjTalkSequence(_talkSeq);
@@ -1061,6 +1061,11 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
for (int idx = 0; idx < 6; ++idx)
_use[idx].load(s, true);
+ // WORKAROUND: Fix German version using hatpin/pin in pillow in Pratt's loft
+ if (_use[1]._target == "Nadel" && _use[1]._verb == "Untersuche"
+ && _use[2]._target == "Nadel" && _use[2]._verb == "Untersuche")
+ _use[1]._target = "Alte Nadel";
+
_quickDraw = s.readByte();
_scaleVal = s.readUint16LE();
_requiredFlag[1] = s.readSint16LE();
@@ -1338,7 +1343,7 @@ void Object::adjustObject() {
frame = 0;
int imgNum = _sequences[frame];
- if (imgNum > _maxFrames)
+ if (imgNum > _maxFrames || imgNum == 0)
imgNum = 1;
_imageFrame = &(*_images)[imgNum - 1];
@@ -1424,8 +1429,19 @@ int Object::pickUpObject(FixedTextActionId fixedTextActionId) {
ui.clearInfo();
Common::String itemName = _description;
- itemName.setChar(tolower(itemName[0]), 0);
- screen.print(Common::Point(0, INFO_LINE + 1), COL_INFO_FOREGROUND, "Picked up %s", itemName.c_str());
+
+ // It's an item, make it lowercase
+ switch (_vm->getLanguage()) {
+ case Common::DE_DEU:
+ // don't do this for German version
+ break;
+ default:
+ // do it for English + Spanish version
+ itemName.setChar(tolower(itemName[0]), 0);
+ break;
+ }
+
+ screen.print(Common::Point(0, INFO_LINE + 1), COL_INFO_FOREGROUND, fixedText.getObjectPickedUpText(), itemName.c_str());
ui._menuCounter = 25;
}
}
diff --git a/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp b/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
new file mode 100644
index 0000000000..f848394864
--- /dev/null
+++ b/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
@@ -0,0 +1,286 @@
+/* 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 "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+Scalpel3DOScreen::Scalpel3DOScreen(SherlockEngine *vm): ScalpelScreen(vm) {
+}
+
+void Scalpel3DOScreen::SHblitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
+ if (!_vm->_isScreenDoubled) {
+ ScalpelScreen::SHblitFrom(src, pt, srcBounds);
+ return;
+ }
+
+ Common::Rect srcRect = srcBounds;
+ Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
+
+ if (!srcRect.isValidRect() || !clip(srcRect, destRect))
+ return;
+
+ // Add dirty area remapped to the 640x200 surface
+ addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));
+
+ // Transfer the area, doubling each pixel
+ for (int yp = 0; yp < srcRect.height(); ++yp) {
+ const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
+ uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);
+
+ for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
+ *destP = *srcP;
+ *(destP + 1) = *srcP;
+ *(destP + 640) = *srcP;
+ *(destP + 640 + 1) = *srcP;
+ }
+ }
+}
+
+void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
+ bool flipped, int overrideColor) {
+ error("TODO: Refactor");
+#if 0
+ if (!_vm->_isScreenDoubled) {
+ ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor);
+ return;
+ }
+
+ Common::Rect drawRect(0, 0, src.w, src.h);
+ Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+ // Clip the display area to on-screen
+ if (!clip(drawRect, destRect))
+ // It's completely off-screen
+ return;
+
+ if (flipped)
+ drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
+ src.w - drawRect.left, src.h - drawRect.top);
+
+ Common::Point destPt(destRect.left, destRect.top);
+ addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2,
+ (destPt.y + drawRect.height()) * 2));
+
+ assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2);
+
+ for (int yp = 0; yp < drawRect.height(); ++yp) {
+ const uint16 *srcP = (const uint16 *)src.getBasePtr(
+ flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
+ uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2);
+
+ for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) {
+ // RGB 0, 0, 0 -> transparent on 3DO
+ if (*srcP) {
+ *destP = *srcP;
+ *(destP + 1) = *srcP;
+ *(destP + 640) = *srcP;
+ *(destP + 640 + 1) = *srcP;
+ }
+
+ srcP = flipped ? srcP - 1 : srcP + 1;
+ }
+ }
+#endif
+}
+
+void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) {
+ if (_vm->_isScreenDoubled)
+ ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color);
+ else
+ ScalpelScreen::fillRect(r, color);
+}
+
+void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) {
+ Events &events = *_vm->_events;
+ uint16 *currentScreenBasePtr = (uint16 *)getPixels();
+ uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
+ uint16 currentScreenPixel = 0;
+ uint16 targetScreenPixel = 0;
+
+ uint16 currentScreenPixelRed = 0;
+ uint16 currentScreenPixelGreen = 0;
+ uint16 currentScreenPixelBlue = 0;
+
+ uint16 targetScreenPixelRed = 0;
+ uint16 targetScreenPixelGreen = 0;
+ uint16 targetScreenPixelBlue = 0;
+
+ uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
+ uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
+ uint16 screenX = 0;
+ uint16 screenY = 0;
+ uint16 pixelsChanged = 0;
+
+ clearDirtyRects();
+
+ do {
+ pixelsChanged = 0;
+ uint16 *currentScreenPtr = currentScreenBasePtr;
+ uint16 *targetScreenPtr = targetScreenBasePtr;
+
+ for (screenY = 0; screenY < screenHeight; screenY++) {
+ for (screenX = 0; screenX < screenWidth; screenX++) {
+ currentScreenPixel = *currentScreenPtr;
+ targetScreenPixel = *targetScreenPtr;
+
+ if (currentScreenPixel != targetScreenPixel) {
+ // pixel doesn't match, adjust accordingly
+ currentScreenPixelRed = currentScreenPixel & 0xF800;
+ currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+ currentScreenPixelBlue = currentScreenPixel & 0x001F;
+ targetScreenPixelRed = targetScreenPixel & 0xF800;
+ targetScreenPixelGreen = targetScreenPixel & 0x07E0;
+ targetScreenPixelBlue = targetScreenPixel & 0x001F;
+
+ if (currentScreenPixelRed != targetScreenPixelRed) {
+ if (currentScreenPixelRed < targetScreenPixelRed) {
+ currentScreenPixelRed += 0x0800;
+ } else {
+ currentScreenPixelRed -= 0x0800;
+ }
+ }
+ if (currentScreenPixelGreen != targetScreenPixelGreen) {
+ // Adjust +2/-2 because we are running RGB555 at RGB565
+ if (currentScreenPixelGreen < targetScreenPixelGreen) {
+ currentScreenPixelGreen += 0x0040;
+ } else {
+ currentScreenPixelGreen -= 0x0040;
+ }
+ }
+ if (currentScreenPixelBlue != targetScreenPixelBlue) {
+ if (currentScreenPixelBlue < targetScreenPixelBlue) {
+ currentScreenPixelBlue += 0x0001;
+ } else {
+ currentScreenPixelBlue -= 0x0001;
+ }
+ }
+
+ uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+ *currentScreenPtr = v;
+ if (_vm->_isScreenDoubled) {
+ *(currentScreenPtr + 1) = v;
+ *(currentScreenPtr + 640) = v;
+ *(currentScreenPtr + 640 + 1) = v;
+ }
+
+ pixelsChanged++;
+ }
+
+ currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+ targetScreenPtr++;
+ }
+
+ if (_vm->_isScreenDoubled)
+ currentScreenPtr += 640;
+ }
+
+ // Too much considered dirty at the moment
+ if (_vm->_isScreenDoubled)
+ addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+ else
+ addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+
+ events.pollEvents();
+ events.delay(10 * speed);
+ } while ((pixelsChanged) && (!_vm->shouldQuit()));
+}
+
+void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) {
+ uint16 *currentScreenPtr = (uint16 *)getPixels();
+ uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
+ uint16 currentScreenPixel = 0;
+
+ uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
+ uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
+ uint16 screenX = 0;
+ uint16 screenY = 0;
+
+ uint16 currentScreenPixelRed = 0;
+ uint16 currentScreenPixelGreen = 0;
+ uint16 currentScreenPixelBlue = 0;
+
+ uint16 limitPixelRed = limitColor & 0xF800;
+ uint16 limitPixelGreen = limitColor & 0x07E0;
+ uint16 limitPixelBlue = limitColor & 0x001F;
+
+ for (screenY = 0; screenY < screenHeight; screenY++) {
+ for (screenX = 0; screenX < screenWidth; screenX++) {
+ currentScreenPixel = *targetScreenPtr;
+
+ currentScreenPixelRed = currentScreenPixel & 0xF800;
+ currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+ currentScreenPixelBlue = currentScreenPixel & 0x001F;
+
+ if (currentScreenPixelRed < limitPixelRed)
+ currentScreenPixelRed = limitPixelRed;
+ if (currentScreenPixelGreen < limitPixelGreen)
+ currentScreenPixelGreen = limitPixelGreen;
+ if (currentScreenPixelBlue < limitPixelBlue)
+ currentScreenPixelBlue = limitPixelBlue;
+
+ uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+ *currentScreenPtr = v;
+ if (_vm->_isScreenDoubled) {
+ *(currentScreenPtr + 1) = v;
+ *(currentScreenPtr + 640) = v;
+ *(currentScreenPtr + 640 + 1) = v;
+ }
+
+ currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+ targetScreenPtr++;
+ }
+
+ if (_vm->_isScreenDoubled)
+ currentScreenPtr += 640;
+ }
+
+ // Too much considered dirty at the moment
+ if (_vm->_isScreenDoubled)
+ addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+ else
+ addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+}
+
+uint16 Scalpel3DOScreen::width() const {
+ return _vm->_isScreenDoubled ? this->w / 2 : this->w;
+}
+
+uint16 Scalpel3DOScreen::height() const {
+ return _vm->_isScreenDoubled ? this->h / 2 : this->h;
+}
+
+void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) {
+ Common::Rect srcRect(0, 0, src.w, src.h);
+ Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+ addDirtyRect(destRect);
+ copyRectToSurface(src, destRect.left, destRect.top, srcRect);
+}
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/3do/scalpel_3do_screen.h b/engines/sherlock/scalpel/3do/scalpel_3do_screen.h
new file mode 100644
index 0000000000..422f588b17
--- /dev/null
+++ b/engines/sherlock/scalpel/3do/scalpel_3do_screen.h
@@ -0,0 +1,76 @@
+/* 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 SHERLOCK_SCALPEL_3DO_SCREEN_H
+#define SHERLOCK_SCALPEL_3DO_SCREEN_H
+
+#include "sherlock/scalpel/scalpel_screen.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+namespace Scalpel {
+
+class Scalpel3DOScreen : public ScalpelScreen {
+protected:
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ * Overriden for the 3DO to automatically double the size of everything to the underlying 640x400 surface
+ */
+ virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
+
+ /**
+ * Draws a surface at a given position within this surface with transparency
+ */
+ virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
+ int overrideColor);
+public:
+ Scalpel3DOScreen(SherlockEngine *vm);
+ virtual ~Scalpel3DOScreen() {}
+
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ */
+ void rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt);
+
+ /**
+ * Fade backbuffer 1 into screen (3DO RGB!)
+ */
+ void fadeIntoScreen3DO(int speed);
+
+ void blitFrom3DOcolorLimit(uint16 color);
+
+ /**
+ * Fill a given area of the surface with a given color
+ */
+ virtual void fillRect(const Common::Rect &r, uint color);
+
+ virtual uint16 width() const;
+ virtual uint16 height() const;
+};
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index b17f38b218..cbb202095f 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -29,6 +29,7 @@
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
#include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
#include "sherlock/scalpel/tsage/logo.h"
#include "sherlock/sherlock.h"
#include "sherlock/music.h"
@@ -371,8 +372,8 @@ bool ScalpelEngine::showCityCutscene() {
if (finished) {
ImageFile titleImages_LondonNovember("title2.vgs", true);
- _screen->_backBuffer1.blitFrom(*_screen);
- _screen->_backBuffer2.blitFrom(*_screen);
+ _screen->_backBuffer1.SHblitFrom(*_screen);
+ _screen->_backBuffer2.SHblitFrom(*_screen);
Common::Point londonPosition;
@@ -386,19 +387,19 @@ bool ScalpelEngine::showCityCutscene() {
}
// London, England
- _screen->_backBuffer1.transBlitFrom(titleImages_LondonNovember[0], londonPosition);
+ _screen->_backBuffer1.SHtransBlitFrom(titleImages_LondonNovember[0], londonPosition);
_screen->randomTransition();
finished = _events->delay(1000, true);
// November, 1888
if (finished) {
- _screen->_backBuffer1.transBlitFrom(titleImages_LondonNovember[1], Common::Point(100, 100));
+ _screen->_backBuffer1.SHtransBlitFrom(titleImages_LondonNovember[1], Common::Point(100, 100));
_screen->randomTransition();
finished = _events->delay(5000, true);
}
// Transition out the title
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2);
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2);
_screen->randomTransition();
}
@@ -407,8 +408,8 @@ bool ScalpelEngine::showCityCutscene() {
if (finished) {
ImageFile titleImages_SherlockHolmesTitle("title.vgs", true);
- _screen->_backBuffer1.blitFrom(*_screen);
- _screen->_backBuffer2.blitFrom(*_screen);
+ _screen->_backBuffer1.SHblitFrom(*_screen);
+ _screen->_backBuffer2.SHblitFrom(*_screen);
Common::Point lostFilesPosition;
Common::Point sherlockHolmesPosition;
@@ -427,17 +428,17 @@ bool ScalpelEngine::showCityCutscene() {
}
// The Lost Files of
- _screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[0], lostFilesPosition);
+ _screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[0], lostFilesPosition);
// Sherlock Holmes
- _screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[1], sherlockHolmesPosition);
+ _screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[1], sherlockHolmesPosition);
// copyright
- _screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[2], copyrightPosition);
+ _screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[2], copyrightPosition);
_screen->verticalTransition();
finished = _events->delay(4000, true);
if (finished) {
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2);
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2);
_screen->randomTransition();
finished = _events->delay(2000);
}
@@ -461,7 +462,7 @@ bool ScalpelEngine::showCityCutscene() {
// English, width 175, height 38
alleyPosition = Common::Point(72, 51);
}
- _screen->transBlitFrom(titleImages_SherlockHolmesTitle[3], alleyPosition);
+ _screen->SHtransBlitFrom(titleImages_SherlockHolmesTitle[3], alleyPosition);
_screen->fadeIn(palette, 3);
// Wait until the track got looped and the first few notes were played
@@ -537,7 +538,7 @@ bool ScalpelEngine::showAlleyCutscene() {
earlyTheFollowingMorningPosition = Common::Point(35, 52);
}
- _screen->transBlitFrom(titleImages_EarlyTheFollowingMorning[0], earlyTheFollowingMorningPosition);
+ _screen->SHtransBlitFrom(titleImages_EarlyTheFollowingMorning[0], earlyTheFollowingMorningPosition);
// fast fade-in
_screen->fadeIn(palette, 1);
@@ -641,23 +642,23 @@ bool ScalpelEngine::scrollCredits() {
delete stream;
// Save a copy of the screen background for use in drawing each credit frame
- _screen->_backBuffer1.blitFrom(*_screen);
+ _screen->_backBuffer1.SHblitFrom(*_screen);
// Loop for showing the credits
for(int idx = 0; idx < 600 && !_events->kbHit() && !shouldQuit(); ++idx) {
// Copy the entire screen background before writing text
- _screen->blitFrom(_screen->_backBuffer1);
+ _screen->SHblitFrom(_screen->_backBuffer1);
// Write the text appropriate for the next frame
if (idx < 400)
- _screen->transBlitFrom(creditsImages[0], Common::Point(10, 200 - idx), false, 0);
+ _screen->SHtransBlitFrom(creditsImages[0], Common::Point(10, 200 - idx), false, 0);
if (idx > 200)
- _screen->transBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
+ _screen->SHtransBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
// Don't show credit text on the top and bottom ten rows of the screen
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->w(), 10));
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h() - 10),
- Common::Rect(0, _screen->h() - 10, _screen->w(), _screen->h()));
+ _screen->SHblitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->width(), 10));
+ _screen->SHblitFrom(_screen->_backBuffer1, Common::Point(0, _screen->height() - 10),
+ Common::Rect(0, _screen->height() - 10, _screen->width(), _screen->height()));
_events->delay(100);
}
@@ -670,7 +671,7 @@ bool ScalpelEngine::show3DOSplash() {
// 3DO EA Splash screen
ImageFile3DO titleImage_3DOSplash("3DOSplash.cel", kImageFile3DOType_Cel);
- _screen->transBlitFrom(titleImage_3DOSplash[0]._frame, Common::Point(0, -20));
+ _screen->SHtransBlitFrom(titleImage_3DOSplash[0]._frame, Common::Point(0, -20));
bool finished = _events->delay(3000, true);
if (finished) {
@@ -706,7 +707,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
_sound->playAiff("prologue/sounds/rain.aiff", 15, true);
// Fade screen to grey
- screen._backBuffer1.fill(0xCE59); // RGB565: 25, 50, 25 (grey)
+ screen._backBuffer1.clear(0xCE59); // RGB565: 25, 50, 25 (grey)
screen.fadeIntoScreen3DO(2);
}
@@ -715,16 +716,16 @@ bool ScalpelEngine::showCityCutscene3DO() {
}
if (finished) {
- screen._backBuffer1.fill(0); // fill backbuffer with black to avoid issues during fade from white
+ screen._backBuffer1.clear(0); // fill backbuffer with black to avoid issues during fade from white
finished = _animation->play3DO("26open1", true, 1, true, 2);
}
if (finished) {
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
// "London, England"
ImageFile3DO titleImage_London("title2a.cel", kImageFile3DOType_Cel);
- screen._backBuffer1.transBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
+ screen._backBuffer1.SHtransBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
screen.fadeIntoScreen3DO(1);
finished = _events->delay(1500, true);
@@ -732,7 +733,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// "November, 1888"
ImageFile3DO titleImage_November("title2b.cel", kImageFile3DOType_Cel);
- screen._backBuffer1.transBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
+ screen._backBuffer1.SHtransBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
screen.fadeIntoScreen3DO(1);
finished = _music->waitUntilMSec(14700, 0, 0, 5000);
@@ -740,8 +741,8 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// Restore screen
- _screen->_backBuffer1.blitFrom(screen._backBuffer2);
- _screen->blitFrom(screen._backBuffer1);
+ _screen->_backBuffer1.SHblitFrom(screen._backBuffer2);
+ _screen->SHblitFrom(screen._backBuffer1);
}
}
@@ -751,7 +752,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// "Sherlock Holmes" (title)
ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel", kImageFile3DOType_Cel);
- screen._backBuffer1.transBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
+ screen._backBuffer1.SHtransBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
// Blend in
screen.fadeIntoScreen3DO(2);
@@ -761,7 +762,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
ImageFile3DO titleImage_Copyright("title1c.cel", kImageFile3DOType_Cel);
- screen.transBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
+ screen.SHtransBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
finished = _events->delay(3500, true);
}
}
@@ -780,7 +781,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// "In the alley behind the Regency Theatre..."
ImageFile3DO titleImage_InTheAlley("title1d.cel", kImageFile3DOType_Cel);
- screen._backBuffer1.transBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
+ screen._backBuffer1.SHtransBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
// Fade in
screen.fadeIntoScreen3DO(4);
@@ -819,7 +820,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
ImageFile3DO titleImage_ScreamingVictim("scream.cel", kImageFile3DOType_Cel);
screen.clear();
- screen.transBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
+ screen.SHtransBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
// Play "scream.aiff"
if (_sound->_voices)
@@ -848,7 +849,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// "Early the following morning on Baker Street..."
ImageFile3DO titleImage_EarlyTheFollowingMorning("title3.cel", kImageFile3DOType_Cel);
- screen._backBuffer1.transBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
+ screen._backBuffer1.SHtransBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
// Fade in
screen.fadeIntoScreen3DO(4);
@@ -908,7 +909,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
ImageFile3DO titleImage_CoffeeNote("note.cel", kImageFile3DOType_Cel);
_screen->clear();
- _screen->transBlitFrom(titleImage_CoffeeNote[0]._frame, Common::Point(0, 0));
+ _screen->SHtransBlitFrom(titleImage_CoffeeNote[0]._frame, Common::Point(0, 0));
if (_sound->_voices) {
finished = _sound->playSound("prologue/sounds/note.aiff", WAIT_KBD_OR_FINISH);
@@ -937,7 +938,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
// TODO: Brighten the image, possibly by doing a partial fade
// to white.
- _screen->_backBuffer2.blitFrom(_screen->_backBuffer1);
+ _screen->_backBuffer2.SHblitFrom(_screen->_backBuffer1);
for (int nr = 1; finished && nr <= 4; nr++) {
char filename[15];
@@ -945,8 +946,8 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
ImageFile3DO *creditsImage = new ImageFile3DO(filename, kImageFile3DOType_Cel);
ImageFrame *creditsFrame = &(*creditsImage)[0];
for (int i = 0; finished && i < 200 + creditsFrame->_height; i++) {
- _screen->blitFrom(_screen->_backBuffer2);
- _screen->transBlitFrom(creditsFrame->_frame, Common::Point((320 - creditsFrame->_width) / 2, 200 - i));
+ _screen->SHblitFrom(_screen->_backBuffer2);
+ _screen->SHtransBlitFrom(creditsFrame->_frame, Common::Point((320 - creditsFrame->_width) / 2, 200 - i));
if (!_events->delay(70, true))
finished = false;
}
@@ -998,7 +999,7 @@ void ScalpelEngine::showLBV(const Common::String &filename) {
delete stream;
_screen->setPalette(images._palette);
- _screen->_backBuffer1.blitFrom(images[0]);
+ _screen->_backBuffer1.SHblitFrom(images[0]);
_screen->verticalTransition();
}
@@ -1156,7 +1157,7 @@ void ScalpelEngine::eraseBrumwellMirror() {
// If player is in range of the mirror, then restore background from the secondary back buffer
if (Common::Rect(70, 100, 200, 200).contains(pt)) {
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 18),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(137, 18),
Common::Rect(137, 18, 184, 74));
}
}
@@ -1218,20 +1219,20 @@ void ScalpelEngine::doBrumwellMirror() {
bool flipped = people[HOLMES]._sequenceNumber == WALK_LEFT || people[HOLMES]._sequenceNumber == STOP_LEFT
|| people[HOLMES]._sequenceNumber == WALK_UPRIGHT || people[HOLMES]._sequenceNumber == STOP_UPRIGHT
|| people[HOLMES]._sequenceNumber == WALK_DOWNLEFT || people[HOLMES]._sequenceNumber == STOP_DOWNLEFT;
- _screen->_backBuffer1.transBlitFrom(imageFrame, pt + Common::Point(38, -imageFrame._frame.h - 25), flipped);
+ _screen->_backBuffer1.SHtransBlitFrom(imageFrame, pt + Common::Point(38, -imageFrame._frame.h - 25), flipped);
// Redraw the mirror borders to prevent the drawn image of Holmes from appearing outside of the mirror
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(114, 18),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(114, 18),
Common::Rect(114, 18, 137, 114));
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 70),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(137, 70),
Common::Rect(137, 70, 142, 114));
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(142, 71),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(142, 71),
Common::Rect(142, 71, 159, 114));
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(159, 72),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(159, 72),
Common::Rect(159, 72, 170, 116));
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(170, 73),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(170, 73),
Common::Rect(170, 73, 184, 114));
- _screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(184, 18),
+ _screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(184, 18),
Common::Rect(184, 18, 212, 114));
}
}
@@ -1272,7 +1273,7 @@ void ScalpelEngine::showScummVMRestoreDialog() {
bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder();
- Graphics::Surface tempSurface;
+ Graphics::ManagedSurface tempSurface;
Common::Point framePos(pos.x, pos.y);
ImageFile3DO *frameImageFile = nullptr;
@@ -1307,7 +1308,7 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
// If we're to show the movie at half-size, we'll need a temporary intermediate surface
if (halfSize)
- tempSurface.create(width / 2, height / 2, _screen->getPixelFormat());
+ tempSurface.create(width / 2, height / 2);
while (!shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
if (videoDecoder->needsUpdate()) {
@@ -1371,19 +1372,19 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
}
// Point the drawing frame to the temporary surface
- frame = &tempSurface;
+ frame = &tempSurface.rawSurface();
}
if (isPortrait && !frameShown) {
// Draw the frame (not the frame of the video, but a frame around the video) itself
- _screen->transBlitFrom(frameImage->_frame, framePos);
+ _screen->SHtransBlitFrom(frameImage->_frame, framePos);
frameShown = true;
}
if (isPortrait && !halfSize) {
screen.rawBlitFrom(*frame, Common::Point(pos.x * 2, pos.y * 2));
} else {
- _screen->blitFrom(*frame, pos);
+ _screen->SHblitFrom(*frame, pos);
}
_screen->update();
@@ -1413,9 +1414,9 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
}
// Restore scene
- screen._backBuffer1.blitFrom(screen._backBuffer2);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2);
_scene->updateBackground();
- screen.slamArea(0, 0, screen.w(), CONTROLS_Y);
+ screen.slamArea(0, 0, screen.width(), CONTROLS_Y);
return !skipVideo;
}
diff --git a/engines/sherlock/scalpel/scalpel_darts.cpp b/engines/sherlock/scalpel/scalpel_darts.cpp
index 87f4566837..c5ba8032f3 100644
--- a/engines/sherlock/scalpel/scalpel_darts.cpp
+++ b/engines/sherlock/scalpel/scalpel_darts.cpp
@@ -102,7 +102,7 @@ void Darts::playDarts() {
score -= lastDart;
_roundScore += lastDart;
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", idx + 1);
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Scored %d points", lastDart);
@@ -154,7 +154,7 @@ void Darts::playDarts() {
events.wait(20);
}
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
@@ -166,8 +166,8 @@ void Darts::playDarts() {
done |= _vm->shouldQuit();
if (!done) {
- screen._backBuffer2.blitFrom((*_dartImages)[0], Common::Point(0, 0));
- screen._backBuffer1.blitFrom(screen._backBuffer2);
+ screen._backBuffer2.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2);
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
} while (!done);
@@ -185,7 +185,7 @@ void Darts::loadDarts() {
_dartImages = new ImageFile("darts.vgs");
screen.setPalette(_dartImages->_palette);
- screen._backBuffer1.blitFrom((*_dartImages)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
@@ -245,7 +245,7 @@ void Darts::showNames(int playerNum) {
screen.slamArea(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, 81, 12);
// Make a copy of the back buffer to the secondary one
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
}
void Darts::showStatus(int playerNum) {
@@ -253,7 +253,7 @@ void Darts::showStatus(int playerNum) {
byte color;
// Copy scoring screen from secondary back buffer. This will erase any previously displayed status/score info
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48));
color = (playerNum == 0) ? PLAYER_COLOR : DART_COL_FORE;
@@ -292,7 +292,7 @@ int Darts::throwDart(int dartNum, int computer) {
if (_vm->shouldQuit())
return 0;
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.slamRect(Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
@@ -309,9 +309,9 @@ int Darts::throwDart(int dartNum, int computer) {
// Copy the bars to the secondary back buffer so that they remain fixed at their selected values
// whilst the dart is being animated at being thrown at the board
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1),
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1),
Common::Rect(DARTBARHX - 1, DARTHORIZY - 1, DARTBARHX + DARTBARSIZE + 3, DARTHORIZY + 10));
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1),
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1),
Common::Rect(DARTBARVX - 1, DARTHEIGHTY - 1, DARTBARVX + 11, DARTHEIGHTY + DARTBARSIZE + 3));
// Convert height and width to relative range of -50 to 50, where 0,0 is the exact centre of the board
@@ -344,7 +344,7 @@ void Darts::drawDartThrow(const Common::Point &pt) {
// Draw the dart
Common::Point drawPos(pos.x - frame._width / 2, pos.y - frame._height);
- screen._backBuffer1.transBlitFrom(frame, drawPos);
+ screen._backBuffer1.SHtransBlitFrom(frame, drawPos);
screen.slamArea(drawPos.x, drawPos.y, frame._width, frame._height);
// Handle erasing old dart frame area
@@ -352,14 +352,14 @@ void Darts::drawDartThrow(const Common::Point &pt) {
screen.slamRect(oldDrawBounds);
oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame._width, drawPos.y + frame._height);
- screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
events.wait(2);
}
// Draw dart in final "stuck to board" form
- screen._backBuffer1.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
- screen._backBuffer2.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
+ screen._backBuffer1.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
+ screen._backBuffer2.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
screen.slamRect(oldDrawBounds);
}
@@ -368,8 +368,8 @@ void Darts::erasePowerBars() {
screen._backBuffer1.fillRect(Common::Rect(DARTBARHX, DARTHORIZY, DARTBARHX + DARTBARSIZE, DARTHORIZY + 10), BLACK);
screen._backBuffer1.fillRect(Common::Rect(DARTBARVX, DARTHEIGHTY, DARTBARVX + 10, DARTHEIGHTY + DARTBARSIZE), BLACK);
- screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1));
- screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1));
screen.slamArea(DARTBARHX - 1, DARTHORIZY - 1, DARTBARSIZE + 3, 11);
screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3);
}
@@ -398,11 +398,11 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool i
if (isVertical) {
screen._backBuffer1.hLine(pt.x, pt.y + DARTBARSIZE - 1 - idx, pt.x + 8, color);
- screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1));
screen.slamArea(pt.x, pt.y + DARTBARSIZE - 1 - idx, 8, 2);
} else {
screen._backBuffer1.vLine(pt.x + idx, pt.y, pt.y + 8, color);
- screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1));
screen.slamArea(pt.x + idx, pt.y, 1, 8);
}
diff --git a/engines/sherlock/scalpel/scalpel_fixed_text.cpp b/engines/sherlock/scalpel/scalpel_fixed_text.cpp
index 8932fb29c5..d76136a1db 100644
--- a/engines/sherlock/scalpel/scalpel_fixed_text.cpp
+++ b/engines/sherlock/scalpel/scalpel_fixed_text.cpp
@@ -105,6 +105,14 @@ static const char *const fixedTextEN[] = {
"Tarot Cards",
"An ornate key",
"A pawn ticket",
+ // SH1: User Interface
+ "No, thank you.",
+ "You can't do that.",
+ "Done...",
+ "Use ",
+ " on %s",
+ "Give ",
+ " to %s",
// SH1: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -250,6 +258,14 @@ static const char *const fixedTextDE[] = {
"Ein Tarot-Kartenspiel", // original interpreter: "Ein Tarock-Kartenspiel" [sic]
"Ein verzierter Schl\201ssel",
"Ein Pfandschein",
+ // SH1: User Interface
+ "Nein, vielen Dank.",
+ "Nein, das geht wirklich nicht.", // original: "Nein, das geht wirklich nicht"
+ "Fertig...",
+ "Benutze ",
+ " mit %s",
+ "Gib ", // original: "Gebe "
+ " an %s", // original: " zu %s"
// SH1: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -316,6 +332,7 @@ static const char *const fixedTextDE[] = {
// up-side down exclamation mark - 0xAD / octal 255
// up-side down question mark - 0xA8 / octal 250
// n with a wave on top - 0xA4 / octal 244
+// more characters see engines/sherlock/fixed_text.cpp
static const char *const fixedTextES[] = {
// Game hotkeys
"VMHTACIUDNFO",
@@ -394,6 +411,14 @@ static const char *const fixedTextES[] = {
"Unas cartas de Tarot",
"Una llave muy vistosa",
"Una papeleta de empe\244o",
+ // SH1: User Interface
+ "No, gracias.",
+ "No puedes hacerlo.", // original: "No puedes hacerlo"
+ "Hecho...",
+ "Usar ",
+ " sobre %s",
+ "Dar ",
+ " a %s",
// SH1: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -517,7 +542,7 @@ static const char *const fixedTextDE_ActionMove[] = {
"L\204\341t sich nicht bewegen",
"Festged\201belt in der Erde...",
"Oha, VIEL zu schwer",
- "Der andere Kiste ist im Weg" // [sic]
+ "Die andere Kiste ist im Weg" // original: "Der andere Kiste ist im Weg"
};
static const char *const fixedTextES_ActionMove[] = {
@@ -616,8 +641,6 @@ static const FixedTextActionEntry fixedTextES_Actions[] = {
// =========================================
-// TODO:
-// It seems there was a French version of Sherlock Holmes 2
static const FixedTextLanguageEntry fixedTextLanguages[] = {
{ Common::DE_DEU, fixedTextDE, fixedTextDE_Actions },
{ Common::ES_ESP, fixedTextES, fixedTextES_Actions },
diff --git a/engines/sherlock/scalpel/scalpel_fixed_text.h b/engines/sherlock/scalpel/scalpel_fixed_text.h
index 841d602408..d9b3bbed79 100644
--- a/engines/sherlock/scalpel/scalpel_fixed_text.h
+++ b/engines/sherlock/scalpel/scalpel_fixed_text.h
@@ -107,6 +107,14 @@ enum FixedTextId {
kFixedText_InitInventory_Tarot,
kFixedText_InitInventory_OrnateKey,
kFixedText_InitInventory_PawnTicket,
+ // SH1: User Interface
+ kFixedText_UserInterface_NoThankYou,
+ kFixedText_UserInterface_YouCantDoThat,
+ kFixedText_UserInterface_Done,
+ kFixedText_UserInterface_Use,
+ kFixedText_UserInterface_UseOn,
+ kFixedText_UserInterface_Give,
+ kFixedText_UserInterface_GiveTo,
// People names
kFixedText_People_SherlockHolmes,
kFixedText_People_DrWatson,
diff --git a/engines/sherlock/scalpel/scalpel_inventory.cpp b/engines/sherlock/scalpel/scalpel_inventory.cpp
index c3e20295fd..e8d4d3b934 100644
--- a/engines/sherlock/scalpel/scalpel_inventory.cpp
+++ b/engines/sherlock/scalpel/scalpel_inventory.cpp
@@ -201,7 +201,7 @@ void ScalpelInventory::highlight(int index, byte color) {
ImageFrame &frame = (*_invShapes[slot])[0];
bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color);
- bb.transBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
+ bb.SHtransBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
163 + ((33 - frame._height) / 2)));
screen.slamArea(8 + slot * 52, 165, 44, 30);
}
@@ -217,12 +217,12 @@ void ScalpelInventory::refreshInv() {
ui._infoFlag = true;
ui.clearInfo();
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
ui.examine();
if (!talk._talkToAbort) {
- screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
+ screen._backBuffer2.SHblitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
loadInv();
}
}
@@ -264,7 +264,7 @@ void ScalpelInventory::putInv(InvSlamMode slamIt) {
// Draw the item image
ImageFrame &frame = (*_invShapes[itemNum])[0];
- bb.transBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
+ bb.SHtransBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
163 + ((33 - frame._height) / 2)));
}
diff --git a/engines/sherlock/scalpel/scalpel_map.cpp b/engines/sherlock/scalpel/scalpel_map.cpp
index 0924581e38..ba14b5b300 100644
--- a/engines/sherlock/scalpel/scalpel_map.cpp
+++ b/engines/sherlock/scalpel/scalpel_map.cpp
@@ -167,13 +167,13 @@ int ScalpelMap::show() {
setupSprites();
if (!IS_3DO) {
- screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
} else {
- screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
- screen.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
}
_drawMap = true;
@@ -238,12 +238,12 @@ int ScalpelMap::show() {
changed = false;
if (!IS_3DO) {
- screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
- screen._backBuffer1.blitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
} else {
- screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+ screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
}
showPlaces();
@@ -359,7 +359,6 @@ void ScalpelMap::freeSprites() {
delete _mapCursors;
delete _shapes;
delete _iconShapes;
- _iconSave.free();
}
void ScalpelMap::showPlaces() {
@@ -376,7 +375,7 @@ void ScalpelMap::showPlaces() {
if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
&& pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
if (_vm->readFlags(idx)) {
- screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
+ screen._backBuffer1.SHtransBlitFrom((*_iconShapes)[pt._translate],
Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
}
}
@@ -388,13 +387,13 @@ void ScalpelMap::showPlaces() {
}
void ScalpelMap::saveTopLine() {
- _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
+ _topLine.SHblitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
}
void ScalpelMap::eraseTopLine() {
Screen &screen = *_vm->_screen;
- screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
+ screen._backBuffer1.SHblitFrom(_topLine, Common::Point(0, 0));
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.height());
}
void ScalpelMap::showPlaceName(int idx, bool highlighted) {
@@ -409,7 +408,7 @@ void ScalpelMap::showPlaceName(int idx, bool highlighted) {
bool flipped = people[HOLMES]._sequenceNumber == MAP_DOWNLEFT || people[HOLMES]._sequenceNumber == MAP_LEFT
|| people[HOLMES]._sequenceNumber == MAP_UPLEFT;
- screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, _lDrawnPos, flipped);
+ screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, _lDrawnPos, flipped);
}
if (highlighted) {
@@ -451,9 +450,9 @@ void ScalpelMap::updateMap(bool flushScreen) {
saveIcon(people[HOLMES]._imageFrame, hPos);
if (people[HOLMES]._sequenceNumber == MAP_DOWNLEFT || people[HOLMES]._sequenceNumber == MAP_LEFT
|| people[HOLMES]._sequenceNumber == MAP_UPLEFT)
- screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, hPos, true);
+ screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, hPos, true);
else
- screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, hPos, false);
+ screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, hPos, false);
if (flushScreen) {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -553,8 +552,8 @@ void ScalpelMap::saveIcon(ImageFrame *src, const Common::Point &pt) {
return;
}
- assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
- _iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
+ assert(size.x <= _iconSave.width() && size.y <= _iconSave.height());
+ _iconSave.SHblitFrom(screen._backBuffer1, Common::Point(0, 0),
Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
_savedPos = pos;
_savedSize = size;
@@ -565,7 +564,7 @@ void ScalpelMap::restoreIcon() {
if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
&& _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
- screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
+ screen._backBuffer1.SHblitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
}
void ScalpelMap::highlightIcon(const Common::Point &pt) {
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index b62703e0fb..83e49bb3fa 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -71,26 +71,26 @@ void ScalpelScene::drawAllShapes() {
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]->_type == ACTIVE_BG_SHAPE && _canimShapes[idx]->_misc == BEHIND)
- screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame,
+ screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame,
_canimShapes[idx]->_position, _canimShapes[idx]->_flags & OBJ_FLIPPED);
}
// Draw all active shapes which are normal and behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all canimations which are normal and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]->_type == ACTIVE_BG_SHAPE && _canimShapes[idx]->_misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+ screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
_canimShapes[idx]->_flags & OBJ_FLIPPED);
}
@@ -103,7 +103,7 @@ void ScalpelScene::drawAllShapes() {
p._sequenceNumber == WALK_UPLEFT || p._sequenceNumber == STOP_UPLEFT ||
p._sequenceNumber == WALK_DOWNRIGHT || p._sequenceNumber == STOP_DOWNRIGHT);
- screen._backBuffer->transBlitFrom(*p._imageFrame, Common::Point(p._position.x / FIXED_INT_MULTIPLIER,
+ screen._backBuffer->SHtransBlitFrom(*p._imageFrame, Common::Point(p._position.x / FIXED_INT_MULTIPLIER,
p._position.y / FIXED_INT_MULTIPLIER - p.frameHeight()), flipped);
}
}
@@ -112,7 +112,7 @@ void ScalpelScene::drawAllShapes() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+ screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
_bgShapes[idx]._flags & OBJ_FLIPPED);
}
@@ -120,7 +120,7 @@ void ScalpelScene::drawAllShapes() {
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if ((_canimShapes[idx]->_type == ACTIVE_BG_SHAPE || _canimShapes[idx]->_type == STATIC_BG_SHAPE) &&
_canimShapes[idx]->_misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+ screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
_canimShapes[idx]->_flags & OBJ_FLIPPED);
}
@@ -132,7 +132,7 @@ void ScalpelScene::drawAllShapes() {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == FORWARD)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+ screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
_bgShapes[idx]._flags & OBJ_FLIPPED);
}
@@ -140,7 +140,7 @@ void ScalpelScene::drawAllShapes() {
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if ((_canimShapes[idx]->_type == ACTIVE_BG_SHAPE || _canimShapes[idx]->_type == STATIC_BG_SHAPE) &&
_canimShapes[idx]->_misc == FORWARD)
- screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+ screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
_canimShapes[idx]->_flags & OBJ_FLIPPED);
}
@@ -242,7 +242,7 @@ void ScalpelScene::doBgAnim() {
if (people[HOLMES]._type == CHARACTER)
screen.restoreBackground(bounds);
else if (people[HOLMES]._type == REMOVE)
- screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds);
+ screen._backBuffer->SHblitFrom(screen._backBuffer2, pt, bounds);
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
@@ -261,7 +261,7 @@ void ScalpelScene::doBgAnim() {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && ((o._flags & OBJ_BEHIND) == 0)) {
// Restore screen area
- screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
+ screen._backBuffer->SHblitFrom(screen._backBuffer2, o._position,
Common::Rect(o._position.x, o._position.y,
o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
@@ -309,14 +309,14 @@ void ScalpelScene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = *_canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -324,14 +324,14 @@ void ScalpelScene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all canimations which are NORMAL and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = *_canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -344,7 +344,7 @@ void ScalpelScene::doBgAnim() {
bool flipped = people[HOLMES]._sequenceNumber == WALK_LEFT || people[HOLMES]._sequenceNumber == STOP_LEFT ||
people[HOLMES]._sequenceNumber == WALK_UPLEFT || people[HOLMES]._sequenceNumber == STOP_UPLEFT ||
people[HOLMES]._sequenceNumber == WALK_DOWNRIGHT || people[HOLMES]._sequenceNumber == STOP_DOWNRIGHT;
- screen._backBuffer->transBlitFrom(*people[HOLMES]._imageFrame,
+ screen._backBuffer->SHtransBlitFrom(*people[HOLMES]._imageFrame,
Common::Point(tempX, people[HOLMES]._position.y / FIXED_INT_MULTIPLIER - people[HOLMES]._imageFrame->_frame.h), flipped);
}
@@ -352,14 +352,14 @@ void ScalpelScene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are NORMAL and are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = *_canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -367,19 +367,19 @@ void ScalpelScene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw any active portrait
if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
- screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
+ screen._backBuffer->SHtransBlitFrom(*people._portrait._imageFrame,
people._portrait._position, people._portrait._flags & OBJ_FLIPPED);
// Draw all static and active canimations that are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = *_canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -387,7 +387,7 @@ void ScalpelScene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Bring the newly built picture to the screen
diff --git a/engines/sherlock/scalpel/scalpel_screen.cpp b/engines/sherlock/scalpel/scalpel_screen.cpp
index 197a2a2634..37e5294c02 100644
--- a/engines/sherlock/scalpel/scalpel_screen.cpp
+++ b/engines/sherlock/scalpel/scalpel_screen.cpp
@@ -28,6 +28,8 @@ namespace Sherlock {
namespace Scalpel {
ScalpelScreen::ScalpelScreen(SherlockEngine *vm) : Screen(vm) {
+ _backBuffer1.create(320, 200);
+ _backBuffer2.create(320, 200);
}
void ScalpelScreen::makeButton(const Common::Rect &bounds, int textX,
@@ -123,255 +125,6 @@ void ScalpelScreen::makeField(const Common::Rect &r) {
_backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP);
}
-/*----------------------------------------------------------------*/
-
-void Scalpel3DOScreen::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
- if (!_vm->_isScreenDoubled) {
- ScalpelScreen::blitFrom(src, pt, srcBounds);
- return;
- }
-
- Common::Rect srcRect = srcBounds;
- Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
-
- if (!srcRect.isValidRect() || !clip(srcRect, destRect))
- return;
-
- // Add dirty area remapped to the 640x200 surface
- addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));
-
- // Transfer the area, doubling each pixel
- for (int yp = 0; yp < srcRect.height(); ++yp) {
- const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
- uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);
-
- for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
- *destP = *srcP;
- *(destP + 1) = *srcP;
- *(destP + 640) = *srcP;
- *(destP + 640 + 1) = *srcP;
- }
- }
-}
-
-void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
- bool flipped, int overrideColor) {
- if (!_vm->_isScreenDoubled) {
- ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor);
- return;
- }
-
- Common::Rect drawRect(0, 0, src.w, src.h);
- Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
- // Clip the display area to on-screen
- if (!clip(drawRect, destRect))
- // It's completely off-screen
- return;
-
- if (flipped)
- drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
- src.w - drawRect.left, src.h - drawRect.top);
-
- Common::Point destPt(destRect.left, destRect.top);
- addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2,
- (destPt.y + drawRect.height()) * 2));
-
- assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2);
-
- for (int yp = 0; yp < drawRect.height(); ++yp) {
- const uint16 *srcP = (const uint16 *)src.getBasePtr(
- flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
- uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2);
-
- for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) {
- // RGB 0, 0, 0 -> transparent on 3DO
- if (*srcP) {
- *destP = *srcP;
- *(destP + 1) = *srcP;
- *(destP + 640) = *srcP;
- *(destP + 640 + 1) = *srcP;
- }
-
- srcP = flipped ? srcP - 1 : srcP + 1;
- }
- }
-}
-
-void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) {
- if (_vm->_isScreenDoubled)
- ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color);
- else
- ScalpelScreen::fillRect(r, color);
-}
-
-void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) {
- Events &events = *_vm->_events;
- uint16 *currentScreenBasePtr = (uint16 *)getPixels();
- uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
- uint16 currentScreenPixel = 0;
- uint16 targetScreenPixel = 0;
-
- uint16 currentScreenPixelRed = 0;
- uint16 currentScreenPixelGreen = 0;
- uint16 currentScreenPixelBlue = 0;
-
- uint16 targetScreenPixelRed = 0;
- uint16 targetScreenPixelGreen = 0;
- uint16 targetScreenPixelBlue = 0;
-
- uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
- uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
- uint16 screenX = 0;
- uint16 screenY = 0;
- uint16 pixelsChanged = 0;
-
- clearDirtyRects();
-
- do {
- pixelsChanged = 0;
- uint16 *currentScreenPtr = currentScreenBasePtr;
- uint16 *targetScreenPtr = targetScreenBasePtr;
-
- for (screenY = 0; screenY < screenHeight; screenY++) {
- for (screenX = 0; screenX < screenWidth; screenX++) {
- currentScreenPixel = *currentScreenPtr;
- targetScreenPixel = *targetScreenPtr;
-
- if (currentScreenPixel != targetScreenPixel) {
- // pixel doesn't match, adjust accordingly
- currentScreenPixelRed = currentScreenPixel & 0xF800;
- currentScreenPixelGreen = currentScreenPixel & 0x07E0;
- currentScreenPixelBlue = currentScreenPixel & 0x001F;
- targetScreenPixelRed = targetScreenPixel & 0xF800;
- targetScreenPixelGreen = targetScreenPixel & 0x07E0;
- targetScreenPixelBlue = targetScreenPixel & 0x001F;
-
- if (currentScreenPixelRed != targetScreenPixelRed) {
- if (currentScreenPixelRed < targetScreenPixelRed) {
- currentScreenPixelRed += 0x0800;
- } else {
- currentScreenPixelRed -= 0x0800;
- }
- }
- if (currentScreenPixelGreen != targetScreenPixelGreen) {
- // Adjust +2/-2 because we are running RGB555 at RGB565
- if (currentScreenPixelGreen < targetScreenPixelGreen) {
- currentScreenPixelGreen += 0x0040;
- } else {
- currentScreenPixelGreen -= 0x0040;
- }
- }
- if (currentScreenPixelBlue != targetScreenPixelBlue) {
- if (currentScreenPixelBlue < targetScreenPixelBlue) {
- currentScreenPixelBlue += 0x0001;
- } else {
- currentScreenPixelBlue -= 0x0001;
- }
- }
-
- uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
- *currentScreenPtr = v;
- if (_vm->_isScreenDoubled) {
- *(currentScreenPtr + 1) = v;
- *(currentScreenPtr + 640) = v;
- *(currentScreenPtr + 640 + 1) = v;
- }
-
- pixelsChanged++;
- }
-
- currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
- targetScreenPtr++;
- }
-
- if (_vm->_isScreenDoubled)
- currentScreenPtr += 640;
- }
-
- // Too much considered dirty at the moment
- if (_vm->_isScreenDoubled)
- addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
- else
- addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-
- events.pollEvents();
- events.delay(10 * speed);
- } while ((pixelsChanged) && (!_vm->shouldQuit()));
-}
-
-void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) {
- uint16 *currentScreenPtr = (uint16 *)getPixels();
- uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
- uint16 currentScreenPixel = 0;
-
- uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
- uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
- uint16 screenX = 0;
- uint16 screenY = 0;
-
- uint16 currentScreenPixelRed = 0;
- uint16 currentScreenPixelGreen = 0;
- uint16 currentScreenPixelBlue = 0;
-
- uint16 limitPixelRed = limitColor & 0xF800;
- uint16 limitPixelGreen = limitColor & 0x07E0;
- uint16 limitPixelBlue = limitColor & 0x001F;
-
- for (screenY = 0; screenY < screenHeight; screenY++) {
- for (screenX = 0; screenX < screenWidth; screenX++) {
- currentScreenPixel = *targetScreenPtr;
-
- currentScreenPixelRed = currentScreenPixel & 0xF800;
- currentScreenPixelGreen = currentScreenPixel & 0x07E0;
- currentScreenPixelBlue = currentScreenPixel & 0x001F;
-
- if (currentScreenPixelRed < limitPixelRed)
- currentScreenPixelRed = limitPixelRed;
- if (currentScreenPixelGreen < limitPixelGreen)
- currentScreenPixelGreen = limitPixelGreen;
- if (currentScreenPixelBlue < limitPixelBlue)
- currentScreenPixelBlue = limitPixelBlue;
-
- uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
- *currentScreenPtr = v;
- if (_vm->_isScreenDoubled) {
- *(currentScreenPtr + 1) = v;
- *(currentScreenPtr + 640) = v;
- *(currentScreenPtr + 640 + 1) = v;
- }
-
- currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
- targetScreenPtr++;
- }
-
- if (_vm->_isScreenDoubled)
- currentScreenPtr += 640;
- }
-
- // Too much considered dirty at the moment
- if (_vm->_isScreenDoubled)
- addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
- else
- addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-}
-
-uint16 Scalpel3DOScreen::w() const {
- return _vm->_isScreenDoubled ? _surface.w / 2 : _surface.w;
-}
-
-uint16 Scalpel3DOScreen::h() const {
- return _vm->_isScreenDoubled ? _surface.h / 2 : _surface.h;
-}
-
-void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) {
- Common::Rect srcRect(0, 0, src.w, src.h);
- Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
- addDirtyRect(destRect);
- _surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
-}
-
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_screen.h b/engines/sherlock/scalpel/scalpel_screen.h
index cee33b8c6c..d9be29c8b2 100644
--- a/engines/sherlock/scalpel/scalpel_screen.h
+++ b/engines/sherlock/scalpel/scalpel_screen.h
@@ -61,44 +61,6 @@ public:
void makeField(const Common::Rect &r);
};
-class Scalpel3DOScreen : public ScalpelScreen {
-protected:
- /**
- * Draws a sub-section of a surface at a given position within this surface
- * Overriden for the 3DO to automatically double the size of everything to the underlying 640x400 surface
- */
- virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
- /**
- * Draws a surface at a given position within this surface with transparency
- */
- virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
- int overrideColor);
-public:
- Scalpel3DOScreen(SherlockEngine *vm) : ScalpelScreen(vm) {}
- virtual ~Scalpel3DOScreen() {}
-
- /**
- * Draws a sub-section of a surface at a given position within this surface
- */
- void rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt);
-
- /**
- * Fade backbuffer 1 into screen (3DO RGB!)
- */
- void fadeIntoScreen3DO(int speed);
-
- void blitFrom3DOcolorLimit(uint16 color);
-
- /**
- * Fill a given area of the surface with a given color
- */
- virtual void fillRect(const Common::Rect &r, uint color);
-
- virtual uint16 w() const;
- virtual uint16 h() const;
-};
-
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index 4e7cf5c378..6534f61a87 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -148,23 +148,24 @@ void ScalpelUserInterface::reset() {
void ScalpelUserInterface::drawInterface(int bufferNum) {
Screen &screen = *_vm->_screen;
- const ImageFrame &src = (*_controlPanel)[0];
+ const Graphics::Surface &src = (*_controlPanel)[0]._frame;
int16 x = (!IS_3DO) ? 0 : UI_OFFSET_3DO;
if (bufferNum & 1) {
if (IS_3DO)
screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
- screen._backBuffer1.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
+ screen._backBuffer1.SHtransBlitFrom(src, Common::Point(x, CONTROLS_Y));
}
if (bufferNum & 2) {
if (IS_3DO)
screen._backBuffer2.fillRect(Common::Rect(0, CONTROLS_Y,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
- screen._backBuffer2.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
+ screen._backBuffer2.SHtransBlitFrom(src, Common::Point(x, CONTROLS_Y));
}
if (bufferNum == 3)
- screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
+ screen._backBuffer2.SHfillRect(Common::Rect(0, INFO_LINE,
+ SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10), INFO_BLACK);
}
void ScalpelUserInterface::handleInput() {
@@ -426,7 +427,7 @@ void ScalpelUserInterface::depressButton(int num) {
offsetButton3DO(pt, num);
ImageFrame &frame = (*_controls)[num];
- screen._backBuffer1.transBlitFrom(frame, pt);
+ screen._backBuffer1.SHtransBlitFrom(frame, pt);
screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
@@ -442,7 +443,7 @@ void ScalpelUserInterface::restoreButton(int num) {
events.setCursor(ARROW);
// Restore the UI on the back buffer
- screen._backBuffer1.blitFrom(screen._backBuffer2, pt,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, pt,
Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19));
screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h);
@@ -489,7 +490,7 @@ void ScalpelUserInterface::toggleButton(uint16 num) {
ImageFrame &frame = (*_controls)[num];
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
offsetButton3DO(pt, num);
- screen._backBuffer1.transBlitFrom(frame, pt);
+ screen._backBuffer1.SHtransBlitFrom(frame, pt);
screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
} else {
@@ -501,7 +502,7 @@ void ScalpelUserInterface::toggleButton(uint16 num) {
void ScalpelUserInterface::clearInfo() {
if (_infoFlag) {
- _vm->_screen->vgaBar(Common::Rect(IS_3DO ? 33 : 16, INFO_LINE,
+ _vm->_screen->vgaBar(Common::Rect(IS_3DO ? 33 : 16, INFO_LINE,
SHERLOCK_SCREEN_WIDTH - (IS_3DO ? 33 : 19), INFO_LINE + 10), INFO_BLACK);
_infoFlag = false;
_oldLook = -1;
@@ -605,74 +606,92 @@ void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
// If inventory is active and an item is selected for a Use or Give action
if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) &&
(inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE)) {
- int width1 = 0, width2 = 0;
- int x, width;
+ int width1 = 0, width2 = 0, width3 = 0;
+ int x;
+
if (inv._invMode == INVMODE_USE) {
// Using an object
- x = width = screen.stringWidth("Use ");
+ Common::String useText1 = FIXED(UserInterface_Use);
+ Common::String useText2;
+ Common::String useText3;
- if (temp < 1000 && scene._bgShapes[temp]._aType != PERSON)
- // It's not a person, so make it lowercase
- tempStr.setChar(tolower(tempStr[0]), 0);
+ x = width1 = screen.stringWidth(useText1);
- x += screen.stringWidth(tempStr);
+ if (temp < 1000 && scene._bgShapes[temp]._aType != PERSON) {
+ // It's not a person, so make it lowercase
+ switch (_vm->getLanguage()) {
+ case Common::DE_DEU:
+ case Common::ES_ESP:
+ // don't do this for German + Spanish version
+ break;
+ default:
+ tempStr.setChar(tolower(tempStr[0]), 0);
+ break;
+ }
+ }
// If we're using an inventory object, add in the width
// of the object name and the " on "
if (_selector != -1) {
- width1 = screen.stringWidth(inv[_selector]._name);
- x += width1;
- width2 = screen.stringWidth(" on ");
+ useText2 = inv[_selector]._name;
+ width2 = screen.stringWidth(useText2);
x += width2;
+
+ useText3 = Common::String::format(FIXED(UserInterface_UseOn), tempStr.c_str());
+
+ } else {
+ useText3 = tempStr;
}
+ width3 = screen.stringWidth(useText3);
+ x += width3;
+
// If the line will be too long, keep cutting off characters
// until the string will fit
while (x > 280) {
- x -= screen.charWidth(tempStr.lastChar());
- tempStr.deleteLastChar();
+ x -= screen.charWidth(useText3.lastChar());
+ useText3.deleteLastChar();
}
int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
screen.print(Common::Point(xStart, INFO_LINE + 1),
- INFO_FOREGROUND, "Use ");
+ INFO_FOREGROUND, "%s", useText1.c_str());
if (_selector != -1) {
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
- screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
- INFO_FOREGROUND, " on ");
- screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
+ screen.print(Common::Point(xStart + width1, INFO_LINE + 1),
+ TALK_FOREGROUND, "%s", useText2.c_str());
+ screen.print(Common::Point(xStart + width1 + width2, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", useText3.c_str());
} else {
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
+ screen.print(Common::Point(xStart + width1, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", useText3.c_str());
}
} else if (temp >= 0 && temp < 1000 && _selector != -1 &&
scene._bgShapes[temp]._aType == PERSON) {
+ Common::String giveText1 = FIXED(UserInterface_Give);
+ Common::String giveText2 = inv[_selector]._name;
+ Common::String giveText3 = Common::String::format(FIXED(UserInterface_GiveTo), tempStr.c_str());
+
// Giving an object to a person
- width1 = screen.stringWidth(inv[_selector]._name);
- x = width = screen.stringWidth("Give ");
- x += width1;
- width2 = screen.stringWidth(" to ");
+ x = width1 = screen.stringWidth(giveText1);
+ width2 = screen.stringWidth(giveText2);
x += width2;
- x += screen.stringWidth(tempStr);
+ width3 = screen.stringWidth(giveText3);
+ x += width3;
// Ensure string will fit on-screen
while (x > 280) {
- x -= screen.charWidth(tempStr.lastChar());
- tempStr.deleteLastChar();
+ x -= screen.charWidth(giveText3.lastChar());
+ giveText3.deleteLastChar();
}
int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
screen.print(Common::Point(xStart, INFO_LINE + 1),
- INFO_FOREGROUND, "Give ");
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
- screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
- INFO_FOREGROUND, " to ");
- screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
+ INFO_FOREGROUND, "%s", giveText1.c_str());
+ screen.print(Common::Point(xStart + width1, INFO_LINE + 1),
+ TALK_FOREGROUND, "%s", giveText2.c_str());
+ screen.print(Common::Point(xStart + width1 + width2, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", giveText3.c_str());
}
} else {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempStr.c_str());
@@ -909,7 +928,7 @@ void ScalpelUserInterface::doEnvControl() {
} while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) && moreKeys);
} else if ((found == 5 && events._released) || _key == saves._hotkeyQuit) {
clearWindow();
- screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, saves._fixedTextQuitGameQuestion.c_str());
+ screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, "%s", saves._fixedTextQuitGameQuestion.c_str());
screen.vgaBar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR);
screen.makeButton(Common::Rect(112, CONTROLS_Y, 160, CONTROLS_Y + 10), 136, saves._fixedTextQuitGameYes);
@@ -1254,7 +1273,7 @@ void ScalpelUserInterface::doLookControl() {
// Need to close the window and depress the Look button
Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
offsetButton3DO(pt, 0);
- screen._backBuffer2.blitFrom((*_controls)[0], pt);
+ screen._backBuffer2.SHblitFrom((*_controls)[0], pt);
banishWindow(true);
_windowBounds.top = CONTROLS_Y1;
@@ -1278,14 +1297,14 @@ void ScalpelUserInterface::doLookControl() {
// Looking at an inventory object
// Backup the user interface
Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1);
- tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
+ tempSurface.SHblitFrom(screen._backBuffer2, Common::Point(0, 0),
Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
inv.drawInventory(INVENTORY_DONT_DISPLAY);
banishWindow(true);
// Restore the ui
- screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
+ screen._backBuffer2.SHblitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
_windowBounds.top = CONTROLS_Y1;
_key = _oldKey = _hotkeyLook;
@@ -1869,7 +1888,7 @@ void ScalpelUserInterface::journalControl() {
// Reset the palette
screen.setPalette(screen._cMap);
- screen._backBuffer1.blitFrom(screen._backBuffer2);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2);
scene.updateBackground();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
@@ -1903,9 +1922,9 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
offsetButton3DO(pt, 0);
- tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
- Common::Rect(pt.x, pt.y, pt.x + tempSurface.w(), pt.y + tempSurface.h()));
- screen._backBuffer2.transBlitFrom((*_controls)[0], pt);
+ tempSurface.SHblitFrom(screen._backBuffer2, Common::Point(0, 0),
+ Common::Rect(pt.x, pt.y, pt.x + tempSurface.width(), pt.y + tempSurface.height()));
+ screen._backBuffer2.SHtransBlitFrom((*_controls)[0], pt);
banishWindow(1);
events.setCursor(MAGNIFY);
@@ -1915,7 +1934,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
_menuMode = LOOK_MODE;
events.clearEvents();
- screen._backBuffer2.blitFrom(tempSurface, pt);
+ screen._backBuffer2.SHblitFrom(tempSurface, pt);
} else {
events.setCursor(ARROW);
banishWindow(true);
@@ -2053,9 +2072,9 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
if (slideUp) {
// Gradually slide up the display of the window
- for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
- screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
- Common::Rect(0, 0, bgSurface.w(), idx));
+ for (int idx = 1; idx <= bgSurface.height(); idx += 2) {
+ screen._backBuffer->SHblitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
+ Common::Rect(0, 0, bgSurface.width(), idx));
screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
@@ -2063,21 +2082,21 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
}
} else {
// Gradually slide down the display of the window
- for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
- screen._backBuffer->blitFrom(bgSurface,
- Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
- Common::Rect(0, bgSurface.h() - idx, bgSurface.w(), bgSurface.h()));
- screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(),
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h() + idx));
+ for (int idx = 1; idx <= bgSurface.height(); idx += 2) {
+ screen._backBuffer->SHblitFrom(bgSurface,
+ Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height()),
+ Common::Rect(0, bgSurface.height() - idx, bgSurface.width(), bgSurface.height()));
+ screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height(),
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.height() + idx));
events.delay(10);
}
}
// Final display of the entire window
- screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
- Common::Rect(0, 0, bgSurface.w(), bgSurface.h()));
- screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(), bgSurface.w(), bgSurface.h());
+ screen._backBuffer->SHblitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height()),
+ Common::Rect(0, 0, bgSurface.width(), bgSurface.height()));
+ screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height(), bgSurface.width(), bgSurface.height());
_windowOpen = true;
}
@@ -2088,10 +2107,10 @@ void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
// Extract the window that's been drawn on the back buffer
Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - height);
Common::Rect r(0, height, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r);
+ tempSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), r);
// Remove drawn window with original user interface
- screen._backBuffer1.blitFrom(screen._backBuffer2,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2,
Common::Point(0, height), r);
// Display the window gradually on-screen
@@ -2115,7 +2134,7 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
Common::copy_backward(pSrc, pSrcEnd, pDest);
// Restore lines from the ui in the secondary back buffer
- screen._backBuffer1.blitFrom(screen._backBuffer2,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2,
Common::Point(0, CONTROLS_Y),
Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx));
@@ -2125,14 +2144,14 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
}
// Restore final two old lines
- screen._backBuffer1.blitFrom(screen._backBuffer2,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2,
Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2),
Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2);
} else {
// Restore old area to completely erase window
- screen._backBuffer1.blitFrom(screen._backBuffer2,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2,
Common::Point(0, CONTROLS_Y),
Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
@@ -2152,7 +2171,7 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
}
// Show entire final area
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
}
@@ -2234,7 +2253,7 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
if (scene._goToScene != 1 && !printed && !talk._talkToAbort) {
_infoFlag = true;
clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done...");
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", FIXED(UserInterface_Done));
_menuCounter = 25;
}
}
@@ -2244,9 +2263,9 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
clearInfo();
if (giveMode) {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "No, thank you.");
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", FIXED(UserInterface_NoThankYou));
} else if (fixedTextActionId == kFixedTextAction_Invalid) {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that.");
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", FIXED(UserInterface_YouCantDoThat));
} else {
Common::String errorMessage = fixedText.getActionMessage(fixedTextActionId, 0);
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", errorMessage.c_str());
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 273d26df74..a885057f35 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -217,7 +217,7 @@ void Object::erase() {
Screen &screen = *_vm->_screen;
if (_visage.isLoaded() && !_oldBounds.isEmpty())
- screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+ screen.SHblitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
}
void Object::update() {
@@ -246,9 +246,9 @@ void Object::update() {
_visage.getFrame(s, _frame);
// Display the frame
- _oldBounds = Common::Rect(_position.x, _position.y, _position.x + s.w(), _position.y + s.h());
+ _oldBounds = Common::Rect(_position.x, _position.y, _position.x + s.width(), _position.y + s.height());
_oldBounds.translate(-s._centroid.x, -s._centroid.y);
- screen.transBlitFrom(s, Common::Point(_oldBounds.left, _oldBounds.top));
+ screen.SHtransBlitFrom(s, Common::Point(_oldBounds.left, _oldBounds.top));
}
}
@@ -652,7 +652,7 @@ void Logo::loadBackground() {
screen.setPalette(palette);
// Copy the surface to the screen
- screen.blitFrom(screen._backBuffer1);
+ screen.SHblitFrom(screen._backBuffer1);
}
void Logo::fade(const byte palette[PALETTE_SIZE], int step) {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 6f9ef179a3..78d0cd862c 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -27,6 +27,7 @@
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
#include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
#include "sherlock/tattoo/tattoo.h"
#include "sherlock/tattoo/tattoo_scene.h"
#include "sherlock/tattoo/tattoo_user_interface.h"
@@ -356,7 +357,7 @@ bool Scene::loadScene(const Common::String &filename) {
if (IS_ROSE_TATTOO) {
// Resize the screen if necessary
int fullWidth = SHERLOCK_SCREEN_WIDTH + bgHeader._scrollSize;
- if (screen._backBuffer1.w() != fullWidth) {
+ if (screen._backBuffer1.width() != fullWidth) {
screen._backBuffer1.create(fullWidth, SHERLOCK_SCREEN_HEIGHT);
screen._backBuffer2.create(fullWidth, SHERLOCK_SCREEN_HEIGHT);
}
@@ -649,7 +650,7 @@ bool Scene::loadScene(const Common::String &filename) {
}
// Backup the image and set the palette
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
screen.setPalette(screen._cMap);
delete rrmStream;
@@ -996,12 +997,12 @@ bool Scene::loadScene(const Common::String &filename) {
#if 0
// code to show the background
- screen.blitFrom(screen._backBuffer1);
+ screen.SHblitFrom(screen._backBuffer1);
_vm->_events->wait(10000);
#endif
// Backup the image
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
}
// Handle drawing any on-screen interface
@@ -1236,7 +1237,7 @@ void Scene::transitionToScene() {
// If the scene is capable of scrolling, set the current scroll so that whoever has control
// of the scroll code is in the middle of the screen
- if (screen._backBuffer1.w() > SHERLOCK_SCREEN_WIDTH)
+ if (screen._backBuffer1.width() > SHERLOCK_SCREEN_WIDTH)
people[people._walkControl].centerScreenOnPerson();
for (uint objIdx = 0; objIdx < _bgShapes.size(); ++objIdx) {
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 74da2a80ea..85d47c84dc 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -23,6 +23,8 @@
#include "sherlock/screen.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+#include "sherlock/tattoo/tattoo_screen.h"
#include "common/system.h"
#include "common/util.h"
#include "graphics/palette.h"
@@ -31,17 +33,14 @@ namespace Sherlock {
Screen *Screen::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_RoseTattoo)
- return new Screen(vm);
+ return new Tattoo::TattooScreen(vm);
else if (vm->getPlatform() == Common::kPlatform3DO)
return new Scalpel::Scalpel3DOScreen(vm);
else
return new Scalpel::ScalpelScreen(vm);
}
-Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->getHeight()), _vm(vm),
- _backBuffer1(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
- _backBuffer2(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
- _backBuffer(&_backBuffer1) {
+Screen::Screen(SherlockEngine *vm) : Graphics::Screen(), _vm(vm), _backBuffer(&_backBuffer1) {
_transitionSeed = 1;
_fadeStyle = false;
Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0);
@@ -58,37 +57,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
}
Screen::~Screen() {
- Fonts::free();
-}
-
-void Screen::update() {
- // Merge the dirty rects
- mergeDirtyRects();
-
- // Loop through copying dirty areas to the physical screen
- Common::List<Common::Rect>::iterator i;
- for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
- const Common::Rect &r = *i;
- const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
- g_system->copyRectToScreen(srcP, _surface.pitch, r.left, r.top,
- r.width(), r.height());
- }
-
- // Signal the physical screen to update
- g_system->updateScreen();
- _dirtyRects.clear();
-}
-
-void Screen::makeAllDirty() {
- addDirtyRect(Common::Rect(0, 0, this->w(), this->h()));
-}
-
-void Screen::getPalette(byte palette[PALETTE_SIZE]) {
- g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
-}
-
-void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
- g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
+ Fonts::freeFont();
}
int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) {
@@ -124,7 +93,7 @@ void Screen::fadeToBlack(int speed) {
}
setPalette(tempPalette);
- fillRect(Common::Rect(0, 0, _surface.w, _surface.h), 0);
+ fillRect(Common::Rect(0, 0, this->w, this->h), 0);
}
void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
@@ -136,59 +105,23 @@ void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
setPalette(palette);
}
-void Screen::addDirtyRect(const Common::Rect &r) {
- _dirtyRects.push_back(r);
- assert(r.width() > 0 && r.height() > 0);
-}
-
-void Screen::mergeDirtyRects() {
- Common::List<Common::Rect>::iterator rOuter, rInner;
-
- // Process the dirty rect list to find any rects to merge
- for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
- rInner = rOuter;
- while (++rInner != _dirtyRects.end()) {
-
- if ((*rOuter).intersects(*rInner)) {
- // these two rectangles overlap or
- // are next to each other - merge them
-
- unionRectangle(*rOuter, *rOuter, *rInner);
-
- // remove the inner rect from the list
- _dirtyRects.erase(rInner);
-
- // move back to beginning of list
- rInner = rOuter;
- }
- }
- }
-}
-
-bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
- destRect = src1;
- destRect.extend(src2);
-
- return !destRect.isEmpty();
-}
-
void Screen::randomTransition() {
Events &events = *_vm->_events;
const int TRANSITION_MULTIPLIER = 0x15a4e35;
- _dirtyRects.clear();
+ clearDirtyRects();
assert(IS_SERRATED_SCALPEL);
for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
int offset = _transitionSeed & 0xFFFF;
- if (offset < (this->w() * this->h()))
+ if (offset < (this->width() * this->height()))
*((byte *)getPixels() + offset) = *((const byte *)_backBuffer->getPixels() + offset);
if (idx != 0 && (idx % 300) == 0) {
// Ensure there's a full screen dirty rect for the next frame update
- if (_dirtyRects.empty())
- addDirtyRect(Common::Rect(0, 0, _surface.w, _surface.h));
+ if (!isDirty())
+ addDirtyRect(Common::Rect(0, 0, this->w, this->h));
events.pollEvents();
events.delay(1);
@@ -196,7 +129,7 @@ void Screen::randomTransition() {
}
// Make sure everything has been transferred
- blitFrom(*_backBuffer);
+ SHblitFrom(*_backBuffer);
}
void Screen::verticalTransition() {
@@ -205,13 +138,13 @@ void Screen::verticalTransition() {
byte table[640];
Common::fill(&table[0], &table[640], 0);
- for (int yp = 0; yp < this->h(); ++yp) {
- for (int xp = 0; xp < this->w(); ++xp) {
- int temp = (table[xp] >= (this->h() - 3)) ? this->h() - table[xp] :
+ for (int yp = 0; yp < this->height(); ++yp) {
+ for (int xp = 0; xp < this->width(); ++xp) {
+ int temp = (table[xp] >= (this->height() - 3)) ? this->height() - table[xp] :
_vm->getRandomNumber(3) + 1;
if (temp) {
- blitFrom(_backBuffer1, Common::Point(xp, table[xp]),
+ SHblitFrom(_backBuffer1, Common::Point(xp, table[xp]),
Common::Rect(xp, table[xp], xp + 1, table[xp] + temp));
table[xp] += temp;
}
@@ -223,7 +156,7 @@ void Screen::verticalTransition() {
void Screen::restoreBackground(const Common::Rect &r) {
if (r.width() > 0 && r.height() > 0)
- _backBuffer->blitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
+ _backBuffer->SHblitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
}
void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) {
@@ -254,11 +187,10 @@ void Screen::slamRect(const Common::Rect &r) {
}
if (srcRect.isValidRect())
- blitFrom(*_backBuffer, Common::Point(destRect.left, destRect.top), srcRect);
+ SHblitFrom(*_backBuffer, Common::Point(destRect.left, destRect.top), srcRect);
}
}
-
void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
int16 *width, int16 *height) {
Common::Point imgPos = pt + frame->_offset;
@@ -335,7 +267,7 @@ void Screen::blockMove(const Common::Rect &r) {
}
void Screen::blockMove() {
- blockMove(Common::Rect(0, 0, w(), h()));
+ blockMove(Common::Rect(0, 0, width(), height()));
}
void Screen::print(const Common::Point &pt, uint color, const char *formatStr, ...) {
@@ -351,13 +283,13 @@ void Screen::print(const Common::Point &pt, uint color, const char *formatStr, .
pos.y--; // Font is always drawing one line higher
if (!pos.x)
// Center text horizontally
- pos.x = (this->w() - width) / 2;
+ pos.x = (this->width() - width) / 2;
Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight);
- if (textBounds.right > this->w())
- textBounds.moveTo(this->w() - width, textBounds.top);
- if (textBounds.bottom > this->h())
- textBounds.moveTo(textBounds.left, this->h() - _fontHeight);
+ if (textBounds.right > this->width())
+ textBounds.moveTo(this->width() - width, textBounds.top);
+ if (textBounds.bottom > this->height())
+ textBounds.moveTo(textBounds.left, this->height() - _fontHeight);
// Write out the string at the given position
writeString(str, Common::Point(textBounds.left, textBounds.top), color);
@@ -387,7 +319,8 @@ void Screen::vgaBar(const Common::Rect &r, int color) {
}
void Screen::setDisplayBounds(const Common::Rect &r) {
- _sceneSurface.setPixels(_backBuffer1.getBasePtr(r.left, r.top), r.width(), r.height(), _backBuffer1.getPixelFormat());
+ _sceneSurface.setPixels((byte *)_backBuffer1.getBasePtr(r.left, r.top),
+ r.width(), r.height(), _backBuffer1.format);
_backBuffer = &_sceneSurface;
}
@@ -397,8 +330,8 @@ void Screen::resetDisplayBounds() {
}
Common::Rect Screen::getDisplayBounds() {
- return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w(), _sceneSurface.h()) :
- Common::Rect(0, 0, this->w(), this->h());
+ return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.width(), _sceneSurface.height()) :
+ Common::Rect(0, 0, this->width(), this->height());
}
void Screen::synchronize(Serializer &s) {
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 04a0c1e505..ceeb1297a3 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -25,52 +25,30 @@
#include "common/list.h"
#include "common/rect.h"
+#include "graphics/screen.h"
+#include "sherlock/image_file.h"
#include "sherlock/surface.h"
#include "sherlock/resources.h"
#include "sherlock/saveload.h"
namespace Sherlock {
-#define PALETTE_SIZE 768
-#define PALETTE_COUNT 256
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
#define BG_GREYSCALE_RANGE_END 229
#define BLACK 0
class SherlockEngine;
-class Screen : public Surface {
+class Screen : virtual public Graphics::Screen, virtual public Surface {
private:
- Common::List<Common::Rect> _dirtyRects;
uint32 _transitionSeed;
Surface _sceneSurface;
// Rose Tattoo fields
int _fadeBytesRead, _fadeBytesToRead;
int _oldFadePercent;
-private:
- /**
- * Merges together overlapping dirty areas of the screen
- */
- void mergeDirtyRects();
-
- /**
- * Returns the union of two dirty area rectangles
- */
- bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
protected:
SherlockEngine *_vm;
-
- /**
- * Clear the current dirty rects list
- */
- void clearDirtyRects() { _dirtyRects.clear(); }
-
- /**
- * Adds a rectangle to the list of modified areas of the screen during the
- * current frame
- */
- virtual void addDirtyRect(const Common::Rect &r);
public:
Surface _backBuffer1, _backBuffer2;
Surface *_backBuffer;
@@ -86,26 +64,6 @@ public:
virtual ~Screen();
/**
- * Handles updating any dirty areas of the screen Surface object to the physical screen
- */
- void update();
-
- /**
- * Makes the whole screen dirty
- */
- void makeAllDirty();
-
- /**
- * Return the currently active palette
- */
- void getPalette(byte palette[PALETTE_SIZE]);
-
- /**
- * Set the palette
- */
- void setPalette(const byte palette[PALETTE_SIZE]);
-
- /**
* Fades from the currently active palette to the passed palette
*/
int equalizePalette(const byte palette[PALETTE_SIZE]);
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index b85321c385..d3b2d0cac8 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -63,9 +63,9 @@ enum GameType {
GType_RoseTattoo = 1
};
-#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w()
-#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h()
-#define SHERLOCK_SCENE_WIDTH _vm->_screen->_backBuffer1.w()
+#define SHERLOCK_SCREEN_WIDTH _vm->_screen->width()
+#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->height()
+#define SHERLOCK_SCENE_WIDTH _vm->_screen->_backBuffer1.width()
#define SHERLOCK_SCENE_HEIGHT (IS_SERRATED_SCALPEL ? 138 : 480)
#define SCENES_COUNT (IS_SERRATED_SCALPEL ? 63 : 101)
#define MAX_BGSHAPES (IS_SERRATED_SCALPEL ? 64 : 150)
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 5a9f0c2ec6..e5b1099123 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -120,7 +120,9 @@ byte Sound::decodeSample(byte sample, byte &reference, int16 &scale) {
}
bool Sound::playSound(const Common::String &name, WaitType waitType, int priority, const char *libraryFilename) {
- stopSound();
+ // Scalpel has only a single sound handle, so it must be stopped before starting a new sound
+ if (IS_SERRATED_SCALPEL)
+ stopSound();
Common::String filename = formFilename(name);
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index b7fc76325c..46304e1b2f 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -21,245 +21,24 @@
*/
#include "sherlock/surface.h"
-#include "sherlock/sherlock.h"
-#include "sherlock/resources.h"
-#include "common/system.h"
-#include "graphics/palette.h"
+#include "sherlock/fonts.h"
namespace Sherlock {
-Surface::Surface(uint16 width, uint16 height) : Fonts(), _freePixels(true) {
- create(width, height);
-}
-
-Surface::Surface() : Fonts(), _freePixels(false) {
-}
-
-Surface::~Surface() {
- if (_freePixels)
- _surface.free();
-}
-
-void Surface::create(uint16 width, uint16 height) {
- if (_freePixels)
- _surface.free();
-
- if (_vm->getPlatform() == Common::kPlatform3DO) {
- _surface.create(width, height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- } else {
- _surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- }
- _freePixels = true;
-}
-
-Graphics::PixelFormat Surface::getPixelFormat() {
- return _surface.format;
-}
-
-void Surface::blitFrom(const Surface &src) {
- blitFrom(src, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const ImageFrame &src) {
- blitFrom(src._frame, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src) {
- blitFrom(src, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const Surface &src, const Common::Point &pt) {
- blitFrom(src, pt, Common::Rect(0, 0, src._surface.w, src._surface.h));
-}
-
-void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt) {
- blitFrom(src._frame, pt, Common::Rect(0, 0, src._frame.w, src._frame.h));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) {
- blitFrom(src, pt, Common::Rect(0, 0, src.w, src.h));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
- Common::Rect srcRect = srcBounds;
- Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
-
- if (srcRect.isValidRect() && clip(srcRect, destRect)) {
- // Surface is at least partially or completely on-screen
- addDirtyRect(destRect);
- _surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
- }
-}
-
-void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds) {
- blitFrom(src._frame, pt, srcBounds);
-}
-
-void Surface::blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
- blitFrom(src._surface, pt, srcBounds);
-}
-
-void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt,
- bool flipped, int overrideColor, int scaleVal) {
- Common::Point drawPt(pt.x + src.sDrawXOffset(scaleVal), pt.y + src.sDrawYOffset(scaleVal));
- transBlitFrom(src._frame, drawPt, flipped, overrideColor, scaleVal);
-}
-
-void Surface::transBlitFrom(const Surface &src, const Common::Point &pt,
- bool flipped, int overrideColor, int scaleVal) {
- const Graphics::Surface &s = src._surface;
- transBlitFrom(s, pt, flipped, overrideColor, scaleVal);
-}
-
-void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
- bool flipped, int overrideColor, int scaleVal) {
- if (scaleVal == SCALE_THRESHOLD) {
- transBlitFromUnscaled(src, pt, flipped, overrideColor);
- return;
- }
-
- int destWidth = src.w * SCALE_THRESHOLD / scaleVal;
- int destHeight = src.h * SCALE_THRESHOLD / scaleVal;
-
- // Loop through drawing output lines
- for (int destY = pt.y, scaleYCtr = 0; destY < (pt.y + destHeight); ++destY, scaleYCtr += scaleVal) {
- if (destY < 0 || destY >= this->h())
- continue;
- const byte *srcLine = (const byte *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
- byte *destLine = (byte *)getBasePtr(pt.x, destY);
-
- // Loop through drawing individual rows
- for (int xCtr = 0, scaleXCtr = 0; xCtr < destWidth; ++xCtr, scaleXCtr += scaleVal) {
- int destX = pt.x + xCtr;
- if (destX < 0 || destX >= this->w())
- continue;
-
- byte srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD];
- if (srcVal != TRANSPARENCY)
- destLine[xCtr] = srcVal;
- }
- }
-
- // Mark the affected area
- addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + destWidth, pt.y + destHeight));
-}
-
-void Surface::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
- bool flipped, int overrideColor) {
- Common::Rect drawRect(0, 0, src.w, src.h);
- Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
- // Clip the display area to on-screen
- if (!clip(drawRect, destRect))
- // It's completely off-screen
- return;
-
- if (flipped)
- drawRect = Common::Rect(src.w - drawRect.right, drawRect.top,
- src.w - drawRect.left, drawRect.bottom);
-
- Common::Point destPt(destRect.left, destRect.top);
- addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(),
- destPt.y + drawRect.height()));
-
- switch (src.format.bytesPerPixel) {
- case 1:
- // 8-bit palettized: Draw loop
- assert(_surface.format.bytesPerPixel == 1); // Security check
- for (int yp = 0; yp < drawRect.height(); ++yp) {
- const byte *srcP = (const byte *)src.getBasePtr(
- flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
- byte *destP = (byte *)getBasePtr(destPt.x, destPt.y + yp);
-
- for (int xp = 0; xp < drawRect.width(); ++xp, ++destP) {
- if (*srcP != TRANSPARENCY)
- *destP = overrideColor ? overrideColor : *srcP;
-
- srcP = flipped ? srcP - 1 : srcP + 1;
- }
- }
- break;
- case 2:
- // 3DO 15-bit RGB565: Draw loop
- assert(_surface.format.bytesPerPixel == 2); // Security check
- for (int yp = 0; yp < drawRect.height(); ++yp) {
- const uint16 *srcP = (const uint16 *)src.getBasePtr(
- flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
- uint16 *destP = (uint16 *)getBasePtr(destPt.x, destPt.y + yp);
-
- for (int xp = 0; xp < drawRect.width(); ++xp, ++destP) {
- if (*srcP) // RGB 0, 0, 0 -> transparent on 3DO
- *destP = *srcP; // overrideColor ? overrideColor : *srcP;
-
- srcP = flipped ? srcP - 1 : srcP + 1;
- }
- }
- break;
- default:
- error("Surface: unsupported bytesperpixel");
- break;
- }
+Surface::Surface() : Graphics::ManagedSurface(), Fonts() {
}
-void Surface::fillRect(int x1, int y1, int x2, int y2, uint color) {
- fillRect(Common::Rect(x1, y1, x2, y2), color);
-}
-
-void Surface::fillRect(const Common::Rect &r, uint color) {
- _surface.fillRect(r, color);
- addDirtyRect(r);
-}
-
-void Surface::fill(uint color) {
- fillRect(Common::Rect(_surface.w, _surface.h), color);
-}
-
-bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
- if (destBounds.left >= w() || destBounds.top >= h() ||
- destBounds.right <= 0 || destBounds.bottom <= 0)
- return false;
-
- // Clip the bounds if necessary to fit on-screen
- if (destBounds.right > w()) {
- srcBounds.right -= destBounds.right - w();
- destBounds.right = w();
- }
-
- if (destBounds.bottom > h()) {
- srcBounds.bottom -= destBounds.bottom - h();
- destBounds.bottom = h();
- }
-
- if (destBounds.top < 0) {
- srcBounds.top += -destBounds.top;
- destBounds.top = 0;
- }
-
- if (destBounds.left < 0) {
- srcBounds.left += -destBounds.left;
- destBounds.left = 0;
- }
-
- return true;
-}
-
-void Surface::clear() {
- fillRect(Common::Rect(0, 0, w(), h()), 0);
-}
-
-void Surface::free() {
- if (_freePixels) {
- _surface.free();
- _freePixels = false;
- }
+Surface::Surface(int width, int height) : Graphics::ManagedSurface(width, height),
+ Fonts() {
+ create(width, height);
}
-void Surface::setPixels(byte *pixels, int width, int height, Graphics::PixelFormat pixelFormat) {
- _surface.format = pixelFormat;
- _surface.w = width;
- _surface.h = height;
- _surface.pitch = width * pixelFormat.bytesPerPixel;
- _surface.setPixels(pixels);
+void Surface::setPixels(byte *pixelsPtr, int sizeX, int sizeY, const Graphics::PixelFormat &pixFormat) {
+ Graphics::ManagedSurface::setPixels(pixelsPtr);
+ this->format = pixFormat;
+ this->w = sizeX;
+ this->h = sizeY;
+ this->pitch = sizeX * pixFormat.bytesPerPixel;
}
void Surface::writeString(const Common::String &str, const Common::Point &pt, uint overrideColor) {
@@ -278,4 +57,21 @@ void Surface::writeFancyString(const Common::String &str, const Common::Point &p
writeString(str, Common::Point(pt.x + 1, pt.y + 1), overrideColor2);
}
+void Surface::SHtransBlitFrom(const ImageFrame &src, const Common::Point &pt,
+ bool flipped, int overrideColor, int scaleVal) {
+ Common::Point drawPt(pt.x + src.sDrawXOffset(scaleVal), pt.y + src.sDrawYOffset(scaleVal));
+ SHtransBlitFrom(src._frame, drawPt, flipped, overrideColor, scaleVal);
+}
+
+void Surface::SHtransBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
+ bool flipped, int overrideColor, int scaleVal) {
+ Common::Rect srcRect(0, 0, src.w, src.h);
+ Common::Rect destRect(pt.x, pt.y, pt.x + src.w * SCALE_THRESHOLD / scaleVal,
+ pt.y + src.h * SCALE_THRESHOLD / scaleVal);
+
+ Graphics::ManagedSurface::transBlitFrom(src, srcRect, destRect, TRANSPARENCY,
+ flipped, overrideColor);
+}
+
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index 378c9be9cd..648b121852 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -20,165 +20,101 @@
*
*/
-#ifndef SHERLOCK_GRAPHICS_H
-#define SHERLOCK_GRAPHICS_H
+#ifndef SHERLOCK_SURFACE_H
+#define SHERLOCK_SURFACE_H
#include "common/rect.h"
#include "common/platform.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
#include "sherlock/fonts.h"
+#include "sherlock/image_file.h"
namespace Sherlock {
#define SCALE_THRESHOLD 0x100
#define TRANSPARENCY 255
-struct ImageFrame;
-
-class Surface: public Fonts {
-private:
- bool _freePixels;
-
- /**
- * Copy a surface into this one
- */
- void blitFrom(const Graphics::Surface &src);
-protected:
- Graphics::Surface _surface;
-
- /**
- * Clips the given source bounds so the passed destBounds will be entirely on-screen
- */
- bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
-
- /**
- * Base method stub for signalling dirty rect areas
- */
- virtual void addDirtyRect(const Common::Rect &r) {}
-
- /**
- * Draws a sub-section of a surface at a given position within this surface
- */
- virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
+/**
+ * Implements a descendent surface that combines both a managed surface and the font
+ * drawing code. It also introduces a series of drawing method stubs that the 3DO
+ * Serrated Scalpel screen overrides to implement sprite doubling
+ */
+class Surface: virtual public Graphics::ManagedSurface, public Fonts {
+public:
/**
- * Draws a surface at a given position within this surface with transparency
+ * Constructor
*/
- virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
- int overrideColor);
-public:
- Surface(uint16 width, uint16 height);
Surface();
- virtual ~Surface();
-
+
/**
- * Sets up an internal surface with the specified dimensions that will be automatically freed
- * when the surface object is destroyed
+ * Constructor
*/
- void create(uint16 width, uint16 height);
-
- Graphics::PixelFormat getPixelFormat();
+ Surface(int width, int height);
/**
- * Copy a surface into this one
+ * Set the surface details
*/
- void blitFrom(const Surface &src);
+ void setPixels(byte *pixelsPtr, int sizeX, int sizeY, const Graphics::PixelFormat &pixFormat);
/**
- * Copy an image frame into this surface
+ * Draws a surface on this surface
*/
- void blitFrom(const ImageFrame &src);
+ virtual void SHblitFrom(const Graphics::Surface &src) {
+ Graphics::ManagedSurface::blitFrom(src);
+ }
/**
* Draws a surface at a given position within this surface
*/
- void blitFrom(const Surface &src, const Common::Point &pt);
-
- /**
- * Copy an image frame onto this surface at a given position
- */
- void blitFrom(const ImageFrame &src, const Common::Point &pt);
+ virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &destPos) {
+ Graphics::ManagedSurface::blitFrom(src, destPos);
+ }
/**
* Draws a sub-section of a surface at a given position within this surface
*/
- void blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
- /**
- * Copy a sub-area of a source image frame into this surface at a given position
- */
- void blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
- /**
- * Draws a surface at a given position within this surface
- */
- void blitFrom(const Graphics::Surface &src, const Common::Point &pt);
+ virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &destPos, const Common::Rect &srcBounds) {
+ Graphics::ManagedSurface::blitFrom(src, srcBounds, destPos);
+ }
/**
* Draws an image frame at a given position within this surface with transparency
*/
- void transBlitFrom(const ImageFrame &src, const Common::Point &pt,
- bool flipped = false, int overrideColor = 0, int scaleVal = 256);
-
- /**
- * Draws a surface at a given position within this surface with transparency
- */
- void transBlitFrom(const Surface &src, const Common::Point &pt,
- bool flipped = false, int overrideColor = 0, int scaleVal = 256);
+ void SHtransBlitFrom(const ImageFrame &src, const Common::Point &pt,
+ bool flipped = false, int overrideColor = 0, int scaleVal = SCALE_THRESHOLD);
/**
- * Draws a surface at a given position within this surface with transparency
+ * Draws an image frame at a given position within this surface with transparency
*/
- void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
- bool flipped = false, int overrideColor = 0, int scaleVal = 256);
+ void SHtransBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
+ bool flipped = false, int overrideColor = 0, int scaleVal = SCALE_THRESHOLD);
/**
* Fill a given area of the surface with a given color
*/
- void fillRect(int x1, int y1, int x2, int y2, uint color);
-
- /**
- * Fill a given area of the surface with a given color
- */
- virtual void fillRect(const Common::Rect &r, uint color);
-
- void fill(uint color);
-
- /**
- * Clear the surface
- */
- void clear();
+ virtual void SHfillRect(const Common::Rect &r, uint color) {
+ Graphics::ManagedSurface::fillRect(r, color);
+ }
/**
- * Free the underlying surface
+ * Return the width of the surface
*/
- void free();
-
+ virtual uint16 width() const { return this->w; }
+
/**
- * Returns true if the surface is empty
+ * Return the height of the surface
*/
- bool empty() const { return _surface.getPixels() == nullptr; }
+ virtual uint16 height() const { return this->h; }
/**
- * Set the pixels for the surface to an existing data block
+ * Draws the given string into the back buffer using the images stored in _font
*/
- void setPixels(byte *pixels, int width, int height, Graphics::PixelFormat format);
-
+ void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
+
/**
- * Draws the given string into the back buffer using the images stored in _font
+ * Draws a fancy version of the given string at the given position
*/
- virtual void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
void writeFancyString(const Common::String &str, const Common::Point &pt, uint overrideColor1, uint overrideColor2);
-
- inline virtual uint16 w() const { return _surface.w; }
- inline virtual uint16 h() const { return _surface.h; }
- inline const byte *getPixels() const { return (const byte *)_surface.getPixels(); }
- inline byte *getPixels() { return (byte *)_surface.getPixels(); }
- inline byte *getBasePtr(int x, int y) { return (byte *)_surface.getBasePtr(x, y); }
- inline const byte *getBasePtr(int x, int y) const { return (const byte *)_surface.getBasePtr(x, y); }
- inline Graphics::Surface &getRawSurface() { return _surface; }
- inline void hLine(int x, int y, int x2, uint color) { _surface.hLine(x, y, x2, color); }
- inline void vLine(int x, int y, int y2, uint color) { _surface.vLine(x, y, y2, color); }
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_darts.cpp b/engines/sherlock/tattoo/tattoo_darts.cpp
index 512358933d..cbc3ea1fe8 100644
--- a/engines/sherlock/tattoo/tattoo_darts.cpp
+++ b/engines/sherlock/tattoo/tattoo_darts.cpp
@@ -83,7 +83,9 @@ void Darts::playDarts(GameType gameType) {
int numHits = 0;
bool gameOver = false;
bool done = false;
- const char *const NUM_HITS_STR[3] = { "a", FIXED(Double), FIXED(Triple) };
+
+ // Set the game mode
+ _gameType = gameType;
screen.setFont(7);
_spacing = screen.fontHeight() + 2;
@@ -161,51 +163,84 @@ void Darts::playDarts(GameType gameType) {
// Show scores
showStatus(playerNum);
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, "%s # %d", FIXED(Dart), idx + 1);
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, FIXED(DartsCurrentDart), idx + 1);
if (_gameType == GAME_301) {
- if (_vm->getLanguage() == Common::FR_FRA)
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0,
- "%s %s: %d", FIXED(Scored), FIXED(Points), lastDart);
- else
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0,
- "%s %d %s", FIXED(Scored), lastDart, FIXED(Points));
+ // "Scored x points"
+ Common::String scoredPoints;
+
+ // original treated 1 point and multiple points the same. Wrote "Scored 1 points"
+ if (lastDart == 1) {
+ scoredPoints = Common::String::format(FIXED(DartsScoredPoint), lastDart);
+ } else {
+ scoredPoints = Common::String::format(FIXED(DartsScoredPoints), lastDart);
+ }
+
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s", scoredPoints.c_str());
} else {
- if (lastDart != 25)
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0,
- "%s %s %d", FIXED(Hit), NUM_HITS_STR[numHits - 1], lastDart);
- else
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0,
- "%s %s %s", FIXED(Hit), NUM_HITS_STR[numHits - 1], FIXED(Bullseye));
+ Common::String hitText;
+
+ if (lastDart != 25) {
+ // Regular hit
+ switch (numHits) {
+ case 1: // "Hit a X"
+ hitText = Common::String::format(FIXED(DartsHitSingle), lastDart);
+ break;
+ case 2: // "Hit double X"
+ hitText = Common::String::format(FIXED(DartsHitDouble), lastDart);
+ break;
+ case 3: // "Hit triple X"
+ hitText = Common::String::format(FIXED(DartsHitTriple), lastDart);
+ break;
+ default:
+ break;
+ }
+ } else {
+ // Bullseye
+ switch (numHits) {
+ case 1:
+ hitText = Common::String(FIXED(DartsHitSingleBullseye));
+ break;
+ case 2:
+ hitText = Common::String(FIXED(DartsHitDoubleBullseye));
+ break;
+ case 3:
+ hitText = Common::String(FIXED(DartsHitTripleBullseye));
+ break;
+ default:
+ break;
+ }
+ }
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s", hitText.c_str());
}
if (score != 0 && playerNum == 0 && !gameOver)
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 3), 0,
- "%s", FIXED(PressAKey));
+ "%s", FIXED(DartsPressKey));
if (gameOver) {
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 3),
- 0, "%s", FIXED(GameOver));
+ 0, "%s", FIXED(DartsGameOver));
if (playerNum == 0) {
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 4), 0,
- "%s %s", FIXED(Holmes), FIXED(Wins));
+ FIXED(DartsWins), FIXED(DartsPlayerHolmes));
_vm->setFlagsDirect(531);
} else {
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 4), 0,
- "%s %s!", _opponent.c_str(), FIXED(Wins));
+ FIXED(DartsWins), _opponent.c_str());
_vm->setFlagsDirect(530);
}
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 5), 0,
- "%s", FIXED(PressAKey));
+ "%s", FIXED(DartsPressKey));
done = true;
idx = 10;
} else if (_gameType == GAME_301 && score < 0) {
screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 2), 0,
- "%s!", FIXED(Busted));
+ "%s!", FIXED(DartsBusted));
// End turn
idx = 10;
@@ -224,13 +259,19 @@ void Darts::playDarts(GameType gameType) {
done = true;
break;
}
+ // Wait for keypress
+ do {
+ events.pollEventsAndWait();
+ events.setButtonState();
+ } while (!_vm->shouldQuit() && !events.kbHit() && !events._pressed);
} else {
- events.wait(20);
+ events.wait(40);
}
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+ // Clears the status part of the board
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
- screen.blitFrom(screen._backBuffer1);
+ screen.SHblitFrom(screen._backBuffer1);
}
playerNum ^= 1;
@@ -238,9 +279,9 @@ void Darts::playDarts(GameType gameType) {
++_roundNum;
if (!done) {
- screen._backBuffer2.blitFrom((*_dartBoard)[0], Common::Point(0, 0));
- screen._backBuffer1.blitFrom(screen._backBuffer2);
- screen.blitFrom(screen._backBuffer2);
+ screen._backBuffer2.SHblitFrom((*_dartBoard)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2);
+ screen.SHblitFrom(screen._backBuffer2);
}
}
@@ -303,7 +344,7 @@ void Darts::initDarts() {
}
}
- _opponent = FIXED(Jock);
+ _opponent = FIXED(DartsPlayerJock);
}
void Darts::loadDarts() {
@@ -327,9 +368,9 @@ void Darts::loadDarts() {
delete stream;
// Load the initial background
- screen._backBuffer1.blitFrom((*_dartBoard)[0], Common::Point(0, 0));
- screen._backBuffer2.blitFrom(screen._backBuffer1);
- screen.blitFrom(screen._backBuffer1);
+ screen._backBuffer1.SHblitFrom((*_dartBoard)[0], Common::Point(0, 0));
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
+ screen.SHblitFrom(screen._backBuffer1);
}
void Darts::closeDarts() {
@@ -346,7 +387,7 @@ void Darts::showNames(int playerNum) {
byte color;
color = playerNum == 0 ? PLAYER_COLOR : DART_COLOR_FORE;
- screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), 0, "%s", FIXED(Holmes));
+ screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), 0, "%s", FIXED(DartsPlayerHolmes));
screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + _spacing + 1,
STATUS_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color);
screen.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + _spacing + 1,
@@ -359,14 +400,14 @@ void Darts::showNames(int playerNum) {
screen.fillRect(Common::Rect(STATUS2_INFO_X, STATUS_INFO_Y + _spacing + 1,
STATUS2_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color);
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
}
void Darts::showStatus(int playerNum) {
Screen &screen = *_vm->_screen;
- const char *const CRICKET_SCORE_NAME[7] = { "20", "19", "18", "17", "16", "15", FIXED(Bull) };
+ const char *const CRICKET_SCORE_NAME[7] = { "20", "19", "18", "17", "16", "15", FIXED(DartsBull) };
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH,
STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10));
screen.print(Common::Point(STATUS_INFO_X + 30, STATUS_INFO_Y + _spacing + 4), 0, "%d", _score1);
@@ -374,10 +415,15 @@ void Darts::showStatus(int playerNum) {
screen.print(Common::Point(STATUS2_INFO_X + 30, STATUS_INFO_Y + _spacing + 4), 0, "%d", _score2);
int temp = (_gameType == GAME_CRICKET) ? STATUS_INFO_Y + 10 * _spacing + 5 : STATUS_INFO_Y + 55;
- screen.print(Common::Point(STATUS_INFO_X, temp), 0, "%s: %d", FIXED(Round), _roundNum);
+
+ // "Round: x"
+ Common::String dartsRoundStatus = Common::String::format(FIXED(DartsCurrentRound), _roundNum);
+ screen.print(Common::Point(STATUS_INFO_X, temp), 0, "%s", dartsRoundStatus.c_str());
if (_gameType == GAME_301) {
- screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 75), 0, "%s: %d", FIXED(TurnTotal), _roundScore);
+ // "Turn Total: x"
+ Common::String dartsTotalPoints = Common::String::format(FIXED(DartsCurrentTotalPoints), _roundScore);
+ screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 75), 0, "%s", dartsTotalPoints.c_str());
} else {
// Show cricket scores
for (int x = 0; x < 7; ++x) {
@@ -402,7 +448,7 @@ void Darts::showStatus(int playerNum) {
}
}
- screen.blitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+ screen.SHblitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH,
STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10));
}
@@ -412,7 +458,7 @@ void Darts::erasePowerBars() {
// Erase the old power bars and replace them with empty ones
screen._backBuffer1.fillRect(Common::Rect(DART_BAR_VX, DART_HEIGHT_Y, DART_BAR_VX + 9, DART_HEIGHT_Y + DART_BAR_SIZE), 0);
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[0], Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1));
screen.slamArea(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, 10, DART_BAR_SIZE + 2);
}
@@ -452,7 +498,7 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int or
}
screen._backBuffer1.hLine(pt.x, pt.y + DART_BAR_SIZE- 1 - idx, pt.x + 8, color);
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(pt.x - 1, pt.y - 1));
+ screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[0], Common::Point(pt.x - 1, pt.y - 1));
screen.slamArea(pt.x, pt.y + DART_BAR_SIZE - 1 - idx, 8, 2);
if (!(idx % 8))
@@ -499,7 +545,7 @@ int Darts::drawHand(int goToPower, int computer) {
break;
}
- screen._backBuffer1.transBlitFrom((*hands)[0], pt);
+ screen._backBuffer1.SHtransBlitFrom((*hands)[0], pt);
screen.slamArea(pt.x - 1, pt.y, _handSize.x + 1, _handSize.y);
screen.restoreBackground(Common::Rect(pt.x, pt.y, pt.x + _handSize.x, pt.y + _handSize.y));
@@ -586,7 +632,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
_handSize.y = hands[idx]._offset.y + hands[idx]._height;
int handCy = SHERLOCK_SCREEN_HEIGHT - _handSize.y;
- screen._backBuffer1.transBlitFrom(hands[idx], Common::Point(_handX, handCy));
+ screen._backBuffer1.SHtransBlitFrom(hands[idx], Common::Point(_handX, handCy));
screen.slamArea(_handX, handCy, _handSize.x + 1, _handSize.y);
screen.slamArea(handOCx, handOCy, handOldxSize, handOldySize);
screen.restoreBackground(Common::Rect(_handX, handCy, _handX + _handSize.x, handCy + _handSize.y));
@@ -608,7 +654,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
// Draw dart
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], drawPos);
+ screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], drawPos);
if (drawPos.x < 0) {
xSize += drawPos.x;
@@ -630,7 +676,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
// Flush the erased dart area
screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
oldDrawPos.x = drawPos.x;
@@ -651,7 +697,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
if (oldDrawPos.x != -1)
screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
cx = dartPos.x;
@@ -677,7 +723,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
ocx = drawPos.x = cx - (*_dartGraphics)[dartNum]._width / 2;
ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawPos.x, drawPos.y));
+ screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawPos.x, drawPos.y));
if (drawPos.x < 0) {
xSize += drawPos.x;
@@ -699,7 +745,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
if (idx != 23)
- screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, drawPos,
Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize)); // erase dart
events.wait(1);
@@ -716,8 +762,8 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
ySize = (*_dartGraphics)[dartNum]._height;
// Draw final dart on the board
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
- screen._backBuffer2.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
+ screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
+ screen._backBuffer2.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
screen.slamArea(ocx, ocy, xSize, ySize);
}
@@ -887,13 +933,16 @@ int Darts::throwDart(int dartNum, int computer) {
events.clearEvents();
erasePowerBars();
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, "%s # %d", FIXED(Dart), dartNum);
+
+ // "Dart # x"
+ Common::String currentDart = Common::String::format(FIXED(DartsCurrentDart), dartNum);
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, "%s", currentDart.c_str());
drawDartsLeft(dartNum, computer);
if (!computer) {
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s", FIXED(HitAKey));
- screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 2), 0, "%s", FIXED(ToStart));
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s", FIXED(DartsStartPressKey1));
+ screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 2), 0, "%s", FIXED(DartsStartPressKey2));
}
if (!computer) {
@@ -907,9 +956,9 @@ int Darts::throwDart(int dartNum, int computer) {
}
drawDartsLeft(dartNum + 1, computer);
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
- screen.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+ screen.SHblitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
if (computer) {
@@ -931,7 +980,7 @@ int Darts::throwDart(int dartNum, int computer) {
height = 101 - height;
// Copy power bars to the secondary back buffer
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1),
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1),
Common::Rect(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, DART_BAR_VX - 1 + 10,
DART_HEIGHT_Y - 1 + DART_BAR_SIZE + 2));
@@ -975,14 +1024,14 @@ void Darts::drawDartsLeft(int dartNum, int computer) {
const int DART_X2[3] = { 393, 441, 502 };
const int DART_Y2[3] = { 373, 373, 373 };
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_X1[0], DART_Y1[0]),
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_X1[0], DART_Y1[0]),
Common::Rect(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
for (int idx = 2; idx >= dartNum - 1; --idx) {
if (computer)
- screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx + 3], Common::Point(DART_X2[idx], DART_Y2[idx]));
+ screen._backBuffer1.SHtransBlitFrom((*_dartsLeft)[idx + 3], Common::Point(DART_X2[idx], DART_Y2[idx]));
else
- screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx], Common::Point(DART_X1[idx], DART_Y1[idx]));
+ screen._backBuffer1.SHtransBlitFrom((*_dartsLeft)[idx], Common::Point(DART_X1[idx], DART_Y1[idx]));
}
screen.slamArea(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH - DART_X1[0], SHERLOCK_SCREEN_HEIGHT - DART_Y1[0]);
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.cpp b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
index 38acd78aba..e41cb1f5eb 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.cpp
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
@@ -66,25 +66,27 @@ static const char *const fixedTextEN[] = {
"Search Backwards",
"Search Forwards",
"Text Not Found !",
-
+ // Darts
"Holmes",
"Jock",
"Bull",
- "Round",
- "Turn Total",
- "Dart",
- "to start",
+ "Round: %d",
+ "Turn Total: %d",
+ "Dart # %d",
"Hit a key",
+ "To start",
"Press a key",
- "bullseye", // ??
- "GAME OVER",
- "BUSTED",
- "Wins",
- "Scored",
- "points",
- "Hit %s %d",
- "Double",
- "Triple",
+ "GAME OVER!",
+ "BUSTED!",
+ "%s Wins",
+ "Scored %d point", // original: treated 1 point and multiple points the same ("Scored 1 points")
+ "Scored %d points",
+ "Hit a %d",
+ "Hit double %d",
+ "Hit triple %d",
+ "Hit a bullseye",
+ "Hit double bullseye",
+ "Hit triple bullseye",
"Apply",
"Water",
@@ -106,6 +108,8 @@ static const char *const fixedTextEN[] = {
"No",
"Enter Password",
"Going East", // correct password, was not and should not to be translated
+ "Watson's Journal",
+ "Journal saved as journal.txt",
// SH2: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -235,7 +239,7 @@ static const char *const fixedTextDE[] = {
"Tagebuch",
"Tasche",
"Optionen",
- "L\224osen",
+ "L\224sen",
"mit",
"Keine Wirkung...",
"Diese Person wei\341 im Augenblick nichts zu berichten.",
@@ -243,31 +247,33 @@ static const char *const fixedTextDE[] = {
"Seite %d",
"Schlie\341en",
- "Lessen", // <--
- "In Datei sichern",
+ "Durchsuchen", // original: "Lessen"
+ "In Datei sichern", // original: "Speichern"
"Suche abbrechen",
"R\201ckw\204rts suchen ",
- "Vorwarts suchen ",
+ "Vorw\204rts suchen ",
"Text nicht gefunden",
-
+ // Darts
"Holmes",
"Jock",
"Bull",
"Runde: %d",
"Gesamt: %d",
"Pfeil # %d",
- "zum Starten",
"Taste dr\201cken",
+ "zum Starten",
"Taste dr\201cken",
- "Bullseye", // ??
"SPIEL BEENDET!",
"VERLOREN!",
- "Gewinnt!", // "Holmes Gewinnt!", "%s Gewinnt!"
+ "%s gewinnt!", // "Holmes Gewinnt!", "%s Gewinnt!", original: "%s Gewinnt!"
+ "Erzielte %d Punkt", // original: treated 1 point and multiple points the same ("Scored 1 points")
"Erzielte %d Punkte",
- "Punkte", // ??
- "Treffer %s %d",
- "Doppel",
- "Dreifach",
+ "%d getroffen", // original: "Treffer %s %d"
+ "Doppel %d getroffen", // original: see above
+ "Dreifach %d getroffen", // original: see above
+ "Bullseye getroffen",
+ "Doppel Bullseye getroffen",
+ "Dreifach Bullseye getroffen",
"Benutze",
"Wasser",
@@ -289,6 +295,8 @@ static const char *const fixedTextDE[] = {
"Nein",
"Pa\341wort eingeben",
"Going East", // correct password, was not and should not to be translated
+ "Watsons Tagebuch",
+ "Journal gespeichert als journal.txt",
// SH2: People names
"Sherlock Holmes", // note: People names were not translated in the German interpreter
"Dr. Watson",
@@ -426,31 +434,33 @@ static const char *const fixedTextFR[] = {
"Page %d",
"Fermer",
- "Lessen", // <--
+ "Rechercher",
"Sauvegarder",
"Annuler ",
"Chercher avant",
"Chercher apr\212s",
"Texte introuvable !",
-
+ // Darts
"Holmes",
"Jock",
"Bull",
"Tour: %d",
"Total: %d",
"Fl\202chette # %d",
- "pour commencer",
"Appuyez sur C",
+ "pour commencer",
"Appuyez sur C",
- "Bullseye", // ??
"FIN DE LA PARTIE!", // original: "Fin de la partie!"
"FIASCO!",
- "Gagnant!", // "Holmes Gagnant!", "%s Gagnant!"
- "Total des points: %d",
- "Punkte", // ??
- "Treffer %s %d",
- "double",
- "triple",
+ "%s a gagn\202!", // "Holmes Gagnant!", "%s Gagnant!"
+ "Rapporte %d point", // original: treated 1 point and multiple points the same ("Scored 1 points")
+ "Rapporte %d points", // original: Total des points: %d",
+ "Touche un %d", // original: ???
+ "Touche double %d",
+ "Touche triple %d",
+ "Touche le Bullseye",
+ "Touche double Bullseye",
+ "Touche triple Bullseye",
"Mouillez",
"Puis",
@@ -472,6 +482,8 @@ static const char *const fixedTextFR[] = {
"Non",
"Entrez le mot de passe",
"Going East", // correct password, was not and should not to be translated
+ "Journal de Watson",
+ "Journal enregistree comme journal.txt",
// SH2: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -610,7 +622,7 @@ static const char *const fixedTextES[] = {
"P\240gina %d",
"Cerrar Diario",
- "Lessen", // <-- not included?!?!
+ "Buscar en Diario",
"Salvar en Archivo",
"Detener B\243squeda",
"Buscar Hacia Atr\240s",
@@ -623,18 +635,20 @@ static const char *const fixedTextES[] = {
"Vuelta: %d",
"Total del Turno: %d",
"Dardo # %d",
- "para empezar",
"Pulsa una tecla",
+ "para empezar",
"Pulsa una tecla",
- "Golpe %s ojo de buey", // ??
"FIN DE LA PARTIDA!",
"ROTO!",
- "Gana!", // "Holmes Gana!", "%s Gana!"
+ "%s gana!", // "Holmes Gana!", "%s Gana!", original: "%s Gana!"
+ "Puntuado %d punto", // original: treated 1 point and multiple points the same ("Scored 1 points")
"Puntuado %d puntos",
- "puntos", // ??
- "Golpe %s %d",
- "doble",
- "triple",
+ "Golpe un %d",
+ "Gople doble %d",
+ "Gople triple %d",
+ "Golpe un ojo de buey",
+ "Gople doble ojo de buey",
+ "Gople triple ojo de buey",
"aplicar",
"Agua",
@@ -656,6 +670,8 @@ static const char *const fixedTextES[] = {
"Non",
"Introducir Palabra Clave",
"Vas al Este", // correct password, was translated in Spanish version (???)
+ "Diario de Watson",
+ "Diario guarda como journal.txt",
// SH2: People names
"Sherlock Holmes",
"Dr. Watson",
@@ -755,7 +771,6 @@ static const char *const fixedTextES[] = {
"Cochero"
};
-// TODO: There also was a Spanish version of Sherlock Holmes 2
static const FixedTextLanguageEntry fixedTextLanguages[] = {
{ Common::DE_DEU, fixedTextDE },
{ Common::ES_ESP, fixedTextES },
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.h b/engines/sherlock/tattoo/tattoo_fixed_text.h
index 48d237db3c..7dbe13bbb3 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.h
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.h
@@ -68,24 +68,26 @@ enum FixedTextId {
kFixedText_SearchForwards,
kFixedText_TextNotFound,
- kFixedText_Holmes,
- kFixedText_Jock,
- kFixedText_Bull,
- kFixedText_Round,
- kFixedText_TurnTotal,
- kFixedText_Dart,
- kFixedText_ToStart,
- kFixedText_HitAKey,
- kFixedText_PressAKey,
- kFixedText_Bullseye,
- kFixedText_GameOver,
- kFixedText_Busted,
- kFixedText_Wins,
- kFixedText_Scored,
- kFixedText_Points,
- kFixedText_Hit,
- kFixedText_Double,
- kFixedText_Triple,
+ kFixedText_DartsPlayerHolmes,
+ kFixedText_DartsPlayerJock,
+ kFixedText_DartsBull,
+ kFixedText_DartsCurrentRound,
+ kFixedText_DartsCurrentTotalPoints,
+ kFixedText_DartsCurrentDart,
+ kFixedText_DartsStartPressKey1,
+ kFixedText_DartsStartPressKey2,
+ kFixedText_DartsPressKey,
+ kFixedText_DartsGameOver,
+ kFixedText_DartsBusted,
+ kFixedText_DartsWins,
+ kFixedText_DartsScoredPoint,
+ kFixedText_DartsScoredPoints,
+ kFixedText_DartsHitSingle,
+ kFixedText_DartsHitDouble,
+ kFixedText_DartsHitTriple,
+ kFixedText_DartsHitSingleBullseye,
+ kFixedText_DartsHitDoubleBullseye,
+ kFixedText_DartsHitTripleBullseye,
kFixedText_Apply,
kFixedText_Water,
@@ -107,6 +109,8 @@ enum FixedTextId {
kFixedText_No,
kFixedText_EnterPassword,
kFixedText_CorrectPassword,
+ kFixedText_WatsonsJournal,
+ kFixedText_JournalSaved,
// SH2: People names
kFixedText_People_SherlockHolmes,
kFixedText_People_DrWatson,
diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp
index e836cca620..918887f320 100644
--- a/engines/sherlock/tattoo/tattoo_journal.cpp
+++ b/engines/sherlock/tattoo/tattoo_journal.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/savefile.h"
#include "sherlock/tattoo/tattoo_journal.h"
#include "sherlock/tattoo/tattoo_fixed_text.h"
#include "sherlock/tattoo/tattoo_scene.h"
@@ -64,7 +65,7 @@ void TattooJournal::show() {
delete stream;
// Set screen to black, and set background
- screen._backBuffer1.blitFrom((*_journalImages)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0));
screen.empty();
screen.setPalette(palette);
@@ -130,7 +131,7 @@ void TattooJournal::handleKeyboardEvents() {
events.warpMouse(Common::Point(r.left + r.width() / 3 - 10, r.top + screen.fontHeight() + 2));
} else {
if (_selector == JH_CLOSE)
- _selector = JH_PRINT;
+ _selector = JH_SAVE;
else
--_selector;
@@ -232,7 +233,7 @@ void TattooJournal::handleKeyboardEvents() {
if (_selector == JH_NONE) {
events.warpMouse(Common::Point(r.left + r.width() / 3 - 10, r.top + screen.fontHeight() + 2));
} else {
- if (_selector == JH_PRINT)
+ if (_selector == JH_SAVE)
_selector = JH_NONE;
else
++_selector;
@@ -378,8 +379,13 @@ void TattooJournal::handleButtons() {
break;
}
- case JH_PRINT:
- // Print Journal - not implemented in ScummVM
+ case JH_SAVE:
+ // Save journal to file
+ disableControls();
+ saveJournal();
+ drawFrame();
+ drawJournal(0, 0);
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
break;
default:
@@ -455,7 +461,7 @@ void TattooJournal::loadLocations() {
void TattooJournal::drawFrame() {
Screen &screen = *_vm->_screen;
- screen._backBuffer1.blitFrom((*_journalImages)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0));
drawControls(0);
}
@@ -480,10 +486,10 @@ void TattooJournal::drawControls(int mode) {
screen._backBuffer1.fillRect(inner, MENU_BACKGROUND);
// Draw the four corners of the info box
- screen._backBuffer1.transBlitFrom(images[0], Common::Point(r.left, r.top));
- screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.top));
- screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.left, r.bottom - images[1]._height));
- screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.bottom - images[1]._height));
+ screen._backBuffer1.SHtransBlitFrom(images[0], Common::Point(r.left, r.top));
+ screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.top));
+ screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.left, r.bottom - images[1]._height));
+ screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.bottom - images[1]._height));
// Draw the top of the info box
screen._backBuffer1.hLine(r.left + images[0]._width, r.top, r.right - images[0]._height, INFO_TOP);
@@ -507,8 +513,8 @@ void TattooJournal::drawControls(int mode) {
// Draw the sides of the separator bar above the scroll bar
int yp = r.top + screen.fontHeight() + 7;
- screen._backBuffer1.transBlitFrom(images[4], Common::Point(r.left, yp - 1));
- screen._backBuffer1.transBlitFrom(images[5], Common::Point(r.right - images[5]._width, yp - 1));
+ screen._backBuffer1.SHtransBlitFrom(images[4], Common::Point(r.left, yp - 1));
+ screen._backBuffer1.SHtransBlitFrom(images[5], Common::Point(r.right - images[5]._width, yp - 1));
// Draw the bar above the scroll bar
screen._backBuffer1.hLine(r.left + images[4]._width, yp, r.right - images[5]._width, INFO_TOP);
@@ -519,8 +525,8 @@ void TattooJournal::drawControls(int mode) {
// Draw the Bars separating the Journal Commands
int xp = r.right / 3;
for (int idx = 0; idx < 2; ++idx) {
- screen._backBuffer1.transBlitFrom(images[6], Common::Point(xp - 2, r.top + 1));
- screen._backBuffer1.transBlitFrom(images[7], Common::Point(xp - 2, yp - 1));
+ screen._backBuffer1.SHtransBlitFrom(images[6], Common::Point(xp - 2, r.top + 1));
+ screen._backBuffer1.SHtransBlitFrom(images[7], Common::Point(xp - 2, yp - 1));
screen._backBuffer1.hLine(xp - 1, r.top + 4, yp - 2, INFO_TOP);
screen._backBuffer1.hLine(xp, r.top + 4, yp - 2, INFO_MIDDLE);
@@ -592,7 +598,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) {
}
// See if the Search was selected, but is not available
- if (_journal.empty() && (_selector == JH_SEARCH || _selector == JH_PRINT))
+ if (_journal.empty() && (_selector == JH_SEARCH || _selector == JH_SAVE))
_selector = JH_NONE;
if (_selector == JH_PAGE_LEFT && _oldSelector == JH_PAGE_RIGHT)
@@ -618,7 +624,10 @@ void TattooJournal::highlightJournalControls(bool slamIt) {
color, "%s", FIXED(SearchJournal));
xp += r.width() / 3;
- color = INFO_BOTTOM;
+ if (!_journal.empty())
+ color = (_selector == JH_SAVE) ? COMMAND_HIGHLIGHTED : INFO_TOP;
+ else
+ color = INFO_BOTTOM;
screen.gPrint(Common::Point(xp - screen.stringWidth(FIXED(SaveJournal)) / 2, r.top + 5),
color, "%s", FIXED(SaveJournal));
@@ -737,7 +746,7 @@ void TattooJournal::disableControls() {
// Print the Journal commands
int xp = r.left + r.width() / 6;
- for (int idx = 0; idx < 2; ++idx) {
+ for (int idx = 0; idx < 3; ++idx) {
screen.gPrint(Common::Point(xp - screen.stringWidth(JOURNAL_COMMANDS[idx]) / 2, r.top + 5),
INFO_BOTTOM, "%s", JOURNAL_COMMANDS[idx]);
@@ -770,7 +779,7 @@ int TattooJournal::getFindName(bool printError) {
// Backup the area under the text entry
Surface bgSurface(r.width() - 6, screen.fontHeight());
- bgSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY,
+ bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY,
r.right - 3, cursorY + screen.fontHeight()));
if (printError) {
@@ -801,7 +810,7 @@ int TattooJournal::getFindName(bool printError) {
events.clearEvents();
// Restore the text background
- screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left, cursorY));
+ screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left, cursorY));
// If there was a name already entered, copy it to name and display it
if (!_find.empty()) {
@@ -837,7 +846,7 @@ int TattooJournal::getFindName(bool printError) {
}
else {
// Erase cursor by restoring background and writing current text
- screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
+ screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED, "%s", name.c_str());
screen.slamArea(r.left + 3, cursorY, r.width() - 3, screen.fontHeight());
}
@@ -880,11 +889,11 @@ int TattooJournal::getFindName(bool printError) {
} else {
if (keyState.keycode & Common::KBD_SHIFT) {
if (_selector == JH_CLOSE)
- _selector = JH_PRINT;
+ _selector = JH_SAVE;
else
--_selector;
} else {
- if (_selector == JH_PRINT)
+ if (_selector == JH_SAVE)
_selector = JH_CLOSE;
else
++_selector;
@@ -903,7 +912,7 @@ int TattooJournal::getFindName(bool printError) {
}
// Redraw the text
- screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
+ screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED,
"%s", name.c_str());
screen.slamArea(r.left + 3, cursorY, r.right - 3, screen.fontHeight());
@@ -949,6 +958,173 @@ void TattooJournal::record(int converseNum, int statementNum, bool replyOnly) {
Journal::record(converseNum, statementNum, replyOnly);
}
+void TattooJournal::saveJournal() {
+ Talk &talk = *_vm->_talk;
+ Common::OutSaveFile *file = g_system->getSavefileManager()->openForSaving("journal.txt", false);
+ int tempIndex = _index;
+
+ _index = 0;
+ talk._converseNum = -1;
+
+ file->writeString(" ");
+ file->writeString(FIXED(WatsonsJournal));
+ file->writeString("\n\n");
+
+ // Loop through saving each page of the journal
+ do {
+ // Print a single talk file
+ Common::String text;
+ int line = 0;
+
+ // Copy all of the talk files entries into one big string
+ do {
+ if (_lines[line].hasPrefix("@")) {
+ text += Common::String(_lines[line].c_str() + 1);
+ if ((line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@"))
+ text += "\n";
+ else
+ text += " ";
+ } else {
+ text += _lines[line];
+ text += " ";
+
+ // Check for embedded location names embedded in comment fields,
+ // which show up as a blank line with the next line starting
+ // with a '@'. We have to add a line break here because the '@' handler
+ // previously assumes that they're always following a blank line
+
+ if ((_lines[line].empty() || _lines[line] == " ")
+ && (line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@"))
+ text += "\n";
+ }
+
+ ++line;
+ } while (line < (int)_lines.size());
+
+ // Now write out the text in 80 column lines
+ do {
+ if (text.size() > 80) {
+ const char *msgP = text.c_str() + 80;
+
+ if (Common::String(text.c_str(), msgP).contains("\n")) {
+ // The 80 characters contain a carriage return,
+ // so we can print out that line
+ const char *cr = strchr(text.c_str(), '\n');
+ file->writeString(Common::String(text.c_str(), cr));
+ text = Common::String(cr + 1);
+ } else {
+ // Move backwards to find a word break
+ while (*msgP != ' ')
+ --msgP;
+
+ // Write out the figured out line
+ file->writeString(Common::String(text.c_str(), msgP));
+
+ // Remove the line that was written out
+ while (*msgP == ' ')
+ ++msgP;
+ text = Common::String(msgP);
+ }
+ } else {
+ // The remainder of the string is under 80 characters.
+ // Check to see if has any line ends
+ if (text.contains("\n")) {
+ // Write out the line up to the carraige return
+ const char *cr = strchr(text.c_str(), '\n');
+ file->writeString(Common::String(text.c_str(), cr));
+ text = Common::String(cr + 1);
+ } else {
+ // Write out the final line
+ file->writeString(text);
+ text = "";
+ }
+ }
+
+ file->writeString("\n");
+ } while (!text.empty());
+
+ // Move to next talk file
+ do {
+ ++_index;
+
+ if (_index < (int)_journal.size())
+ loadJournalFile(false);
+ } while (_index < (int)_journal.size() && _lines.empty());
+
+ // Don't immediately exit if there are no loaded lines for
+ // the next page, since it's probably a stealth file and
+ // can simply be skipped
+ file->writeString("\n");
+ } while (_index < (int)_journal.size());
+
+ file->finalize();
+ delete file;
+
+ // Free up any talk file in memory
+ talk.freeTalkVars();
+
+ // Show the message for the journal having been saved
+ showSavedDialog();
+
+ // Reset the previous settings of the journal
+ _index = tempIndex;
+}
+
+void TattooJournal::showSavedDialog() {
+ TattooEngine &vm = *(TattooEngine *)_vm;
+ Events &events = *vm._events;
+ Screen &screen = *vm._screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)vm._ui;
+ ImageFile &images = *ui._interfaceImages;
+ disableControls();
+
+ Common::String msg = FIXED(JournalSaved);
+ Common::Rect inner(0, 0, screen.stringWidth(msg), screen.fontHeight());
+ inner.moveTo((SHERLOCK_SCREEN_WIDTH - inner.width()) / 2,
+ (SHERLOCK_SCREEN_HEIGHT / 2) - (screen.fontHeight() / 2));
+
+ Common::Rect r = inner;
+ r.grow(10);
+
+ if (vm._transparentMenus)
+ ui.makeBGArea(r);
+ else
+ screen._backBuffer1.fillRect(r, MENU_BACKGROUND);
+
+ // Draw the four corners of the info box
+ screen._backBuffer1.transBlitFrom(images[0], Common::Point(r.left, r.top));
+ screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.top));
+ screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.left, r.bottom - images[1]._height));
+ screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.bottom - images[1]._height));
+
+ // Draw the top of the info box
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.top, r.right - images[0]._height, INFO_TOP);
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.top + 1, r.right - images[0]._height, INFO_MIDDLE);
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.top + 2, r.right - images[0]._height, INFO_BOTTOM);
+
+ // Draw the bottom of the info box
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.bottom - 3, r.right - images[0]._height, INFO_TOP);
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.bottom - 2, r.right - images[0]._height, INFO_MIDDLE);
+ screen._backBuffer1.hLine(r.left + images[0]._width, r.bottom - 1, r.right - images[0]._height, INFO_BOTTOM);
+
+ // Draw the left side of the info box
+ screen._backBuffer1.vLine(r.left, r.top + images[0]._height, r.bottom - images[2]._height, INFO_TOP);
+ screen._backBuffer1.vLine(r.left + 1, r.top + images[0]._height, r.bottom - images[2]._height, INFO_MIDDLE);
+ screen._backBuffer1.vLine(r.left + 2, r.top + images[0]._height, r.bottom - images[2]._height, INFO_BOTTOM);
+
+ // Draw the right side of the info box
+ screen._backBuffer1.vLine(r.right - 3, r.top + images[0]._height, r.bottom - images[2]._height, INFO_TOP);
+ screen._backBuffer1.vLine(r.right - 2, r.top + images[0]._height, r.bottom - images[2]._height, INFO_MIDDLE);
+ screen._backBuffer1.vLine(r.right - 1, r.top + images[0]._height, r.bottom - images[2]._height, INFO_BOTTOM);
+
+ // Draw the text
+ screen._backBuffer1.writeString(msg, Common::Point(inner.left, inner.top), INFO_TOP);
+ screen.slamRect(r);
+
+ // Five second pause
+ events.delay(5000, true);
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_journal.h b/engines/sherlock/tattoo/tattoo_journal.h
index 96c1c6cab4..9f0fa1fc9b 100644
--- a/engines/sherlock/tattoo/tattoo_journal.h
+++ b/engines/sherlock/tattoo/tattoo_journal.h
@@ -31,7 +31,7 @@ namespace Sherlock {
namespace Tattoo {
enum JournalHighlight {
- JH_NONE = -1, JH_CLOSE = 0, JH_SEARCH = 1, JH_PRINT = 2,
+ JH_NONE = -1, JH_CLOSE = 0, JH_SEARCH = 1, JH_SAVE = 2,
JH_SCROLL_LEFT = 3, JH_PAGE_LEFT = 4, JH_PAGE_RIGHT = 5, JH_SCROLL_RIGHT = 6, JH_THUMBNAIL = 7
};
@@ -86,6 +86,16 @@ private:
* Get in a name to search through the journal for
*/
int getFindName(bool printError);
+
+ /**
+ * Save the journal to file
+ */
+ void saveJournal();
+
+ /**
+ * Show a message that the journal has been saved to file
+ */
+ void showSavedDialog();
public:
TattooJournal(SherlockEngine *vm);
virtual ~TattooJournal() {}
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 4c7e8c8fef..0839e46260 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -105,7 +105,7 @@ int TattooMap::show() {
// Load the map image and draw it to the back buffer
ImageFile *map = new ImageFile("map.vgs");
screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
- screen._backBuffer1.blitFrom((*map)[0], Common::Point(0, 0));
+ screen._backBuffer1.SHblitFrom((*map)[0], Common::Point(0, 0));
delete map;
screen.clear();
@@ -114,7 +114,7 @@ int TattooMap::show() {
// Copy the map drawn in the back buffer to the secondary back buffer
screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
- screen._backBuffer2.blitFrom(screen._backBuffer1);
+ screen._backBuffer2.SHblitFrom(screen._backBuffer1);
// Display the built map to the screen
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -148,12 +148,12 @@ int TattooMap::show() {
if (_targetScroll.x < 0)
_targetScroll.x = 0;
- if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.w())
- _targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
+ if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.width())
+ _targetScroll.x = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
if (_targetScroll.y < 0)
_targetScroll.y = 0;
- if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.h())
- _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+ if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.height())
+ _targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
// Check the keyboard
if (events.kbHit()) {
@@ -166,8 +166,8 @@ int TattooMap::show() {
break;
case Common::KEYCODE_END:
- _targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
- _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+ _targetScroll.x = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
+ _targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
break;
case Common::KEYCODE_PAGEUP:
@@ -178,8 +178,8 @@ int TattooMap::show() {
case Common::KEYCODE_PAGEDOWN:
_targetScroll.y += SHERLOCK_SCREEN_HEIGHT;
- if (_targetScroll.y > (screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT))
- _targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+ if (_targetScroll.y > (screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT))
+ _targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
break;
case Common::KEYCODE_SPACE:
@@ -304,7 +304,7 @@ void TattooMap::drawMapIcons() {
if (_data[idx]._iconNum != -1 && _vm->readFlags(idx + 1)) {
MapEntry &mapEntry = _data[idx];
ImageFrame &img = (*_iconImages)[mapEntry._iconNum];
- screen._backBuffer1.transBlitFrom(img._frame, Common::Point(mapEntry.x - img._width / 2,
+ screen._backBuffer1.SHtransBlitFrom(img._frame, Common::Point(mapEntry.x - img._width / 2,
mapEntry.y - img._height / 2));
}
}
@@ -355,10 +355,10 @@ void TattooMap::restoreArea(const Common::Rect &bounds) {
Screen &screen = *_vm->_screen;
Common::Rect r = bounds;
- r.clip(Common::Rect(0, 0, screen._backBuffer1.w(), screen._backBuffer1.h()));
+ r.clip(Common::Rect(0, 0, screen._backBuffer1.width(), screen._backBuffer1.height()));
if (!r.isEmpty())
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(r.left, r.top), r);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(r.left, r.top), r);
}
void TattooMap::showCloseUp(int closeUpNum) {
@@ -407,7 +407,7 @@ void TattooMap::showCloseUp(int closeUpNum) {
screen._currentScroll.y + closeUp.y / 100 - picSize.y / 2);
restoreArea(oldBounds);
- screen._backBuffer1.transBlitFrom(pic[0], pt, false, 0, scaleVal);
+ screen._backBuffer1.SHtransBlitFrom(pic[0], pt, false, 0, scaleVal);
screen.slamRect(oldBounds);
screen.slamArea(pt.x, pt.y, picSize.x, picSize.y);
@@ -426,7 +426,7 @@ void TattooMap::showCloseUp(int closeUpNum) {
screen._currentScroll.y + SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2 + pic[0]._height);
restoreArea(oldBounds);
- screen._backBuffer1.transBlitFrom(pic[0], Common::Point(r.left, r.top));
+ screen._backBuffer1.SHtransBlitFrom(pic[0], Common::Point(r.left, r.top));
screen.slamRect(oldBounds);
screen.slamRect(r);
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index 0af8deff9f..65cc283b66 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -1042,7 +1042,7 @@ void TattooPerson::walkHolmesToNPC() {
holmes._walkDest.x = MAX(_position.x / FIXED_INT_MULTIPLIER - imgFrame.sDrawXSize(scaleVal), 0);
} else {
holmes._walkDest.x = MIN(_position.x / FIXED_INT_MULTIPLIER + imgFrame.sDrawXSize(scaleVal) * 2,
- screen._backBuffer1.w() - 1);
+ screen._backBuffer1.width() - 1);
}
// See where Holmes is with respect to the NPC (y coords)
@@ -1168,7 +1168,7 @@ void TattooPerson::centerScreenOnPerson() {
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
ui._targetScroll.x = CLIP(_position.x / FIXED_INT_MULTIPLIER - SHERLOCK_SCREEN_WIDTH / 2,
- 0, screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH);
+ 0, screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH);
screen._currentScroll = ui._targetScroll;
// Reset the default look position to the center of the screen
@@ -1354,6 +1354,7 @@ void TattooPeople::setTalkSequence(int speaker, int sequenceNum) {
int TattooPeople::findSpeaker(int speaker) {
+ speaker &= 0x7f;
int result = People::findSpeaker(speaker);
const char *portrait = _characters[speaker]._portrait;
@@ -1477,7 +1478,7 @@ const Common::Point TattooPeople::restrictToZone(int zoneId, const Common::Point
Screen &screen = *_vm->_screen;
Common::Rect &r = scene._zones[zoneId];
- if (destPos.x < 0 || destPos.x > screen._backBuffer1.w())
+ if (destPos.x < 0 || destPos.x > screen._backBuffer1.width())
return destPos;
else if (destPos.y < r.top && r.left < destPos.x && destPos.x < r.right)
return Common::Point(destPos.x, r.top);
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 27f37665dc..00015cb189 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -141,15 +141,15 @@ void TattooScene::drawAllShapes() {
if (obj._type == ACTIVE_BG_SHAPE && obj._misc == BEHIND) {
if (obj._quickDraw && obj._scaleVal == SCALE_THRESHOLD)
- screen._backBuffer1.blitFrom(*obj._imageFrame, obj._position);
+ screen._backBuffer1.SHblitFrom(*obj._imageFrame, obj._position);
else
- screen._backBuffer1.transBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
+ screen._backBuffer1.SHtransBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
}
}
// Draw the animation if it is behind the person
if (_activeCAnim.active() && _activeCAnim._zPlacement == BEHIND)
- screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
+ screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
(_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
screen.resetDisplayBounds();
@@ -194,13 +194,13 @@ void TattooScene::drawAllShapes() {
if (se._shape) {
// it's a bg shape
if (se._shape->_quickDraw && se._shape->_scaleVal == SCALE_THRESHOLD)
- screen._backBuffer1.blitFrom(*se._shape->_imageFrame, se._shape->_position);
+ screen._backBuffer1.SHblitFrom(*se._shape->_imageFrame, se._shape->_position);
else
- screen._backBuffer1.transBlitFrom(*se._shape->_imageFrame, se._shape->_position,
+ screen._backBuffer1.SHtransBlitFrom(*se._shape->_imageFrame, se._shape->_position,
se._shape->_flags & OBJ_FLIPPED, 0, se._shape->_scaleVal);
} else if (se._isAnimation) {
// It's an active animation
- screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
+ screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
(_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
} else {
// Drawing person
@@ -212,7 +212,7 @@ void TattooScene::drawAllShapes() {
if (p._tempScaleVal == SCALE_THRESHOLD) {
p._tempX += adjust.x;
- screen._backBuffer1.transBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
+ screen._backBuffer1.SHtransBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
- p.frameHeight() - adjust.y), p._walkSequences[p._sequenceNumber]._horizFlip, 0, p._tempScaleVal);
} else {
if (adjust.x) {
@@ -242,7 +242,7 @@ void TattooScene::drawAllShapes() {
++adjust.y;
}
- screen._backBuffer1.transBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
+ screen._backBuffer1.SHtransBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
- p._imageFrame->sDrawYSize(p._tempScaleVal) - adjust.y), p._walkSequences[p._sequenceNumber]._horizFlip, 0, p._tempScaleVal);
}
}
@@ -255,15 +255,15 @@ void TattooScene::drawAllShapes() {
if (obj._type == ACTIVE_BG_SHAPE && obj._misc == FORWARD) {
if (obj._quickDraw && obj._scaleVal == SCALE_THRESHOLD)
- screen._backBuffer1.blitFrom(*obj._imageFrame, obj._position);
+ screen._backBuffer1.SHblitFrom(*obj._imageFrame, obj._position);
else
- screen._backBuffer1.transBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
+ screen._backBuffer1.SHtransBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
}
}
// Draw the canimation if it is set as FORWARD
if (_activeCAnim.active() && _activeCAnim._zPlacement == FORWARD)
- screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position, (_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
+ screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position, (_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
// Draw all NO_SHAPE shapes which have their flag bits clear
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
diff --git a/engines/sherlock/tattoo/tattoo_screen.cpp b/engines/sherlock/tattoo/tattoo_screen.cpp
new file mode 100644
index 0000000000..c98ae2679d
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_screen.cpp
@@ -0,0 +1,37 @@
+/* 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 "sherlock/tattoo/tattoo_screen.h"
+#include "sherlock/tattoo/tattoo.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+TattooScreen::TattooScreen(SherlockEngine *vm) : Screen(vm) {
+ _backBuffer1.create(640, 480);
+ _backBuffer2.create(640, 480);
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_screen.h b/engines/sherlock/tattoo/tattoo_screen.h
new file mode 100644
index 0000000000..b55e9bb0dd
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_screen.h
@@ -0,0 +1,44 @@
+/* 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 SHERLOCK_TATTOO_SCREEN_H
+#define SHERLOCK_TATTOO_SCREEN_H
+
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+namespace Tattoo {
+
+class TattooScreen : public Screen {
+public:
+ TattooScreen(SherlockEngine *vm);
+ virtual ~TattooScreen() {}
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp
index a5ada7b63e..e6b9a9627e 100644
--- a/engines/sherlock/tattoo/tattoo_talk.cpp
+++ b/engines/sherlock/tattoo/tattoo_talk.cpp
@@ -795,7 +795,10 @@ OpcodeReturn TattooTalk::cmdTalkInterruptsDisable(const byte *&str) { error("Dum
// Dummy opcode
OpcodeReturn TattooTalk::cmdTalkInterruptsEnable(const byte *&str) { error("Dummy opcode cmdTalkInterruptsEnable called"); }
-OpcodeReturn TattooTalk::cmdTurnSoundsOff(const byte *&str) { error("TODO: script opcode (cmdTurnSoundsOff)"); }
+OpcodeReturn TattooTalk::cmdTurnSoundsOff(const byte *&str) {
+ _vm->_sound->stopSound();
+ return RET_SUCCESS;
+}
OpcodeReturn TattooTalk::cmdWalkHolmesAndNPCToCAnimation(const byte *&str) {
int npcNum = *++str;
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index ee028f89c2..677a662535 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -72,7 +72,7 @@ TattooUserInterface::~TattooUserInterface() {
void TattooUserInterface::initScrollVars() {
Screen &screen = *_vm->_screen;
- _scrollSize = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
+ _scrollSize = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
_targetScroll = Common::Point(0, 0);
screen._currentScroll = Common::Point(0, 0);
}
@@ -233,7 +233,7 @@ void TattooUserInterface::doJournal() {
Common::copy(&lookupTable1[0], &lookupTable1[PALETTE_COUNT], &_lookupTable1[0]);
// Restore the scene
- screen._backBuffer1.blitFrom(screen._backBuffer2);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2);
scene.updateBackground();
screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
@@ -727,7 +727,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
if (_mask != nullptr) {
// Since a mask is active, restore the screen from the secondary back buffer prior to applying the mask
- screen._backBuffer1.blitFrom(screen._backBuffer2, screen._currentScroll, Common::Rect(screen._currentScroll.x, 0,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, screen._currentScroll, Common::Rect(screen._currentScroll.x, 0,
screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
switch (scene._currentScene) {
@@ -757,7 +757,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
case 53:
if (++_maskCounter == 2) {
_maskCounter = 0;
- if (++_maskOffset.x == screen._backBuffer1.w())
+ if (++_maskOffset.x == screen._backBuffer1.width())
_maskOffset.x = 0;
}
break;
@@ -779,7 +779,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) ||
obj._type == HIDE_SHAPE || obj._type == REMOVE)
- screen._backBuffer1.blitFrom(screen._backBuffer2, obj._oldPosition,
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, obj._oldPosition,
Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
obj._oldPosition.y + obj._oldSize.y));
}
@@ -793,7 +793,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
Object &obj = scene._bgShapes[idx];
if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
- screen._backBuffer1.blitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
obj._oldPosition = obj._position;
obj._oldSize = obj._noShapeSize;
@@ -870,7 +870,7 @@ void TattooUserInterface::maskArea(Common::SeekableReadStream &mask, const Commo
int pixel, len, xp, yp;
for (yp = 0; yp < ySize; ++yp) {
- byte *ptr = bb1.getBasePtr(pt.x, pt.y + yp);
+ byte *ptr = (byte *)bb1.getBasePtr(pt.x, pt.y + yp);
for (xp = 0; xp < xSize;) {
// The mask data consists of pairs of pixel/lengths, where all non-zero pixels means that the
@@ -893,7 +893,7 @@ void TattooUserInterface::makeBGArea(const Common::Rect &r) {
Screen &screen = *_vm->_screen;
for (int yp = r.top; yp < r.bottom; ++yp) {
- byte *ptr = screen._backBuffer1.getBasePtr(r.left, yp);
+ byte *ptr = (byte *)screen._backBuffer1.getBasePtr(r.left, yp);
for (int xp = r.left; xp < r.right; ++xp, ++ptr)
*ptr = _lookupTable[*ptr];
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index 8f0649130a..a35f4e5d74 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -88,7 +88,7 @@ void WidgetBase::erase() {
if (_oldBounds.width() > 0) {
// Restore the affected area from the secondary back buffer into the first one, and then copy to screen
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+ screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
screen.slamRect(_oldBounds);
// Reset the old bounds so it won't be erased again
@@ -111,7 +111,7 @@ void WidgetBase::draw() {
drawBackground();
// Draw the widget onto the back buffer and then slam it to the screen
- screen._backBuffer1.transBlitFrom(_surface, Common::Point(_bounds.left, _bounds.top));
+ screen._backBuffer1.SHtransBlitFrom(_surface, Common::Point(_bounds.left, _bounds.top));
screen.slamRect(_bounds);
// Store a copy of the drawn area for later erasing
@@ -183,8 +183,8 @@ void WidgetBase::restrictToScreen() {
_bounds.moveTo(_bounds.left, 0);
if (_bounds.right > (screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH))
_bounds.moveTo(screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH - _bounds.width(), _bounds.top);
- if (_bounds.bottom > screen._backBuffer1.h())
- _bounds.moveTo(_bounds.left, screen._backBuffer1.h() - _bounds.height());
+ if (_bounds.bottom > screen._backBuffer1.height())
+ _bounds.moveTo(_bounds.left, screen._backBuffer1.height() - _bounds.height());
}
void WidgetBase::makeInfoArea(Surface &s) {
@@ -192,30 +192,30 @@ void WidgetBase::makeInfoArea(Surface &s) {
ImageFile &images = *ui._interfaceImages;
// Draw the four corners of the Info Box
- s.transBlitFrom(images[0], Common::Point(0, 0));
- s.transBlitFrom(images[1], Common::Point(s.w() - images[1]._width, 0));
- s.transBlitFrom(images[2], Common::Point(0, s.h() - images[2]._height));
- s.transBlitFrom(images[3], Common::Point(s.w() - images[3]._width, s.h()));
+ s.SHtransBlitFrom(images[0], Common::Point(0, 0));
+ s.SHtransBlitFrom(images[1], Common::Point(s.width() - images[1]._width, 0));
+ s.SHtransBlitFrom(images[2], Common::Point(0, s.height() - images[2]._height));
+ s.SHtransBlitFrom(images[3], Common::Point(s.width() - images[3]._width, s.height()));
// Draw the top of the Info Box
- s.hLine(images[0]._width, 0, s.w() - images[1]._width, INFO_TOP);
- s.hLine(images[0]._width, 1, s.w() - images[1]._width, INFO_MIDDLE);
- s.hLine(images[0]._width, 2, s.w() - images[1]._width, INFO_BOTTOM);
+ s.hLine(images[0]._width, 0, s.width() - images[1]._width, INFO_TOP);
+ s.hLine(images[0]._width, 1, s.width() - images[1]._width, INFO_MIDDLE);
+ s.hLine(images[0]._width, 2, s.width() - images[1]._width, INFO_BOTTOM);
// Draw the bottom of the Info Box
- s.hLine(images[0]._width, s.h()- 3, s.w() - images[1]._width, INFO_TOP);
- s.hLine(images[0]._width, s.h()- 2, s.w() - images[1]._width, INFO_MIDDLE);
- s.hLine(images[0]._width, s.h()- 1, s.w() - images[1]._width, INFO_BOTTOM);
+ s.hLine(images[0]._width, s.height()- 3, s.width() - images[1]._width, INFO_TOP);
+ s.hLine(images[0]._width, s.height()- 2, s.width() - images[1]._width, INFO_MIDDLE);
+ s.hLine(images[0]._width, s.height()- 1, s.width() - images[1]._width, INFO_BOTTOM);
// Draw the left Side of the Info Box
- s.vLine(0, images[0]._height, s.h()- images[2]._height, INFO_TOP);
- s.vLine(1, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
- s.vLine(2, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
+ s.vLine(0, images[0]._height, s.height()- images[2]._height, INFO_TOP);
+ s.vLine(1, images[0]._height, s.height()- images[2]._height, INFO_MIDDLE);
+ s.vLine(2, images[0]._height, s.height()- images[2]._height, INFO_BOTTOM);
// Draw the right Side of the Info Box
- s.vLine(s.w() - 3, images[0]._height, s.h()- images[2]._height, INFO_TOP);
- s.vLine(s.w() - 2, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
- s.vLine(s.w() - 1, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
+ s.vLine(s.width() - 3, images[0]._height, s.height()- images[2]._height, INFO_TOP);
+ s.vLine(s.width() - 2, images[0]._height, s.height()- images[2]._height, INFO_MIDDLE);
+ s.vLine(s.width() - 1, images[0]._height, s.height()- images[2]._height, INFO_BOTTOM);
}
void WidgetBase::makeInfoArea() {
diff --git a/engines/sherlock/tattoo/widget_credits.cpp b/engines/sherlock/tattoo/widget_credits.cpp
index b8e297709f..1c878daaf6 100644
--- a/engines/sherlock/tattoo/widget_credits.cpp
+++ b/engines/sherlock/tattoo/widget_credits.cpp
@@ -37,7 +37,7 @@ void WidgetCredits::initCredits() {
Screen &screen = *_vm->_screen;
Common::SeekableReadStream *stream = res.load("credits.txt");
int spacing = screen.fontHeight() * 2;
- int yp = screen.h();
+ int yp = screen.height();
_creditsActive = true;
_creditLines.clear();
@@ -60,7 +60,7 @@ void WidgetCredits::initCredits() {
} else {
int width = screen.stringWidth(line) + 2;
- _creditLines.push_back(CreditLine(line, Common::Point((screen.w() - width) / 2 + 1, yp), width));
+ _creditLines.push_back(CreditLine(line, Common::Point((screen.width() - width) / 2 + 1, yp), width));
yp += spacing;
}
}
@@ -120,10 +120,10 @@ void WidgetCredits::close() {
void WidgetCredits::drawCredits() {
Screen &screen = *_vm->_screen;
- Common::Rect screenRect(0, 0, screen.w(), screen.h());
+ Common::Rect screenRect(0, 0, screen.width(), screen.height());
Surface &bb1 = screen._backBuffer1;
- for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < screen.h(); ++idx) {
+ for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < screen.height(); ++idx) {
if (screenRect.contains(_creditLines[idx]._position)) {
if (!_creditLines[idx]._line2.empty()) {
int x1 = _creditLines[idx]._position.x;
@@ -176,7 +176,7 @@ void WidgetCredits::drawCredits() {
void WidgetCredits::blitCredits() {
Screen &screen = *_vm->_screen;
- Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+ Common::Rect screenRect(0, -_creditSpeed, screen.width(), screen.height() + _creditSpeed);
for (uint idx = 0; idx < _creditLines.size(); ++idx) {
if (screenRect.contains(_creditLines[idx]._position)) {
@@ -185,14 +185,12 @@ void WidgetCredits::blitCredits() {
screen.slamRect(r);
}
-
- _creditLines[idx]._position.y -= _creditSpeed;
}
}
void WidgetCredits::eraseCredits() {
Screen &screen = *_vm->_screen;
- Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+ Common::Rect screenRect(0, -_creditSpeed, screen.width(), screen.height() + _creditSpeed);
for (uint idx = 0; idx < _creditLines.size(); ++idx) {
if (screenRect.contains(_creditLines[idx]._position)) {
@@ -200,7 +198,10 @@ void WidgetCredits::eraseCredits() {
r.moveTo(_creditLines[idx]._position.x, _creditLines[idx]._position.y - 1 + _creditSpeed);
screen.restoreBackground(r);
+ screen.slamRect(r);
}
+
+ _creditLines[idx]._position.y -= _creditSpeed;
}
if (_creditLines[_creditLines.size() - 1]._position.y < -_creditSpeed) {
diff --git a/engines/sherlock/tattoo/widget_files.cpp b/engines/sherlock/tattoo/widget_files.cpp
index ff8cb83dca..7666e81480 100644
--- a/engines/sherlock/tattoo/widget_files.cpp
+++ b/engines/sherlock/tattoo/widget_files.cpp
@@ -107,36 +107,36 @@ void WidgetFiles::render(FilesRenderMode mode) {
byte color;
if (mode == RENDER_ALL) {
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
makeInfoArea();
switch (_fileMode) {
case SAVEMODE_LOAD:
_surface.writeString(FIXED(LoadGame),
- Common::Point((_surface.w() - _surface.stringWidth(FIXED(LoadGame))) / 2, 5), INFO_TOP);
+ Common::Point((_surface.width() - _surface.stringWidth(FIXED(LoadGame))) / 2, 5), INFO_TOP);
break;
case SAVEMODE_SAVE:
_surface.writeString(FIXED(SaveGame),
- Common::Point((_surface.w() - _surface.stringWidth(FIXED(SaveGame))) / 2, 5), INFO_TOP);
+ Common::Point((_surface.width() - _surface.stringWidth(FIXED(SaveGame))) / 2, 5), INFO_TOP);
break;
default:
break;
}
- _surface.hLine(3, _surface.fontHeight() + 7, _surface.w() - 4, INFO_TOP);
- _surface.hLine(3, _surface.fontHeight() + 8, _surface.w() - 4, INFO_MIDDLE);
- _surface.hLine(3, _surface.fontHeight() + 9, _surface.w() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 6));
- _surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, _surface.fontHeight() + 6));
+ _surface.hLine(3, _surface.fontHeight() + 7, _surface.width() - 4, INFO_TOP);
+ _surface.hLine(3, _surface.fontHeight() + 8, _surface.width() - 4, INFO_MIDDLE);
+ _surface.hLine(3, _surface.fontHeight() + 9, _surface.width() - 4, INFO_BOTTOM);
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 6));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, _surface.fontHeight() + 6));
- int xp = _surface.w() - BUTTON_SIZE - 6;
+ int xp = _surface.width() - BUTTON_SIZE - 6;
_surface.vLine(xp, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_TOP);
_surface.vLine(xp + 1, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_MIDDLE);
_surface.vLine(xp + 2, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[6], Common::Point(xp - 1, _surface.fontHeight() + 8));
- _surface.transBlitFrom(images[7], Common::Point(xp - 1, _bounds.height() - 4));
+ _surface.SHtransBlitFrom(images[6], Common::Point(xp - 1, _surface.fontHeight() + 8));
+ _surface.SHtransBlitFrom(images[7], Common::Point(xp - 1, _bounds.height() - 4));
}
int xp = _surface.stringWidth("00.") + _surface.widestChar() + 5;
@@ -149,7 +149,7 @@ void WidgetFiles::render(FilesRenderMode mode) {
color = INFO_TOP;
if (mode == RENDER_NAMES_AND_SCROLLBAR)
- _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
+ _surface.fillRect(Common::Rect(4, yp, _surface.width() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
Common::String numStr = Common::String::format("%d.", idx + 1);
_surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
@@ -324,7 +324,7 @@ bool WidgetFiles::getFilename() {
filename.setChar(' ', index);
}
- _surface.fillRect(Common::Rect(pt.x, pt.y, _surface.w() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _surface.width() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
_surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
} else if ((keyState.keycode == Common::KEYCODE_LEFT && index > 0)
@@ -387,7 +387,7 @@ bool WidgetFiles::getFilename() {
}
if ((keyState.ascii >= ' ') && (keyState.ascii <= 'z') && (index < 50)) {
- if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w() - BUTTON_SIZE - 20) {
+ if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w - BUTTON_SIZE - 20) {
if (insert)
filename.insertChar(keyState.ascii, index);
else
diff --git a/engines/sherlock/tattoo/widget_foolscap.cpp b/engines/sherlock/tattoo/widget_foolscap.cpp
index c8df71e873..8225946838 100644
--- a/engines/sherlock/tattoo/widget_foolscap.cpp
+++ b/engines/sherlock/tattoo/widget_foolscap.cpp
@@ -103,7 +103,7 @@ void WidgetFoolscap::show() {
// Set up the window background
_surface.create(_bounds.width(), _bounds.height());
- _surface.blitFrom(paperFrame, Common::Point(0, 0));
+ _surface.SHblitFrom(paperFrame, Common::Point(0, 0));
// If they have already solved the puzzle, put the answer on the graphic
if (_vm->readFlags(299)) {
@@ -265,7 +265,7 @@ void WidgetFoolscap::handleKeyboardEvents() {
void WidgetFoolscap::restoreChar() {
Screen &screen = *_vm->_screen;
ImageFrame &bgFrame = (*_images)[0];
- _surface.blitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y,
+ _surface.SHblitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y,
_cursorPos.x + screen.widestChar(), _cursorPos.y + screen.fontHeight()));
}
diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp
index b49e30b30d..34331f0eae 100644
--- a/engines/sherlock/tattoo/widget_inventory.cpp
+++ b/engines/sherlock/tattoo/widget_inventory.cpp
@@ -94,7 +94,7 @@ void WidgetInventoryTooltip::setText(const Common::String &str) {
// Allocate a fresh surface for the new string
_bounds = Common::Rect(width, height);
_surface.create(width, height);
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
if (line2.empty()) {
_surface.writeFancyString(str, Common::Point(0, 0), BLACK, INFO_TOP);
@@ -338,7 +338,7 @@ void WidgetInventoryVerbs::load() {
// Create the surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
makeInfoArea();
// Draw the Verb commands and the lines separating them
@@ -352,8 +352,8 @@ void WidgetInventoryVerbs::load() {
_surface.vLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 1, _bounds.right - 4, INFO_MIDDLE);
_surface.vLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 2, _bounds.right - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1)));
- _surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1)));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
(_surface.fontHeight() + 7) * (idx + 1) - 1));
}
}
@@ -515,7 +515,7 @@ void WidgetInventory::load(int mode) {
// Redraw the inventory menu on the widget surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
// Draw the window background and then the inventory on top of it
makeInfoArea(_surface);
@@ -531,7 +531,7 @@ void WidgetInventory::drawBars() {
_surface.hLine(3, INVENTORY_YSIZE + 3, _bounds.width() - 4, INFO_TOP);
_surface.hLine(3, INVENTORY_YSIZE + 4, _bounds.width() - 4, INFO_MIDDLE);
_surface.hLine(3, INVENTORY_YSIZE + 5, _bounds.width() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[4], Common::Point(0, INVENTORY_YSIZE + 2));
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, INVENTORY_YSIZE + 2));
for (int idx = 1; idx <= NUM_INVENTORY_SHOWN / 2; ++idx) {
x = idx * (INVENTORY_XSIZE + 3);
@@ -540,10 +540,10 @@ void WidgetInventory::drawBars() {
_surface.vLine(x + 1, 3, _bounds.height() - 4, INFO_MIDDLE);
_surface.vLine(x + 2, 3, _bounds.height() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[6], Common::Point(x - 1, 1));
- _surface.transBlitFrom(images[7], Common::Point(x - 1, _bounds.height() - 4));
- _surface.transBlitFrom(images[6], Common::Point(x - 1, INVENTORY_YSIZE + 5));
- _surface.transBlitFrom(images[7], Common::Point(x - 1, INVENTORY_YSIZE + 2));
+ _surface.SHtransBlitFrom(images[6], Common::Point(x - 1, 1));
+ _surface.SHtransBlitFrom(images[7], Common::Point(x - 1, _bounds.height() - 4));
+ _surface.SHtransBlitFrom(images[6], Common::Point(x - 1, INVENTORY_YSIZE + 5));
+ _surface.SHtransBlitFrom(images[7], Common::Point(x - 1, INVENTORY_YSIZE + 2));
}
_surface.hLine(x + 2, INVENTORY_YSIZE + 2, INVENTORY_YSIZE + 8, INFO_BOTTOM);
@@ -566,7 +566,7 @@ void WidgetInventory::drawInventory() {
// Draw the item
if (itemId < inv._holdings) {
ImageFrame &img = (*inv._invShapes[idx])[0];
- _surface.transBlitFrom(img, Common::Point(pt.x + (INVENTORY_XSIZE - img._width) / 2,
+ _surface.SHtransBlitFrom(img, Common::Point(pt.x + (INVENTORY_XSIZE - img._width) / 2,
pt.y + (INVENTORY_YSIZE - img._height) / 2));
}
}
diff --git a/engines/sherlock/tattoo/widget_options.cpp b/engines/sherlock/tattoo/widget_options.cpp
index 92bd10bbf6..81f50f3bc5 100644
--- a/engines/sherlock/tattoo/widget_options.cpp
+++ b/engines/sherlock/tattoo/widget_options.cpp
@@ -257,17 +257,17 @@ void WidgetOptions::render(OptionRenderMode mode) {
// Setup the dialog
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
makeInfoArea();
// Draw the lines separating options in the dialog
int yp = _surface.fontHeight() + 7;
for (int idx = 0; idx < 7; ++idx) {
- _surface.transBlitFrom(images[4], Common::Point(0, yp - 1));
- _surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, yp - 1));
- _surface.hLine(3, yp, _surface.w() - 4, INFO_TOP);
- _surface.hLine(3, yp + 1, _surface.w() - 4, INFO_MIDDLE);
- _surface.hLine(3, yp + 2, _surface.w() - 4, INFO_BOTTOM);
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, yp - 1));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, yp - 1));
+ _surface.hLine(3, yp, _surface.width() - 4, INFO_TOP);
+ _surface.hLine(3, yp + 1, _surface.width() - 4, INFO_MIDDLE);
+ _surface.hLine(3, yp + 2, _surface.width() - 4, INFO_BOTTOM);
yp += _surface.fontHeight() + 7;
if (idx == 1)
@@ -281,7 +281,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
for (int idx = 0, yp = 5; idx < 11; ++idx, yp += _surface.fontHeight() + 7) {
if (mode == OP_ALL || idx == _selector || idx == _oldSelector) {
if (mode == OP_NAMES)
- _surface.fillRect(Common::Rect(4, yp, _surface.w() - 5, yp + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.fillRect(Common::Rect(4, yp, _surface.width() - 5, yp + _surface.fontHeight() - 1), TRANSPARENCY);
byte color = (idx == _selector) ? COMMAND_HIGHLIGHTED : INFO_TOP;
Common::String str;
@@ -302,11 +302,11 @@ void WidgetOptions::render(OptionRenderMode mode) {
int num = (_surface.fontHeight() + 4) & 0xfe;
int sliderY = yp + num / 2 - 8;
- _surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.w() - 5,
+ _surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.width() - 5,
sliderY - (num - 6) / 2 + num - 1), TRANSPARENCY);
_surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2,
- _surface.w() - _surface.widestChar() - 1, sliderY + 3), INFO_MIDDLE);
- drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.w() - _surface.widestChar(), sliderY + 6));
+ _surface.width() - _surface.widestChar() - 1, sliderY + 3), INFO_MIDDLE);
+ drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.width() - _surface.widestChar(), sliderY + 6));
_surface.fillRect(Common::Rect(_midiSliderX - 1, sliderY - (num - 6) / 2 + 2,
_midiSliderX + 1, sliderY - (num - 6) / 2 + num - 3), INFO_MIDDLE);
@@ -315,7 +315,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
if (_midiSliderX - 4 > _surface.widestChar())
_surface.fillRect(Common::Rect(_midiSliderX - 4, sliderY, _midiSliderX - 4, sliderY + 4), INFO_BOTTOM);
- if (_midiSliderX + 4 < _surface.w() - _surface.widestChar())
+ if (_midiSliderX + 4 < _surface.width() - _surface.widestChar())
_surface.fillRect(Common::Rect(_midiSliderX + 4, sliderY, _midiSliderX + 4, sliderY + 4), INFO_BOTTOM);
break;
}
@@ -332,18 +332,18 @@ void WidgetOptions::render(OptionRenderMode mode) {
int num = (_surface.fontHeight() + 4) & 0xfe;
int sliderY = yp + num / 2 - 8;
- _surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.w() - 5,
+ _surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.width() - 5,
sliderY - (num - 6) / 2 + num - 1), TRANSPARENCY);
- _surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2, _surface.w() - _surface.widestChar() - 1,
+ _surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2, _surface.width() - _surface.widestChar() - 1,
sliderY + 3), INFO_MIDDLE);
- drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.w() - _surface.widestChar(), sliderY + 6));
+ drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.width() - _surface.widestChar(), sliderY + 6));
_surface.fillRect(Common::Rect(_digiSliderX - 1, sliderY - (num - 6) / 2 + 2, _digiSliderX + 1,
sliderY - (num - 6) / 2 + num - 3), INFO_MIDDLE);
drawDialogRect(Common::Rect(_digiSliderX - 3, sliderY - (num - 6) / 2, _digiSliderX + 4,
sliderY - (num - 6) / 2 + num));
if (_digiSliderX - 4 > _surface.widestChar())
_surface.fillRect(Common::Rect(_digiSliderX - 4, sliderY, _digiSliderX - 4, sliderY + 4), INFO_BOTTOM);
- if (_digiSliderX + 4 < _surface.w() - _surface.widestChar())
+ if (_digiSliderX + 4 < _surface.width() - _surface.widestChar())
_surface.fillRect(Common::Rect(_digiSliderX + 4, sliderY, _digiSliderX + 4, sliderY + 4), INFO_BOTTOM);
break;
}
@@ -375,7 +375,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
// Unless we're doing one of the Slider Controls, print the text for the line
if (idx != 3 && idx != 6) {
- int xp = (_surface.w() - _surface.stringWidth(str)) / 2;
+ int xp = (_surface.width() - _surface.stringWidth(str)) / 2;
_surface.writeString(str, Common::Point(xp, yp), color);
}
}
diff --git a/engines/sherlock/tattoo/widget_password.cpp b/engines/sherlock/tattoo/widget_password.cpp
index 57a5e02653..2a2921026d 100644
--- a/engines/sherlock/tattoo/widget_password.cpp
+++ b/engines/sherlock/tattoo/widget_password.cpp
@@ -47,7 +47,7 @@ void WidgetPassword::show() {
// Create the surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
makeInfoArea();
// Draw the header area
@@ -55,8 +55,8 @@ void WidgetPassword::show() {
_surface.hLine(3, _surface.fontHeight() + 7, _bounds.width() - 4, INFO_TOP);
_surface.hLine(3, _surface.fontHeight() + 8, _bounds.width() - 4, INFO_MIDDLE);
_surface.hLine(3, _surface.fontHeight() + 9, _bounds.width() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 7 - 1));
- _surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, _surface.fontHeight() + 7 - 1));
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 7 - 1));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, _surface.fontHeight() + 7 - 1));
// Set the password entry data
_cursorPos = Common::Point(_surface.widestChar(), _surface.fontHeight() + 12);
diff --git a/engines/sherlock/tattoo/widget_quit.cpp b/engines/sherlock/tattoo/widget_quit.cpp
index f853e7f47f..ea8f2e080c 100644
--- a/engines/sherlock/tattoo/widget_quit.cpp
+++ b/engines/sherlock/tattoo/widget_quit.cpp
@@ -48,22 +48,22 @@ void WidgetQuit::show() {
// Create the surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
makeInfoArea();
// Draw the message text
- _surface.writeString(FIXED(AreYouSureYou), Common::Point((_surface.w() - _surface.stringWidth(FIXED(AreYouSureYou))) / 2, 5), INFO_TOP);
- _surface.writeString(FIXED(WishToQuit), Common::Point((_surface.w() - _surface.stringWidth(FIXED(WishToQuit))) / 2,
+ _surface.writeString(FIXED(AreYouSureYou), Common::Point((_surface.width() - _surface.stringWidth(FIXED(AreYouSureYou))) / 2, 5), INFO_TOP);
+ _surface.writeString(FIXED(WishToQuit), Common::Point((_surface.width() - _surface.stringWidth(FIXED(WishToQuit))) / 2,
_surface.fontHeight() + 9), INFO_TOP);
// Draw the horizontal bars seperating the commands and the message
int yp = (_surface.fontHeight() + 4) * 2 + 3;
for (int idx = 0; idx < 2; ++idx) {
- _surface.transBlitFrom(images[4], Common::Point(0, yp - 1));
- _surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, yp - 1));
- _surface.hLine(3, yp, _surface.w() - 4, INFO_TOP);
- _surface.hLine(3, yp + 1, _surface.w() - 4, INFO_MIDDLE);
- _surface.hLine(3, yp + 2, _surface.w() - 4, INFO_BOTTOM);
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, yp - 1));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, yp - 1));
+ _surface.hLine(3, yp, _surface.width() - 4, INFO_TOP);
+ _surface.hLine(3, yp + 1, _surface.width() - 4, INFO_MIDDLE);
+ _surface.hLine(3, yp + 2, _surface.width() - 4, INFO_BOTTOM);
const char *btn = (idx == 0) ? YES : NO;
_surface.writeString(btn, Common::Point((_bounds.width() - _surface.stringWidth(btn)) / 2, yp + 5), INFO_TOP);
@@ -129,11 +129,11 @@ void WidgetQuit::handleEvents() {
if (_select != _oldSelect) {
byte color = (_select == 1) ? COMMAND_HIGHLIGHTED : INFO_TOP;
int yp = (_surface.fontHeight() + 4) * 2 + 8;
- _surface.writeString(FIXED(Yes), Common::Point((_surface.w() - _surface.stringWidth(FIXED(Yes))) / 2, yp), color);
+ _surface.writeString(FIXED(Yes), Common::Point((_surface.width() - _surface.stringWidth(FIXED(Yes))) / 2, yp), color);
color = (_select == 0) ? COMMAND_HIGHLIGHTED : INFO_TOP;
yp += (_surface.fontHeight() + 7);
- _surface.writeString(FIXED(No), Common::Point((_surface.w() - _surface.stringWidth(FIXED(No))) / 2, yp), color);
+ _surface.writeString(FIXED(No), Common::Point((_surface.width() - _surface.stringWidth(FIXED(No))) / 2, yp), color);
}
_oldSelect = _select;
diff --git a/engines/sherlock/tattoo/widget_talk.cpp b/engines/sherlock/tattoo/widget_talk.cpp
index 6e7bde292f..b673f32d31 100644
--- a/engines/sherlock/tattoo/widget_talk.cpp
+++ b/engines/sherlock/tattoo/widget_talk.cpp
@@ -100,7 +100,7 @@ void WidgetTalk::load() {
// Set up the surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
// Form the background for the new window
makeInfoArea();
@@ -389,7 +389,7 @@ void WidgetTalk::render(Highlight highlightMode) {
if (highlightMode == HL_NO_HIGHLIGHTING || _statementLines[idx]._num == _selector ||
_statementLines[idx]._num == _oldSelector) {
// Erase the line contents
- _surface.fillRect(Common::Rect(3, yp, _surface.w() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
+ _surface.fillRect(Common::Rect(3, yp, _surface.width() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
// Different coloring based on whether the option has been previously chosen or not
byte color = (!talk._talkHistory[talk._converseNum][_statementLines[idx]._num]) ?
diff --git a/engines/sherlock/tattoo/widget_text.cpp b/engines/sherlock/tattoo/widget_text.cpp
index 86aa067301..a29cd2700f 100644
--- a/engines/sherlock/tattoo/widget_text.cpp
+++ b/engines/sherlock/tattoo/widget_text.cpp
@@ -80,6 +80,7 @@ void WidgetText::centerWindowOnSpeaker(int speaker) {
TattooScene &scene = *(TattooScene *)_vm->_scene;
Common::Point pt;
+ speaker &= 0x7f;
bool flag = _vm->readFlags(FLAG_PLAYER_IS_HOLMES);
if (people[HOLMES]._type == CHARACTER && ((speaker == HOLMES && flag) || (speaker == WATSON && !flag))) {
// Place the window centered above the player
@@ -165,7 +166,7 @@ void WidgetText::render(const Common::String &str) {
// Allocate a surface for the window
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
// Form the background for the new window
makeInfoArea();
@@ -194,7 +195,7 @@ void WidgetMessage::load(const Common::String &str, int time) {
// Allocate a surface for the window
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
// Form the background for the new window and write the line of text
makeInfoArea();
diff --git a/engines/sherlock/tattoo/widget_tooltip.cpp b/engines/sherlock/tattoo/widget_tooltip.cpp
index b29f45f531..1560cb9a80 100644
--- a/engines/sherlock/tattoo/widget_tooltip.cpp
+++ b/engines/sherlock/tattoo/widget_tooltip.cpp
@@ -47,7 +47,7 @@ void WidgetTooltipBase::draw() {
// Draw the widget directly onto the screen. Unlike other widgets, we don't draw to the back buffer,
// since nothing should be drawing on top of tooltips, so there's no need to store in the back buffer
- screen.transBlitFrom(_surface, Common::Point(_bounds.left - screen._currentScroll.x,
+ screen.SHtransBlitFrom(_surface, Common::Point(_bounds.left - screen._currentScroll.x,
_bounds.top - screen._currentScroll.y));
// Store a copy of the drawn area for later erasing
@@ -126,7 +126,7 @@ void WidgetTooltip::setText(const Common::String &str) {
// Reallocate the text surface with the new size
_surface.create(width, height);
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
if (line2.empty()) {
// Only a single line
diff --git a/engines/sherlock/tattoo/widget_verbs.cpp b/engines/sherlock/tattoo/widget_verbs.cpp
index 499afb2e79..5041888ffb 100644
--- a/engines/sherlock/tattoo/widget_verbs.cpp
+++ b/engines/sherlock/tattoo/widget_verbs.cpp
@@ -127,7 +127,7 @@ void WidgetVerbs::render() {
// Create the drawing surface
_surface.create(_bounds.width(), _bounds.height());
- _surface.fill(TRANSPARENCY);
+ _surface.clear(TRANSPARENCY);
// Draw basic background
makeInfoArea();
@@ -142,8 +142,8 @@ void WidgetVerbs::render() {
_surface.hLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 1, _bounds.width() - 4, INFO_MIDDLE);
_surface.hLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 2, _bounds.width() - 4, INFO_BOTTOM);
- _surface.transBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1) - 1));
- _surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
+ _surface.SHtransBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1) - 1));
+ _surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
(_surface.fontHeight() + 7) * (idx + 1) - 1));
}
}
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index 8a8967629d..4b91f50a61 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -136,7 +136,7 @@ const ExtraGuiOptions SkyMetaEngine::getExtraGuiOptions(const Common::String &ta
}
GameDescriptor SkyMetaEngine::findGame(const char *gameid) const {
- if (0 == scumm_stricmp(gameid, skySetting.gameid))
+ if (0 == scumm_stricmp(gameid, skySetting.gameId))
return skySetting;
return GameDescriptor();
}
@@ -175,7 +175,7 @@ GameList SkyMetaEngine::detectGames(const Common::FSList &fslist) const {
// Match found, add to list of candidates, then abort inner loop.
// The game detector uses US English by default. We want British
// English to match the recorded voices better.
- GameDescriptor dg(skySetting.gameid, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown);
+ GameDescriptor dg(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown);
const SkyVersion *sv = skyVersions;
while (sv->dinnerTableEntries) {
if (dinnerTableEntries == sv->dinnerTableEntries &&
@@ -223,7 +223,6 @@ SaveStateList SkyMetaEngine::listSaves(const char *target) const {
// Find all saves
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles("SKY-VM.###");
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
// Slot 0 is the autosave, if it exists.
// TODO: Check for the existence of the autosave -- but this require us
@@ -243,6 +242,8 @@ SaveStateList SkyMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/sword1/configure.engine b/engines/sword1/configure.engine
index 0578d176a9..1d17903b69 100644
--- a/engines/sword1/configure.engine
+++ b/engines/sword1/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 sword1 "Broken Sword" yes
+add_engine sword1 "Broken Sword" yes "" "" "highres"
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index 99c4bda9e9..0edf856125 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -128,17 +128,17 @@ GameList SwordMetaEngine::getSupportedGames() const {
}
GameDescriptor SwordMetaEngine::findGame(const char *gameid) const {
- if (0 == scumm_stricmp(gameid, sword1FullSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1FullSettings.gameId))
return sword1FullSettings;
- if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameId))
return sword1DemoSettings;
- if (0 == scumm_stricmp(gameid, sword1MacFullSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1MacFullSettings.gameId))
return sword1MacFullSettings;
- if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameId))
return sword1MacDemoSettings;
- if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameId))
return sword1PSXSettings;
- if (0 == scumm_stricmp(gameid, sword1PSXDemoSettings.gameid))
+ if (0 == scumm_stricmp(gameid, sword1PSXDemoSettings.gameId))
return sword1PSXDemoSettings;
return GameDescriptor();
}
@@ -241,7 +241,6 @@ SaveStateList SwordMetaEngine::listSaves(const char *target) const {
char saveName[40];
Common::StringArray filenames = saveFileMan->listSavefiles("sword1.###");
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
int slotNum = 0;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
@@ -259,6 +258,8 @@ SaveStateList SwordMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/sword1/objectman.cpp b/engines/sword1/objectman.cpp
index 07f19154a0..651e47f211 100644
--- a/engines/sword1/objectman.cpp
+++ b/engines/sword1/objectman.cpp
@@ -119,7 +119,7 @@ char *ObjectMan::lockText(uint32 textId, uint8 lang) {
return NULL;
addr += sizeof(Header);
if ((textId & ITM_ID) >= _resMan->readUint32(addr)) {
- // Workaround for missing sentences in some langages in the demo.
+ // Workaround for missing sentences in some languages in the demo.
switch(textId) {
case 8455194:
return const_cast<char *>(_translationId8455194[lang]);
@@ -160,7 +160,7 @@ char *ObjectMan::lockText(uint32 textId, uint8 lang) {
}
uint32 offset = _resMan->readUint32(addr + ((textId & ITM_ID) + 1) * 4);
if (offset == 0) {
- // Workaround bug for missing sentence in some langages in Syria (see bug #1977094).
+ // Workaround bug for missing sentence in some languages in Syria (see bug #1977094).
// We use the hardcoded text in this case.
if (textId == 2950145)
return const_cast<char *>(_translationId2950145[lang]);
@@ -223,7 +223,7 @@ void ObjectMan::saveLiveList(uint16 *dest) {
}
// String displayed when a subtitle sentence is missing in the cluster file.
-// It happens with at least one sentence in Syria in some langages (see bug
+// It happens with at least one sentence in Syria in some languages (see bug
// #1977094).
// Note: an empty string or a null pointer causes a crash.
diff --git a/engines/sword1/objectman.h b/engines/sword1/objectman.h
index fef1a8da3a..79be82c02f 100644
--- a/engines/sword1/objectman.h
+++ b/engines/sword1/objectman.h
@@ -62,7 +62,7 @@ private:
uint16 _liveList[TOTAL_SECTIONS]; //which sections are active
uint8 *_cptData[TOTAL_SECTIONS];
static char _missingSubTitleStr[];
- static const char *const _translationId2950145[7]; //translation for textId 2950145 (missing from cluster file for some langages)
+ static const char *const _translationId2950145[7]; //translation for textId 2950145 (missing from cluster file for some languages)
static const char *const _translationId8455194[7]; //translation for textId 8455194 (missing in the demo)
static const char *const _translationId8455195[7]; //translation for textId 8455195 (missing in the demo)
static const char *const _translationId8455196[7]; //translation for textId 8455196 (missing in the demo)
diff --git a/engines/sword1/router.cpp b/engines/sword1/router.cpp
index 72c8440e1c..0c2e9569b6 100644
--- a/engines/sword1/router.cpp
+++ b/engines/sword1/router.cpp
@@ -1455,7 +1455,7 @@ int32 Router::newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2) {
* newCheck differs from check in that that 4 route options are
* considered corresponding to actual walked routes.
*
- * Note distance doesnt take account of shrinking ???
+ * Note distance doesn't take account of shrinking ???
*
* Note Bars array must be properly calculated ie min max dx dy co
*********************************************************************/
diff --git a/engines/sword2/configure.engine b/engines/sword2/configure.engine
index 7153605433..a794e7287c 100644
--- a/engines/sword2/configure.engine
+++ b/engines/sword2/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 sword2 "Broken Sword II" yes
+add_engine sword2 "Broken Sword II" yes "" "" "highres"
diff --git a/engines/sword2/router.cpp b/engines/sword2/router.cpp
index d3f274dd2c..e95fa367a0 100644
--- a/engines/sword2/router.cpp
+++ b/engines/sword2/router.cpp
@@ -1712,7 +1712,7 @@ int32 Router::newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2) {
* newCheck differs from check in that that 4 route options are
* considered corresponding to actual walked routes.
*
- * Note distance doesnt take account of shrinking ???
+ * Note distance doesn't take account of shrinking ???
*
* Note Bars array must be properly calculated ie min max dx dy co
*********************************************************************/
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index baedecb52f..44371bf6cf 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -234,7 +234,6 @@ SaveStateList Sword2MetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -252,6 +251,8 @@ SaveStateList Sword2MetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/sword25/POTFILES b/engines/sword25/POTFILES
new file mode 100644
index 0000000000..f4b0e6fc27
--- /dev/null
+++ b/engines/sword25/POTFILES
@@ -0,0 +1 @@
+engines/sword25/detection.cpp
diff --git a/engines/sword25/configure.engine b/engines/sword25/configure.engine
index 6a9428c758..f805483f54 100644
--- a/engines/sword25/configure.engine
+++ b/engines/sword25/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 sword25 "Broken Sword 2.5" yes "" "" "png zlib 16bit"
+add_engine sword25 "Broken Sword 2.5" yes "" "" "png zlib 16bit highres"
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp
index df68d11609..4ca565c972 100644
--- a/engines/sword25/detection.cpp
+++ b/engines/sword25/detection.cpp
@@ -21,6 +21,7 @@
*/
#include "base/plugins.h"
+#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "sword25/sword25.h"
@@ -41,10 +42,17 @@ static const char *directoryGlobs[] = {
0
};
+static const ExtraGuiOption sword25ExtraGuiOption = {
+ _s("Use English speech"),
+ _s("Use English speech instead of German for every language other than German"),
+ "english_speech",
+ false
+};
+
class Sword25MetaEngine : public AdvancedMetaEngine {
public:
Sword25MetaEngine() : AdvancedMetaEngine(Sword25::gameDescriptions, sizeof(ADGameDescription), sword25Game) {
- _guioptions = GUIO1(GUIO_NOMIDI);
+ _guiOptions = GUIO1(GUIO_NOMIDI);
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
@@ -58,6 +66,7 @@ public:
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
virtual int getMaximumSaveSlot() const { return Sword25::PersistenceService::getSlotCount(); }
virtual SaveStateList listSaves(const char *target) const;
};
@@ -74,6 +83,12 @@ bool Sword25MetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsListSaves);
}
+const ExtraGuiOptions Sword25MetaEngine::getExtraGuiOptions(const Common::String &target) const {
+ ExtraGuiOptions options;
+ options.push_back(sword25ExtraGuiOption);
+ return options;
+}
+
SaveStateList Sword25MetaEngine::listSaves(const char *target) const {
Common::String pattern = target;
pattern = pattern + ".???";
diff --git a/engines/sword25/detection_tables.h b/engines/sword25/detection_tables.h
index b58f430fcf..927060bf18 100644
--- a/engines/sword25/detection_tables.h
+++ b/engines/sword25/detection_tables.h
@@ -29,7 +29,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("data.b25c", "f8b6e03ada2d2f6cf27fbc11ad1572e9", 654310588),
Common::EN_ANY,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -38,7 +38,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_fr.b25c", "690caf157387e06d2c3d1ca53c43f428", 1006043),
Common::FR_FRA,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -47,7 +47,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("data.b25c", "f8b6e03ada2d2f6cf27fbc11ad1572e9", 654310588),
Common::DE_DEU,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -56,7 +56,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_hr.b25c", "e881054d1f8ec1e527422fc521c25405", 1273217),
Common::HR_HRV,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -65,7 +65,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_it.b25c", "f3325666da0515cc2b42062e953c0889", 996197),
Common::IT_ITA,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -74,7 +74,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_pl.b25c", "49dc1a20f95391a808e475c49be2bac0", 1281799),
Common::PL_POL,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -83,7 +83,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_pt.b25c", "1df701432f9e13dcefe1adeb890b9c69", 993812),
Common::PT_BRA,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -92,7 +92,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_ru.b25c", "deb33dd2f90a71ff60181918a8ce5063", 1235378),
Common::RU_RUS,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
{
@@ -101,7 +101,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_es.b25c", "384c19072d83725f351bb9ecb4d3f02b", 987965),
Common::ES_ESP,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
// Hungarian "psylog" version.
@@ -112,7 +112,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("lang_hu.b25c", "7de51a3b4926a192549e75b1a7d81667", 1864915),
Common::HU_HUN,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
@@ -126,19 +126,22 @@ static const ADGameDescription gameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY,
Common::kPlatformUnknown,
- GF_EXTRACTED | ADGF_TESTING,
+ GF_EXTRACTED | ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
// Distributed by ScummVM
// Contains all language packs, English voice-overs and Hungarian version
+ // Mark it as Unknown Language since it contains multiple languages. If we
+ // mark it as English, then changing the language in-game causes the detection
+ // to fail the next time we try to start the engine.
{
"sword25",
"Latest version",
AD_ENTRY1s("data.b25c", "880a8a67faf4a4e7ab62cf114b771428", 827397764),
- Common::EN_ANY,
+ Common::UNK_LANG,
Common::kPlatformUnknown,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOASPECT)
},
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index eb0f0390dc..62a897a332 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -58,6 +58,8 @@ MoviePlayer::~MoviePlayer() {
}
bool MoviePlayer::loadMovie(const Common::String &filename, uint z) {
+ if (isMovieLoaded())
+ unloadMovie();
// Get the file and load it into the decoder
Common::SeekableReadStream *in = Kernel::getInstance()->getPackage()->getStream(filename);
_decoder.loadStream(in);
diff --git a/engines/sword25/fmv/movieplayer.h b/engines/sword25/fmv/movieplayer.h
index 95fb05ee60..b59b223b4c 100644
--- a/engines/sword25/fmv/movieplayer.h
+++ b/engines/sword25/fmv/movieplayer.h
@@ -67,7 +67,7 @@ public:
* movie file, it will be unloaded and, if necessary, stopped playing.
* @param Filename The filename of the movie file to be loaded
* @param Z Z indicates the position of the film on the main graphics layer
- * @return Returns false if an error occured while loading, otherwise true.
+ * @return Returns false if an error occurred while loading, otherwise true.
*/
bool loadMovie(const Common::String &filename, uint z);
diff --git a/engines/sword25/gfx/animationresource.cpp b/engines/sword25/gfx/animationresource.cpp
index 431d466658..423a2b86b4 100644
--- a/engines/sword25/gfx/animationresource.cpp
+++ b/engines/sword25/gfx/animationresource.cpp
@@ -211,8 +211,9 @@ bool AnimationResource::precacheAllFrames() const {
error("Could not precache \"%s\".", (*iter).fileName.c_str());
return false;
}
-#else
- Kernel::getInstance()->getResourceManager()->requestResource((*iter).fileName);
+#else
+ Resource *pResource = Kernel::getInstance()->getResourceManager()->requestResource((*iter).fileName);
+ pResource->release(); //unlock precached resource
#endif
}
diff --git a/engines/sword25/gfx/fontresource.cpp b/engines/sword25/gfx/fontresource.cpp
index c4d4c3c52e..1d7aedcb6e 100644
--- a/engines/sword25/gfx/fontresource.cpp
+++ b/engines/sword25/gfx/fontresource.cpp
@@ -103,8 +103,9 @@ bool FontResource::parserCallback_font(ParserNode *node) {
if (!_pKernel->getResourceManager()->precacheResource(_bitmapFileName)) {
error("Could not precache \"%s\".", _bitmapFileName.c_str());
}
-#else
- _pKernel->getResourceManager()->requestResource(_bitmapFileName);
+#else
+ Resource *pResource = _pKernel->getResourceManager()->requestResource(_bitmapFileName);
+ pResource->release(); //unlock precached resource
#endif
return true;
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index d409c538c0..769c9b1162 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -77,7 +77,8 @@ bool Text::setFont(const Common::String &font) {
return false;
}
#else
- getResourceManager()->requestResource(font);
+ Resource *pResource = getResourceManager()->requestResource(font);
+ pResource->release(); //unlock precached resource
_font = font;
updateFormat();
forceRefresh();
diff --git a/engines/sword25/kernel/kernel_script.cpp b/engines/sword25/kernel/kernel_script.cpp
index 1b7c6a6f14..40dcbd5b98 100644
--- a/engines/sword25/kernel/kernel_script.cpp
+++ b/engines/sword25/kernel/kernel_script.cpp
@@ -257,6 +257,7 @@ static int processMessages(lua_State *L) {
// to the closeWanted() opcode; see also the TODO comment in there.
lua_pushbooleancpp(L, !Engine::shouldQuit());
+ g_system->delayMillis(10);
return 1;
}
diff --git a/engines/sword25/package/packagemanager.cpp b/engines/sword25/package/packagemanager.cpp
index 2db4f2da74..457dda6268 100644
--- a/engines/sword25/package/packagemanager.cpp
+++ b/engines/sword25/package/packagemanager.cpp
@@ -56,7 +56,8 @@ static Common::String normalizePath(const Common::String &path, const Common::St
PackageManager::PackageManager(Kernel *pKernel) : Service(pKernel),
_currentDirectory(PATH_SEPARATOR),
- _rootFolder(ConfMan.get("path")) {
+ _rootFolder(ConfMan.get("path")),
+ _useEnglishSpeech(ConfMan.getBool("english_speech")) {
if (!registerScriptBindings())
error("Script bindings could not be registered.");
else
@@ -71,14 +72,34 @@ PackageManager::~PackageManager() {
}
+Common::String PackageManager::ensureSpeechLang(const Common::String &fileName) {
+ if (!_useEnglishSpeech || fileName.size() < 9 || !fileName.hasPrefix("/speech/"))
+ return fileName;
+
+ // Always keep German speech as a fallback in case the English speech pack is not present.
+ // However this means we cannot play with German text and English voice.
+ if (fileName.hasPrefix("/speech/de"))
+ return fileName;
+
+ Common::String newFileName = "/speech/en";
+ int fileIdx = 9;
+ while (fileIdx < fileName.size() && fileName[fileIdx] != '/')
+ ++fileIdx;
+ if (fileIdx < fileName.size())
+ newFileName += fileName.c_str() + fileIdx;
+
+ return newFileName;
+}
+
/**
* Scans through the archive list for a specified file
*/
Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &fileName) {
+ Common::String fileName2 = ensureSpeechLang(fileName);
// Loop through checking each archive
Common::List<ArchiveEntry *>::iterator i;
for (i = _archiveList.begin(); i != _archiveList.end(); ++i) {
- if (!fileName.hasPrefix((*i)->_mountPath)) {
+ if (!fileName2.hasPrefix((*i)->_mountPath)) {
// The mount path is in different subtree. Skipping
continue;
}
@@ -87,7 +108,7 @@ Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &
Common::Archive *archiveFolder = (*i)->archive;
// Construct relative path
- Common::String resPath(&fileName.c_str()[(*i)->_mountPath.size()]);
+ Common::String resPath(&fileName2.c_str()[(*i)->_mountPath.size()]);
if (archiveFolder->hasFile(resPath)) {
return archiveFolder->getMember(resPath);
@@ -203,23 +224,29 @@ bool PackageManager::changeDirectory(const Common::String &directory) {
}
Common::String PackageManager::getAbsolutePath(const Common::String &fileName) {
- return normalizePath(fileName, _currentDirectory);
+ return normalizePath(ensureSpeechLang(fileName), _currentDirectory);
}
bool PackageManager::fileExists(const Common::String &fileName) {
// FIXME: The current Zip implementation doesn't support getting a folder entry, which is needed for detecting
- // the English voick pack
- if (fileName == "/speech/en") {
+ // the English voice pack
+ Common::String fileName2 = ensureSpeechLang(fileName);
+ if (fileName2 == "/speech/en") {
// To get around this, change to detecting one of the files in the folder
- return getArchiveMember(normalizePath(fileName + "/APO0001.ogg", _currentDirectory));
+ bool exists = getArchiveMember(normalizePath(fileName2 + "/APO0001.ogg", _currentDirectory));
+ if (!exists && _useEnglishSpeech) {
+ _useEnglishSpeech = false;
+ warning("English speech not found");
+ }
+ return exists;
}
- Common::ArchiveMemberPtr fileNode = getArchiveMember(normalizePath(fileName, _currentDirectory));
+ Common::ArchiveMemberPtr fileNode = getArchiveMember(normalizePath(fileName2, _currentDirectory));
return fileNode;
}
int PackageManager::doSearch(Common::ArchiveMemberList &list, const Common::String &filter, const Common::String &path, uint typeFilter) {
- Common::String normalizedFilter = normalizePath(filter, _currentDirectory);
+ Common::String normalizedFilter = normalizePath(ensureSpeechLang(filter), _currentDirectory);
int num = 0;
if (path.size() > 0)
diff --git a/engines/sword25/package/packagemanager.h b/engines/sword25/package/packagemanager.h
index a1806a4046..5475cb02fc 100644
--- a/engines/sword25/package/packagemanager.h
+++ b/engines/sword25/package/packagemanager.h
@@ -87,6 +87,9 @@ private:
Common::String _currentDirectory;
Common::FSNode _rootFolder;
Common::List<ArchiveEntry *> _archiveList;
+
+ bool _useEnglishSpeech;
+ Common::String ensureSpeechLang(const Common::String &fileName);
Common::ArchiveMemberPtr getArchiveMember(const Common::String &fileName);
diff --git a/engines/sword25/script/luacallback.cpp b/engines/sword25/script/luacallback.cpp
index 72f7e01612..acfda498c6 100644
--- a/engines/sword25/script/luacallback.cpp
+++ b/engines/sword25/script/luacallback.cpp
@@ -119,7 +119,7 @@ void LuaCallback::invokeCallbackFunctions(lua_State *L, uint objectHandle) {
// Lua_pcall the function and the parameters pop themselves from the stack
if (lua_pcall(L, argumentCount, 0, 0) != 0) {
// An error has occurred
- error("An error occured executing a callback function: %s", lua_tostring(L, -1));
+ error("An error occurred executing a callback function: %s", lua_tostring(L, -1));
// Pop error message from the stack
lua_pop(L, 1);
diff --git a/engines/sword25/script/luascript.cpp b/engines/sword25/script/luascript.cpp
index e93289596b..3aca6676ac 100644
--- a/engines/sword25/script/luascript.cpp
+++ b/engines/sword25/script/luascript.cpp
@@ -214,7 +214,7 @@ bool LuaScriptEngine::executeBuffer(const byte *data, uint size, const Common::S
// Run buffer contents
if (lua_pcall(_state, 0, 0, -2) != 0) {
- error("An error occured while executing \"%s\":\n%s.",
+ error("An error occurred while executing \"%s\":\n%s.",
name.c_str(),
lua_tostring(_state, -1));
lua_pop(_state, 2);
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index 5223481d50..b6f2641714 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -120,7 +120,7 @@ Common::Error Sword25Engine::appStart() {
// Pass the command line to the script engine.
ScriptEngine *scriptPtr = Kernel::getInstance()->getScript();
if (!scriptPtr) {
- error("Script intialization failed.");
+ error("Script initialization failed.");
return Common::kUnknownError;
}
diff --git a/engines/sword25/util/lua/lbaselib.cpp b/engines/sword25/util/lua/lbaselib.cpp
index 659c61d956..ec044970ad 100644
--- a/engines/sword25/util/lua/lbaselib.cpp
+++ b/engines/sword25/util/lua/lbaselib.cpp
@@ -492,7 +492,7 @@ static int costatus (lua_State *L, lua_State *co) {
else
return CO_SUS; /* initial state */
}
- default: /* some error occured */
+ default: /* some error occurred */
return CO_DEAD;
}
}
diff --git a/engines/sword25/util/lua/ldo.cpp b/engines/sword25/util/lua/ldo.cpp
index a230097f2a..f4139cb9fc 100644
--- a/engines/sword25/util/lua/ldo.cpp
+++ b/engines/sword25/util/lua/ldo.cpp
@@ -111,10 +111,9 @@ static const char* luaErrorDescription[] = {
void luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
- // LUAI_THROW has been replaced with an error message in ScummVM, together
- // with the LUA error code and description
- //LUAI_THROW(L, L->errorJmp);
- error("LUA error occured, error code is %d (%s)", errcode, luaErrorDescription[errcode]);
+ // LUAI_THROW is sometimes used to ignore the error and restore LUA state
+ LUAI_THROW(L, L->errorJmp);
+ error("LUA error occurred, error code is %d (%s)", errcode, luaErrorDescription[errcode]);
}
else {
L->status = cast_byte(errcode);
diff --git a/engines/sword25/util/lua/luaconf.h b/engines/sword25/util/lua/luaconf.h
index fb85983998..53d0f55290 100644
--- a/engines/sword25/util/lua/luaconf.h
+++ b/engines/sword25/util/lua/luaconf.h
@@ -621,7 +621,7 @@ union luai_Cast { double l_d; long l_l; };
#else
/* default handling with long jumps */
-//#define LUAI_THROW(L,c) longjmp((c)->b, 1) // replaced with error() in ScummVM
+#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 4fd3a06311..caa7bdbec9 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -88,7 +88,7 @@ enum {
class TeenAgentMetaEngine : public AdvancedMetaEngine {
public:
TeenAgentMetaEngine() : AdvancedMetaEngine(teenAgentGameDescriptions, sizeof(ADGameDescription), teenAgentGames) {
- _singleid = "teenagent";
+ _singleId = "teenagent";
}
virtual const char *getName() const {
@@ -128,7 +128,6 @@ public:
pattern += ".##";
Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles(pattern);
- Common::sort(filenames.begin(), filenames.end());
SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
@@ -145,6 +144,8 @@ public:
saveList.push_back(SaveStateDescriptor(slot, buf));
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp
index 348ade62b0..7aff7a1805 100644
--- a/engines/testbed/detection.cpp
+++ b/engines/testbed/detection.cpp
@@ -49,7 +49,7 @@ class TestbedMetaEngine : public AdvancedMetaEngine {
public:
TestbedMetaEngine() : AdvancedMetaEngine(testbedDescriptions, sizeof(ADGameDescription), testbed_setting) {
_md5Bytes = 512;
- _singleid = "testbed";
+ _singleId = "testbed";
}
virtual const char *getName() const {
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 7cb291275c..2fde6e788a 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -85,7 +85,7 @@ static const PlainGameDescriptor tinselGames[] = {
class TinselMetaEngine : public AdvancedMetaEngine {
public:
TinselMetaEngine() : AdvancedMetaEngine(Tinsel::gameDescriptions, sizeof(Tinsel::TinselGameDescription), tinselGames) {
- _singleid = "tinsel";
+ _singleId = "tinsel";
}
virtual const char *getName() const {
@@ -136,7 +136,6 @@ SaveStateList TinselMetaEngine::listSaves(const char *target) const {
Common::String pattern = target;
pattern = pattern + ".###";
Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern);
- sort(files.begin(), files.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
int slotNum = 0;
@@ -160,6 +159,8 @@ SaveStateList TinselMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -227,8 +228,8 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile
// Check which files are included in some dw2 ADGameDescription *and* present
// in fslist without a '1' suffix character. Compute MD5s and file sizes for these files.
- for (g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
- if (strcmp(g->desc.gameid, "dw2") != 0)
+ for (g = &Tinsel::gameDescriptions[0]; g->desc.gameId != 0; ++g) {
+ if (strcmp(g->desc.gameId, "dw2") != 0)
continue;
for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) {
@@ -264,8 +265,8 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile
int maxFilesMatched = 0;
// MD5 based matching
- for (g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) {
- if (strcmp(g->desc.gameid, "dw2") != 0)
+ for (g = &Tinsel::gameDescriptions[0]; g->desc.gameId != 0; ++g) {
+ if (strcmp(g->desc.gameId, "dw2") != 0)
continue;
bool fileMissing = false;
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index 0282aff3cb..2ff96a9b64 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -164,7 +164,7 @@ static void t0WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
// Horizontal loop
for (int x = 0; x < pObj->width; ) {
- uint32 numBytes = READ_UINT32(srcP);
+ uint32 numBytes = READ_LE_UINT32(srcP);
srcP += sizeof(uint32);
bool repeatFlag = (numBytes & 0x80000000L) != 0;
numBytes &= 0x7fffffff;
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 2a9804263a..e0c1f8d1f9 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -381,11 +381,25 @@ MidiMusicPlayer::MidiMusicPlayer(TinselEngine *vm) {
bool milesAudioEnabled = false;
if (vm->getPlatform() == Common::kPlatformDOS) {
- // Enable Miles Audio for DOS only
- milesAudioEnabled = true;
+ // Enable Miles Audio for DOS platform only...
+ switch (vm->getGameID()) {
+ case GID_DW1:
+ if (!vm->getIsADGFDemo()) {
+ // ...for Discworld 1
+ milesAudioEnabled = true;
+ } else {
+ if (vm->isV1CD()) {
+ // ...and for Discworld 1 CD Demo
+ milesAudioEnabled = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
- if ((vm->getGameId() == GID_DW1) && (milesAudioEnabled)) {
+ if (milesAudioEnabled) {
// Discworld 1 (DOS) uses Miles Audio 3
// use our own Miles Audio drivers
//
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 77932a5cdf..2adddca4fd 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -820,7 +820,7 @@ const char *const TinselEngine::_textFiles[][3] = {
TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _random("tinsel"),
- _sound(0), _midiMusic(0), _pcmMusic(0), _bmv(0) {
+ _console(0), _sound(0), _midiMusic(0), _pcmMusic(0), _bmv(0) {
_vm = this;
_config = new Config(this);
diff --git a/engines/toltecs/configure.engine b/engines/toltecs/configure.engine
index be5533efa2..8310a6d6ef 100644
--- a/engines/toltecs/configure.engine
+++ b/engines/toltecs/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 toltecs "3 Skulls of the Toltecs" yes
+add_engine toltecs "3 Skulls of the Toltecs" yes "" "" "highres"
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index fb7d8121ff..7c707895e6 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -206,7 +206,7 @@ static const ExtraGuiOption toltecsExtraGuiOption = {
class ToltecsMetaEngine : public AdvancedMetaEngine {
public:
ToltecsMetaEngine() : AdvancedMetaEngine(Toltecs::gameDescriptions, sizeof(Toltecs::ToltecsGameDescription), toltecsGames) {
- _singleid = "toltecs";
+ _singleId = "toltecs";
}
virtual const char *getName() const {
@@ -266,7 +266,6 @@ SaveStateList ToltecsMetaEngine::listSaves(const char *target) const {
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- 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) {
@@ -284,6 +283,8 @@ SaveStateList ToltecsMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/tony/configure.engine b/engines/tony/configure.engine
index f85f45d158..2df4434982 100644
--- a/engines/tony/configure.engine
+++ b/engines/tony/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 tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit"
+add_engine tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit highres"
diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp
index 2f05c0abea..ec0b3e186b 100644
--- a/engines/tony/detection.cpp
+++ b/engines/tony/detection.cpp
@@ -118,7 +118,6 @@ SaveStateList TonyMetaEngine::listSaves(const char *target) const {
Common::String pattern = "tony.0##";
filenames = saveFileMan->listSavefiles(pattern);
- 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) {
@@ -137,6 +136,8 @@ SaveStateList TonyMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/toon/POTFILES b/engines/toon/POTFILES
new file mode 100644
index 0000000000..5bdfa37e5f
--- /dev/null
+++ b/engines/toon/POTFILES
@@ -0,0 +1 @@
+engines/toon/toon.cpp
diff --git a/engines/toon/configure.engine b/engines/toon/configure.engine
index 00c98f7d8a..689bce1c02 100644
--- a/engines/toon/configure.engine
+++ b/engines/toon/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 toon "Toonstruck" yes
+add_engine toon "Toonstruck" yes "" "" "highres"
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index e38ae3d2f5..5d2e0a9bca 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -127,7 +127,7 @@ static const char * const directoryGlobs[] = {
class ToonMetaEngine : public AdvancedMetaEngine {
public:
ToonMetaEngine() : AdvancedMetaEngine(Toon::gameDescriptions, sizeof(ADGameDescription), toonGames) {
- _singleid = "toon";
+ _singleId = "toon";
_maxScanDepth = 3;
_directoryGlobs = directoryGlobs;
}
@@ -176,7 +176,6 @@ SaveStateList ToonMetaEngine::listSaves(const char *target) const {
pattern += ".###";
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
@@ -208,6 +207,8 @@ SaveStateList ToonMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 9e2905f454..3ab23a1e51 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -27,6 +27,7 @@
#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/memstream.h"
+#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "engines/util.h"
@@ -3334,7 +3335,7 @@ bool ToonEngine::saveGame(int32 slot, const Common::String &saveGameDesc) {
Common::String savegameDescription;
if (slot == -1) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
savegameId = dialog->runModalWithCurrentTarget();
savegameDescription = dialog->getResultString();
delete dialog;
@@ -3426,7 +3427,7 @@ bool ToonEngine::loadGame(int32 slot) {
int16 savegameId;
if (slot == -1) {
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Restore game:", "Restore", false);
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
savegameId = dialog->runModalWithCurrentTarget();
delete dialog;
} else {
diff --git a/engines/touche/configure.engine b/engines/touche/configure.engine
index 777578e623..f35940ef47 100644
--- a/engines/touche/configure.engine
+++ b/engines/touche/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 touche "Touche: The Adventures of the Fifth Musketeer" yes
+add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes "" "" "highres"
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 1d0e136d69..dcb58ffae6 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -128,7 +128,7 @@ class ToucheMetaEngine : public AdvancedMetaEngine {
public:
ToucheMetaEngine() : AdvancedMetaEngine(Touche::gameDescriptions, sizeof(ADGameDescription), toucheGames) {
_md5Bytes = 4096;
- _singleid = "touche";
+ _singleId = "touche";
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
diff --git a/engines/tsage/blue_force/blueforce_dialogs.cpp b/engines/tsage/blue_force/blueforce_dialogs.cpp
index 5be27c9ae7..3697ca700e 100644
--- a/engines/tsage/blue_force/blueforce_dialogs.cpp
+++ b/engines/tsage/blue_force/blueforce_dialogs.cpp
@@ -161,7 +161,7 @@ void RightClickDialog::execute() {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
// Deactivate the graphics manager used for the dialog
@@ -242,7 +242,7 @@ void AmmoBeltDialog::execute() {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
_gfxManager.deactivate();
diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp
index e6e71399dc..2c5f9bd738 100644
--- a/engines/tsage/blue_force/blueforce_logic.cpp
+++ b/engines/tsage/blue_force/blueforce_logic.cpp
@@ -859,7 +859,7 @@ void SceneExt::endStrip() {
}
void SceneExt::clearScreen() {
- BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+ BF_GLOBALS._screen.clear();
}
/*--------------------------------------------------------------------------*/
@@ -1411,7 +1411,7 @@ void SceneMessage::process(Event &event) {
void SceneMessage::draw() {
- GfxSurface &surface = BF_GLOBALS._screenSurface;
+ GfxSurface &surface = BF_GLOBALS._screen;
// Clear the game area
surface.fillRect(Rect(0, 0, SCREEN_WIDTH, UI_INTERFACE_Y), 0);
diff --git a/engines/tsage/blue_force/blueforce_scenes6.cpp b/engines/tsage/blue_force/blueforce_scenes6.cpp
index 92534d3095..0d6b5c2487 100644
--- a/engines/tsage/blue_force/blueforce_scenes6.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes6.cpp
@@ -78,7 +78,7 @@ void Scene600::Action1::signal() {
pObj->animate(ANIM_MODE_NONE, NULL);
}
- BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+ BF_GLOBALS._screen.fillRect(BF_GLOBALS._screen.getBounds(), 0);
scene->loadScene(999);
setDelay(5);
break;
@@ -275,7 +275,7 @@ void Scene666::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
loadScene(999);
- BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+ BF_GLOBALS._screen.fillRect(BF_GLOBALS._screen.getBounds(), 0);
if (BF_GLOBALS._dayNumber == 0) {
BF_GLOBALS._dayNumber = 1;
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
index d1faca5dac..7240c91720 100644
--- a/engines/tsage/converse.cpp
+++ b/engines/tsage/converse.cpp
@@ -469,7 +469,7 @@ int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
while (!g_globals->_events.getEvent(event, EVENT_KEYPRESS | EVENT_BUTTON_DOWN | EVENT_MOUSE_MOVE) &&
!g_vm->shouldQuit()) {
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
if (g_vm->shouldQuit())
break;
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index d4068c25c9..985d16b031 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -1467,7 +1467,7 @@ void ScenePalette::fade(const byte *adjustData, bool fullAdjust, int percent) {
// Set the altered palette
g_system->getPaletteManager()->setPalette((const byte *)&tempPalette[0], 0, 256);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
PaletteRotation *ScenePalette::addRotation(int start, int end, int rotationMode, int duration, Action *action) {
@@ -1524,11 +1524,11 @@ void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) {
if (g_vm->getGameID() != GType_Ringworld && g_vm->getGameID() != GType_Sherlock1)
tempRect.setHeight(T2_GLOBALS._interfaceY);
- g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface,
+ g_globals->_screen.copyFrom(g_globals->_sceneManager._scene->_backSurface,
tempRect, Rect(0, 0, tempRect.width(), tempRect.height()), NULL);
if (g_vm->getGameID() == GType_Ringworld2 && !GLOBALS._player._uiEnabled
&& T2_GLOBALS._interfaceY == UI_INTERFACE_Y) {
- g_globals->_screenSurface.fillRect(Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT - 1), 0);
+ g_globals->_screen.fillRect(Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT - 1), 0);
}
for (SynchronizedList<PaletteModifier *>::iterator i = tempPalette._listeners.begin(); i != tempPalette._listeners.end(); ++i)
@@ -1796,7 +1796,7 @@ void SceneItem::display(int resNum, int lineNum, ...) {
// Keep event on-screen until a mouse or keypress
while (!g_vm->shouldQuit() && !g_globals->_events.getEvent(event,
EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) {
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
if ((g_vm->getGameID() == GType_Ringworld2) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
@@ -2816,7 +2816,7 @@ void SceneObject::updateScreen() {
destRect.translate(-sceneBounds.left, -sceneBounds.top);
srcRect.translate(-g_globals->_sceneOffset.x, -g_globals->_sceneOffset.y);
- g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface, srcRect, destRect);
+ g_globals->_screen.copyFrom(g_globals->_sceneManager._scene->_backSurface, srcRect, destRect);
}
}
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index f85d8433f3..fe555f2fdb 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -40,7 +40,7 @@ struct tSageGameDescription {
};
const char *TSageEngine::getGameId() const {
- return _gameDescription->desc.gameid;
+ return _gameDescription->desc.gameId;
}
uint32 TSageEngine::getGameID() const {
@@ -75,7 +75,7 @@ enum {
class TSageMetaEngine : public AdvancedMetaEngine {
public:
TSageMetaEngine() : AdvancedMetaEngine(TsAGE::gameDescriptions, sizeof(TsAGE::tSageGameDescription), tSageGameTitles) {
- _singleid = "tsage";
+ _singleId = "tsage";
}
virtual const char *getName() const {
@@ -117,7 +117,6 @@ public:
pattern += ".###";
Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end());
TsAGE::tSageSavegameHeader header;
SaveStateList saveList;
@@ -141,6 +140,8 @@ public:
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h
index 109ac353e6..f331ecdab5 100644
--- a/engines/tsage/detection_tables.h
+++ b/engines/tsage/detection_tables.h
@@ -165,7 +165,7 @@ static const tSageGameDescription gameDescriptions[] = {
AD_ENTRY1s("r2rw.rlb", "df6c25622387007788ca36d99362c1f0", 47586928),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_CD | ADGF_TESTING,
+ ADGF_CD,
GUIO0()
},
GType_Ringworld2,
@@ -179,7 +179,7 @@ static const tSageGameDescription gameDescriptions[] = {
AD_ENTRY1s("r2rw.rlb", "c8e1a82c67c3caf57368eadde13dc15f", 32384464),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_CD | ADGF_TESTING,
+ ADGF_CD,
GUIO0()
},
GType_Ringworld2,
diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp
index 0491c043a4..1fa17022de 100644
--- a/engines/tsage/events.cpp
+++ b/engines/tsage/events.cpp
@@ -50,7 +50,7 @@ bool EventsClass::pollEvent() {
++_frameNumber;
// Update screen
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
if (!g_system->getEventManager()->pollEvent(_event)) return false;
@@ -400,7 +400,7 @@ void EventsClass::delay(int numFrames) {
_priorFrameTime = g_system->getMillis();
}
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
_prevDelayFrame = _frameNumber;
_priorFrameTime = g_system->getMillis();
}
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index b880f35007..b95bea3b23 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -59,7 +59,7 @@ static SavedObject *classFactoryProc(const Common::String &className) {
/*--------------------------------------------------------------------------*/
-Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface),
+Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screen),
_randomSource("tsage"), _color1(0), _color2(255), _color3(255) {
reset();
_stripNum = 0;
@@ -119,7 +119,7 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
_color3 = 4;
_dialogCenter.y = 100;
}
- _screenSurface.setScreenSurface();
+
_gfxManagers.push_back(&_gfxManagerInstance);
_sceneObjects = &_sceneObjectsInstance;
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
index 1194fe8b9c..e1ebe261dc 100644
--- a/engines/tsage/globals.h
+++ b/engines/tsage/globals.h
@@ -30,6 +30,7 @@
#include "tsage/events.h"
#include "tsage/sound.h"
#include "tsage/saveload.h"
+#include "tsage/screen.h"
#include "tsage/user_interface.h"
namespace TsAGE {
@@ -38,7 +39,7 @@ class Globals : public SavedObject {
private:
static void dispatchSound(ASound *obj);
public:
- GfxSurface _screenSurface;
+ Screen _screen;
GfxManager _gfxManagerInstance;
Common::List<GfxManager *> _gfxManagers;
SceneHandler *_sceneHandler;
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 156503fb51..58fa5b8094 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -229,123 +229,43 @@ void Rect::synchronize(Serializer &s) {
/*--------------------------------------------------------------------------*/
-GfxSurface::GfxSurface() : _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
+GfxSurface::GfxSurface() : Graphics::ManagedSurface(), _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
_disableUpdates = false;
_lockSurfaceCtr = 0;
- _customSurface = NULL;
_transColor = -1;
- _trackDirtyRects = false;
_flags = 0;
}
-GfxSurface::GfxSurface(const GfxSurface &s) {
+GfxSurface::GfxSurface(const GfxSurface &s): Graphics::ManagedSurface() {
_lockSurfaceCtr = 0;
- _customSurface = NULL;
- _trackDirtyRects = false;
- *this = s;
+
+ operator=(s);
}
GfxSurface::~GfxSurface() {
- clear();
+ // Sanity check.. GfxSurface should always be just referencing _rawSurface,
+ // and not directly managing it's own surface
+ assert(disposeAfterUse() == DisposeAfterUse::NO);
}
-void GfxSurface::clear() {
- if (_customSurface) {
- _customSurface->free();
- delete _customSurface;
- _customSurface = NULL;
- }
-}
-
-/**
- * Specifies that the surface will encapsulate the ScummVM screen surface
- */
-void GfxSurface::setScreenSurface() {
- _trackDirtyRects = true;
- create(SCREEN_WIDTH, SCREEN_HEIGHT);
-}
-
-/**
- * Updates the physical screen with the screen surface buffer
- */
-void GfxSurface::updateScreen() {
- assert(_trackDirtyRects);
-
- // Merge any overlapping dirty rects
- mergeDirtyRects();
-
- // Loop through the dirty rect list to copy the affected areas to the sc
- for (Common::List<Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
- Rect r = *i;
-
- // Make sure that there is something to update. If not, skip this
- // rectangle. An example case is the speedbike closeup at the beginning
- // of Ringworld (third screen).
- if (r.isEmpty())
- continue;
-
- const byte *srcP = (const byte *)_customSurface->getBasePtr(r.left, r.top);
- g_system->copyRectToScreen(srcP, _customSurface->pitch, r.left, r.top,
- r.width(), r.height());
- }
-
- // Update the physical screen
- g_system->updateScreen();
-
- // Now that the dirty rects have been copied, clear the dirty rect list
- _dirtyRects.clear();
-}
+void GfxSurface::create(uint16 width, uint16 height) {
+ free();
-/**
- * Adds a rect to the dirty rect list
- */
-void GfxSurface::addDirtyRect(const Rect &r) {
- if (_trackDirtyRects) {
- // Get the bounds and adjust to allow for sub-screen areas
- Rect r2 = r;
- r2.translate(_bounds.left, _bounds.top);
-
- // Add to the dirty rect list
- r2.right = MIN(r2.right + 1, SCREEN_WIDTH);
- r2.bottom = MIN(r2.bottom + 1, SCREEN_HEIGHT);
-
- if (r2.isValidRect())
- _dirtyRects.push_back(r2);
- }
+ _rawSurface.create(width, height);
+ setBounds(Rect(0, 0, width, height));
}
-
-
-/**
- * Specifies that the surface should maintain it's own internal surface
- */
-void GfxSurface::create(int width, int height) {
- assert((width >= 0) && (height >= 0));
-
- if (_customSurface) {
- _customSurface->free();
- delete _customSurface;
- }
- _customSurface = new Graphics::Surface();
- _customSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
- Common::fill((byte *)_customSurface->getPixels(), (byte *)_customSurface->getBasePtr(0, height), 0);
- _bounds = Rect(0, 0, width, height);
+void GfxSurface::setBounds(const Rect &bounds) {
+ _bounds = bounds;
+ Graphics::ManagedSurface::create(_rawSurface, bounds);
}
/**
* Locks the surface for access, and returns a raw ScummVM surface to manipulate it
*/
-Graphics::Surface GfxSurface::lockSurface() {
+Graphics::ManagedSurface &GfxSurface::lockSurface() {
++_lockSurfaceCtr;
-
- Graphics::Surface *src = _customSurface;
- assert(src);
-
- // Setup the returned surface either as one pointing to the same pixels as the source, or
- // as a subset of the source one based on the currently set bounds
- Graphics::Surface result;
- result.init(_bounds.width(), _bounds.height(), src->pitch, src->getBasePtr(_bounds.left, _bounds.top), src->format);
- return result;
+ return *this;
}
/**
@@ -367,69 +287,43 @@ void GfxSurface::synchronize(Serializer &s) {
if (s.isSaving()) {
// Save contents of the surface
- if (_customSurface) {
- s.syncAsSint16LE(_customSurface->w);
- s.syncAsSint16LE(_customSurface->h);
- s.syncBytes((byte *)_customSurface->getPixels(), _customSurface->w * _customSurface->h);
+ if (disposeAfterUse() == DisposeAfterUse::YES) {
+ s.syncAsSint16LE(this->w);
+ s.syncAsSint16LE(this->h);
+ s.syncBytes((byte *)getPixels(), this->w * this->h);
} else {
int zero = 0;
s.syncAsSint16LE(zero);
s.syncAsSint16LE(zero);
}
} else {
- int w = 0, h = 0;
- s.syncAsSint16LE(w);
- s.syncAsSint16LE(h);
-
- if ((w == 0) || (h == 0)) {
- if (_customSurface)
- delete _customSurface;
- _customSurface = NULL;
+ int xSize = 0, ySize = 0;
+ s.syncAsSint16LE(xSize);
+ s.syncAsSint16LE(ySize);
+
+ if (xSize == 0 || ySize == 0) {
+ free();
} else {
- create(w, h);
- s.syncBytes((byte *)_customSurface->getPixels(), w * h);
+ create(xSize, ySize);
+ s.syncBytes((byte *)getPixels(), xSize * ySize);
}
}
}
-/**
- * Fills a specified rectangle on the surface with the specified color
- *
- * @bounds Area to fill
- * @color Color to use
- */
-void GfxSurface::fillRect(const Rect &bounds, int color) {
- Graphics::Surface surface = lockSurface();
- surface.fillRect(bounds, color);
- unlockSurface();
- addDirtyRect(bounds);
-}
-
GfxSurface &GfxSurface::operator=(const GfxSurface &s) {
assert(_lockSurfaceCtr == 0);
assert(s._lockSurfaceCtr == 0);
- if (_customSurface) {
- _customSurface->free();
- delete _customSurface;
- }
-
- _customSurface = s._customSurface;
_disableUpdates = s._disableUpdates;
_bounds = s._bounds;
_centroid = s._centroid;
_transColor = s._transColor;
_flags = s._flags;
- if (_customSurface) {
- // Surface owns the internal data, so replicate it so new surface owns it's own
- _customSurface = new Graphics::Surface();
- _customSurface->create(s._customSurface->w, s._customSurface->h, Graphics::PixelFormat::createFormatCLUT8());
- const byte *srcP = (const byte *)s._customSurface->getPixels();
- byte *destP = (byte *)_customSurface->getPixels();
-
- Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP);
- }
+ // Copy the source's surface
+ create(s.w, s.h);
+ blitFrom(s);
+ setBounds(s.getBounds());
return *this;
}
@@ -474,7 +368,7 @@ bool GfxSurface::displayText(const Common::String &msg, const Common::Point &pt)
/**
* Loads a quarter of a screen from a resource
*/
-void GfxSurface::loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection) {
+void GfxSurface::loadScreenSection(Graphics::ManagedSurface &dest, int xHalf, int yHalf, int xSection, int ySection) {
int screenNum = g_globals->_sceneManager._scene->_activeScreenNumber;
Rect updateRect(0, 0, 160, 100);
updateRect.translate(xHalf * 160, yHalf * 100);
@@ -682,50 +576,6 @@ void GfxSurface::draw(const Common::Point &pt, Rect *rect) {
}
}
-/**
- * Merges any clipping rectangles that overlap to try and reduce
- * the total number of clip rectangles.
- */
-void GfxSurface::mergeDirtyRects() {
- if (_dirtyRects.size() <= 1)
- return;
-
- Common::List<Rect>::iterator rOuter, rInner;
-
- for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
- rInner = rOuter;
- while (++rInner != _dirtyRects.end()) {
-
- if ((*rOuter).intersects(*rInner)) {
- // these two rectangles overlap or
- // are next to each other - merge them
-
- unionRectangle(*rOuter, *rOuter, *rInner);
-
- // remove the inner rect from the list
- _dirtyRects.erase(rInner);
-
- // move back to beginning of list
- rInner = rOuter;
- }
- }
- }
-}
-
-/**
- * Creates the union of two rectangles.
- * Returns True if there is a union.
- * @param pDest destination rectangle that is to receive the new union
- * @param pSrc1 a source rectangle
- * @param pSrc2 a source rectangle
- */
-bool GfxSurface::unionRectangle(Common::Rect &destRect, const Rect &src1, const Rect &src2) {
- destRect = src1;
- destRect.extend(src2);
-
- return !destRect.isEmpty();
-}
-
/*--------------------------------------------------------------------------*/
GfxElement::GfxElement() {
@@ -762,17 +612,16 @@ void GfxElement::highlight() {
Rect tempRect(_bounds);
tempRect.collapse(g_globals->_gfxEdgeAdjust - 1, g_globals->_gfxEdgeAdjust - 1);
- for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) {
- byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp);
- for (int xp = tempRect.left; xp < tempRect.right; ++xp, ++lineP) {
+ Graphics::Surface dest = surface.getSubArea(tempRect);
+
+ for (int yp = 0; yp < dest.h; ++yp) {
+ byte *lineP = (byte *)dest.getBasePtr(0, yp);
+ for (int xp = 0; xp < tempRect.right; ++xp, ++lineP) {
if (*lineP == _colors.background) *lineP = _colors.foreground;
else if (*lineP == _colors.foreground) *lineP = _colors.background;
}
}
- // Mark the affected area as dirty
- gfxManager.getSurface().addDirtyRect(tempRect);
-
// Release the surface
gfxManager.unlockSurface();
}
@@ -816,10 +665,11 @@ void GfxElement::drawFrame() {
// Loop through the surface area to replace each pixel
// with its proper shaded replacement
- Graphics::Surface surface = gfxManager.lockSurface();
- for (int y = tempRect.top; y < tempRect.bottom; ++y) {
- byte *lineP = (byte *)surface.getBasePtr(tempRect.left, y);
- for (int x = 0; x < tempRect.width(); ++x) {
+ Graphics::Surface dest = gfxManager.getSurface().getSubArea(tempRect);
+
+ for (int y = 0; y < dest.h; ++y) {
+ byte *lineP = (byte *)dest.getBasePtr(0, y);
+ for (int x = 0; x < dest.w; ++x) {
*lineP = transList[*lineP];
lineP++;
}
@@ -827,27 +677,24 @@ void GfxElement::drawFrame() {
// Draw the edge frame
// Outer frame border
- surface.hLine(tempRect.left + 2, tempRect.top, tempRect.right - 2, 0);
- surface.hLine(tempRect.left + 2, tempRect.bottom, tempRect.right - 2, 0);
- surface.vLine(tempRect.left, tempRect.top + 2, tempRect.bottom - 2, 0);
- surface.vLine(tempRect.right, tempRect.top + 2, tempRect.bottom - 2, 0);
- *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.top + 1)) = 0;
- *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.top + 1)) = 0;
- *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.bottom - 1)) = 0;
- *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.bottom - 1)) = 0;
+ dest.hLine(2, 0, dest.w - 2, 0);
+ dest.hLine(2, dest.h - 1, dest.w - 2, 0);
+ dest.vLine(0, 2, dest.h - 2, 0);
+ dest.vLine(tempRect.right, 2, dest.h - 2, 0);
+ *((byte *)dest.getBasePtr(1, 1)) = 0;
+ *((byte *)dest.getBasePtr(dest.w - 1, 1)) = 0;
+ *((byte *)dest.getBasePtr(1, dest.h - 1)) = 0;
+ *((byte *)dest.getBasePtr(dest.w - 1, dest.h - 1)) = 0;
// Inner frame border
- surface.hLine(tempRect.left + 2, tempRect.top + 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColor);
- surface.hLine(tempRect.left + 2, tempRect.bottom - 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColor);
- surface.vLine(tempRect.left + 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
- surface.vLine(tempRect.right - 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
- *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
- *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
- *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
- *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
-
- gfxManager.unlockSurface();
- gfxManager.getSurface().addDirtyRect(tempRect);
+ dest.hLine(2, 1, dest.w - 2, R2_GLOBALS._frameEdgeColor);
+ dest.hLine(2, dest.h - 1, dest.w - 2, R2_GLOBALS._frameEdgeColor);
+ dest.vLine(1, 2, dest.h - 2, R2_GLOBALS._frameEdgeColor);
+ dest.vLine(dest.w - 1, 2, dest.h - 2, R2_GLOBALS._frameEdgeColor);
+ *((byte *)dest.getBasePtr(2, 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)dest.getBasePtr(dest.w - 2, 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)dest.getBasePtr(2, dest.h - 2)) = R2_GLOBALS._frameEdgeColor;
+ *((byte *)dest.getBasePtr(dest.w - 2, dest.h - 2)) = R2_GLOBALS._frameEdgeColor;
} else {
// Fill dialog content with specified background color
@@ -1236,7 +1083,7 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
_gfxManager.deactivate();
@@ -1269,7 +1116,7 @@ void GfxDialog::setPalette() {
/*--------------------------------------------------------------------------*/
-GfxManager::GfxManager() : _surface(g_globals->_screenSurface), _oldManager(NULL) {
+GfxManager::GfxManager() : _surface(g_globals->_screen), _oldManager(NULL) {
_font.setOwner(this);
_font._fillFlag = false;
_bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -1563,23 +1410,24 @@ int GfxFont::writeChar(const char ch) {
int yOffset = (_fontData[charOffset + 1] >> 3) & 0x1f;
const uint8 *dataP = &_fontData[charOffset + 2];
- // Lock the surface for access
- Graphics::Surface surfacePtr = _gfxManager->lockSurface();
-
Rect charRect;
charRect.set(0, 0, charWidth, _fontSize.y);
charRect.translate(_topLeft.x + _position.x, _topLeft.y + _position.y + yOffset);
+ // Get the sub-section of the screen to update
+ Graphics::Surface dest = _gfxManager->getSurface().getSubArea(charRect);
+
if (_fillFlag)
- surfacePtr.fillRect(charRect, _colors.background);
+ dest.fillRect(charRect, _colors.background);
charRect.bottom = charRect.top + charHeight;
+ assert(charRect.height() <= dest.h);
// Display the character
int bitCtr = 0;
uint8 v = 0;
- for (int yp = charRect.top; yp < charRect.bottom; ++yp) {
- byte *destP = (byte *)surfacePtr.getBasePtr(charRect.left, yp);
+ for (int yp = 0; yp < charHeight; ++yp) {
+ byte *destP = (byte *)dest.getBasePtr(0, yp);
for (int xs = 0; xs < charRect.width(); ++xs, ++destP) {
// Get the next color index to use
@@ -1599,13 +1447,9 @@ int GfxFont::writeChar(const char ch) {
}
}
- // Mark the affected area as dirty
- _gfxManager->getSurface().addDirtyRect(charRect);
-
// Move the text writing position
_position.x += charWidth;
- _gfxManager->unlockSurface();
return charWidth;
}
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index 25f7aea8cd..3b395b7625 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -28,7 +28,7 @@
#include "common/list.h"
#include "common/rect.h"
#include "common/system.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
namespace TsAGE {
@@ -73,20 +73,13 @@ public:
enum FrameFlag { FRAME_FLIP_CENTROID_X = 4, FRAME_FLIP_CENTROID_Y = 8 };
-class GfxSurface {
+class GfxSurface: virtual public Graphics::ManagedSurface {
private:
- Graphics::Surface *_customSurface;
int _lockSurfaceCtr;
+ Graphics::ManagedSurface _rawSurface;
bool _disableUpdates;
Rect _bounds;
-
- bool _trackDirtyRects;
- Common::List<Rect> _dirtyRects;
-
- void mergeDirtyRects();
- bool unionRectangle(Common::Rect &destRect, const Rect &src1, const Rect &src2);
-
public:
Common::Point _centroid;
int _transColor;
@@ -95,17 +88,13 @@ public:
public:
GfxSurface();
GfxSurface(const GfxSurface &s);
- ~GfxSurface();
+ virtual ~GfxSurface();
- void setScreenSurface();
- void updateScreen();
- void addDirtyRect(const Rect &r);
- Graphics::Surface lockSurface();
+ Graphics::ManagedSurface &lockSurface();
void unlockSurface();
void synchronize(Serializer &s);
- void create(int width, int height);
- void clear();
- void setBounds(const Rect &bounds) { _bounds = bounds; }
+ virtual void create(uint16 width, uint16 height);
+ void setBounds(const Rect &bounds);
const Rect &getBounds() const { return _bounds; }
void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds,
@@ -119,10 +108,9 @@ public:
copyFrom(src, tempRect, priorityRegion);
}
void draw(const Common::Point &pt, Rect *rect = NULL);
- void fillRect(const Rect &bounds, int color);
GfxSurface &operator=(const GfxSurface &s);
- static void loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection);
+ static void loadScreenSection(Graphics::ManagedSurface &dest, int xHalf, int yHalf, int xSection, int ySection);
static bool displayText(const Common::String &msg, const Common::Point &pt = Common::Point(160, 100));
};
@@ -281,7 +269,7 @@ public:
void getStringBounds(const char *s, Rect &bounds, int maxWidth);
void setDialogPalette();
- Graphics::Surface lockSurface() {
+ Graphics::ManagedSurface lockSurface() {
_surface.setBounds(_bounds);
return _surface.lockSurface();
}
diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk
index e23b157a95..b58c748567 100644
--- a/engines/tsage/module.mk
+++ b/engines/tsage/module.mk
@@ -47,6 +47,7 @@ MODULE_OBJS := \
ringworld2/ringworld2_vampire.o \
saveload.o \
scenes.o \
+ screen.o \
sherlock/sherlock_logo.o \
sound.o \
staticres.o \
diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp
index 1dd3bc158b..9fa17f3920 100644
--- a/engines/tsage/ringworld/ringworld_dialogs.cpp
+++ b/engines/tsage/ringworld/ringworld_dialogs.cpp
@@ -181,7 +181,7 @@ void RightClickDialog::execute() {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
_gfxManager.deactivate();
@@ -391,7 +391,7 @@ void InventoryDialog::execute() {
Event event;
while (!g_globals->_events.getEvent(event) && !g_vm->shouldQuit()) {
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
if (g_vm->shouldQuit())
break;
@@ -439,7 +439,7 @@ void InventoryDialog::execute() {
// Inventory item selected
InvObject *invObject = static_cast<GfxInvImage *>(hiliteObj)->_invObject;
if (lookFlag) {
- g_globals->_screenSurface.displayText(invObject->_description);
+ g_globals->_screen.displayText(invObject->_description);
} else {
RING_INVENTORY._selectedItem = invObject;
invObject->setCursor();
diff --git a/engines/tsage/ringworld/ringworld_logic.cpp b/engines/tsage/ringworld/ringworld_logic.cpp
index 1d8293cffd..354c86abfc 100644
--- a/engines/tsage/ringworld/ringworld_logic.cpp
+++ b/engines/tsage/ringworld/ringworld_logic.cpp
@@ -320,7 +320,7 @@ void SceneArea::wait() {
// Wait until a mouse or keypress
Event event;
while (!g_vm->shouldQuit() && !g_globals->_events.getEvent(event)) {
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
}
diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp
index a515224964..a9ed7af870 100644
--- a/engines/tsage/ringworld/ringworld_scenes3.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes3.cpp
@@ -532,7 +532,7 @@ void Scene2100::Action1::signal() {
// Wait for an event
Event event;
if (!g_globals->_events.getEvent(event)) {
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
continue;
}
@@ -2265,7 +2265,7 @@ void Scene2150::Action1::signal() {
// Wait for an event
Event event;
if (!g_globals->_events.getEvent(event)) {
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
continue;
}
@@ -5119,7 +5119,7 @@ void Scene2320::Action3::signal() {
// Wait for an event
Event event;
if (!g_globals->_events.getEvent(event)) {
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
continue;
}
diff --git a/engines/tsage/ringworld/ringworld_scenes5.cpp b/engines/tsage/ringworld/ringworld_scenes5.cpp
index cb8a89de80..98859f32ee 100644
--- a/engines/tsage/ringworld/ringworld_scenes5.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes5.cpp
@@ -2813,7 +2813,7 @@ void Scene4150::Action1::signal() {
case 4: {
for (int idx = 100; idx >= 0; idx -= 5) {
g_globals->_scenePalette.fade(adjustData, false, idx);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
}
@@ -2841,7 +2841,7 @@ void Scene4150::Action1::signal() {
case 7:
for (int idx = 100; idx >= 0; idx -= 5) {
g_globals->_scenePalette.fade(adjustData, false, idx);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
}
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index 99f88a1687..027fb558db 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -154,7 +154,7 @@ int RightClickDialog::execute() {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
// Execute the specified action
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index d24541932f..ecaa671bd7 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -351,7 +351,7 @@ SceneExt::SceneExt(): Scene() {
_preventSaving = false;
// Reset screen clipping area
- R2_GLOBALS._screenSurface._clipRect = Rect();
+ R2_GLOBALS._screen._clipRect = Rect();
// WORKAROUND: In the original, playing animations don't reset the global _animationCtr
// counter as scene changes unless the playing animation explicitly finishes. For now,
@@ -513,7 +513,7 @@ void SceneExt::endStrip() {
}
void SceneExt::clearScreen() {
- R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0);
+ R2_GLOBALS._screen.fillRect(R2_GLOBALS._screen.getBounds(), 0);
}
void SceneExt::refreshBackground(int xAmount, int yAmount) {
@@ -543,15 +543,12 @@ void SceneExt::refreshBackground(int xAmount, int yAmount) {
int screenSize = g_vm->_memoryManager.getSize(dataP);
// Lock the background for update
- Graphics::Surface s = _backSurface.lockSurface();
- assert(screenSize == (s.w * s.h));
+ assert(screenSize == (_backSurface.w * _backSurface.h));
+ Graphics::Surface s = _backSurface.getSubArea(Common::Rect(0, 0, _backSurface.w, _backSurface.h));
- // Copy the data
+ // Copy the data into the surface
byte *destP = (byte *)s.getPixels();
Common::copy(dataP, dataP + (s.w * s.h), destP);
- _backSurface.unlockSurface();
-
- R2_GLOBALS._screenSurface.addDirtyRect(_backSurface.getBounds());
// Free the resource data
DEALLOCATE(dataP);
@@ -601,7 +598,7 @@ void SceneExt::loadBlankScene() {
_backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2);
_backSurface.fillRect(_backSurface.getBounds(), 0);
- R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0);
+ R2_GLOBALS._screen.fillRect(R2_GLOBALS._screen.getBounds(), 0);
}
/*--------------------------------------------------------------------------*/
@@ -1966,10 +1963,9 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
byte *sliceData1 = sliceDataStart;
Rect playerBounds = _screenBounds;
- int y = _screenBounds.top;
- R2_GLOBALS._screenSurface.addDirtyRect(playerBounds);
- Graphics::Surface surface = R2_GLOBALS._screenSurface.lockSurface();
+ Graphics::Surface dest = R2_GLOBALS._screen.getSubArea(playerBounds);
+ int y = 0;
// Handle different drawing modes
switch (slice._drawMode) {
@@ -1980,7 +1976,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
// TODO: Check of _subData._drawType was done for two different kinds of
// line slice drawing in original
const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, y++);
+ byte *pDest = (byte *)dest.getBasePtr(0, y++);
Common::copy(pSrc, pSrc + _subData._sliceSize, pDest);
}
@@ -1997,7 +1993,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
if (offset) {
const byte *pSrc = (const byte *)sliceDataStart + offset;
- byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, playerBounds.top);
+ byte *pDest = (byte *)dest.getBasePtr(0, 0);
//Common::copy(pSrc, pSrc + playerBounds.width(), pDest);
rleDecode(pSrc, pDest, playerBounds.width());
@@ -2012,7 +2008,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
// TODO: Check of _subData._drawType was done for two different kinds of
// line slice drawing in original
const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, playerBounds.top);
+ byte *pDest = (byte *)dest.getBasePtr(0, 0);
rleDecode(pSrc, pDest, _subData._sliceSize);
}
@@ -2027,7 +2023,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex) {
const byte *pSrc1 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData2 + sliceNum * 2);
const byte *pSrc2 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
- byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, y++);
+ byte *pDest = (byte *)dest.getBasePtr(0, y++);
if (slice2._drawMode == 0) {
// Uncompressed background, foreground compressed
@@ -2047,17 +2043,14 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
break;
}
- // Unlock the screen surface
- R2_GLOBALS._screenSurface.unlockSurface();
-
if (_objectMode == ANIMOBJMODE_42) {
_screenBounds.expandPanes();
// Copy the drawn frame to the back surface
- Rect srcRect = R2_GLOBALS._screenSurface.getBounds();
+ Rect srcRect = R2_GLOBALS._screen.getBounds();
Rect destRect = srcRect;
destRect.translate(-g_globals->_sceneOffset.x, -g_globals->_sceneOffset.y);
- R2_GLOBALS._sceneManager._scene->_backSurface.copyFrom(R2_GLOBALS._screenSurface,
+ R2_GLOBALS._sceneManager._scene->_backSurface.copyFrom(R2_GLOBALS._screen,
srcRect, destRect);
// Draw any objects into the scene
diff --git a/engines/tsage/ringworld2/ringworld2_outpost.cpp b/engines/tsage/ringworld2/ringworld2_outpost.cpp
index cad21b4623..8c64970bda 100644
--- a/engines/tsage/ringworld2/ringworld2_outpost.cpp
+++ b/engines/tsage/ringworld2/ringworld2_outpost.cpp
@@ -4689,7 +4689,7 @@ GfxButton *Scene1337::OptionsDialog::execute(GfxButton *defaultButton) {
}
g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
}
_gfxManager.deactivate();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index 573cbbb29a..63879b0366 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -1613,7 +1613,7 @@ void Scene180::signal() {
case 43:
case 47:
_helpEnabled = false;
- R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
_palette.loadPalette(0);
_palette.loadPalette(9998);
R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 8, this);
@@ -1815,7 +1815,7 @@ void Scene180::signal() {
_shipDisplay.remove();
_backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
- R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
R2_GLOBALS._sound2.fadeOut2(NULL);
R2_GLOBALS._sound1.fadeOut2(this);
break;
@@ -1880,7 +1880,7 @@ void Scene180::signal() {
R2_GLOBALS._paneRefreshFlag[0] = 3;
_backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
- R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
setSceneDelay(1);
break;
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
index 9954b929b2..3cb8e52692 100644
--- a/engines/tsage/saveload.cpp
+++ b/engines/tsage/saveload.cpp
@@ -289,10 +289,10 @@ void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &h
// Create a thumbnail and save it
Graphics::Surface *thumb = new Graphics::Surface();
- Graphics::Surface s = g_globals->_screenSurface.lockSurface();
+ Graphics::Surface s = g_globals->_screen.lockSurface();
::createThumbnail(thumb, (const byte *)s.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
Graphics::saveThumbnail(*out, *thumb);
- g_globals->_screenSurface.unlockSurface();
+ g_globals->_screen.unlockSurface();
thumb->free();
delete thumb;
diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp
index 80ce1e3ecc..095c0d7ab5 100644
--- a/engines/tsage/scenes.cpp
+++ b/engines/tsage/scenes.cpp
@@ -139,7 +139,7 @@ void SceneManager::fadeInIfNecessary() {
percent = 100;
g_globals->_scenePalette.fade((const byte *)&adjustData, false, percent);
- GLOBALS._screenSurface.updateScreen();
+ GLOBALS._screen.update();
g_system->delayMillis(10);
}
@@ -175,7 +175,7 @@ void SceneManager::changeScene(int newSceneNumber) {
}
// Blank out the screen
- g_globals->_screenSurface.fillRect(g_globals->_screenSurface.getBounds(), 0);
+ g_globals->_screen.fillRect(g_globals->_screen.getBounds(), 0);
// If there are any fading sounds, wait until fading is complete
while (g_globals->_soundManager.isFading()) {
@@ -463,7 +463,7 @@ void Scene::refreshBackground(int xAmount, int yAmount) {
// Check if the section is already loaded
if ((_enabledSections[xp * 16 + yp] == 0xffff) || ((xAmount == 0) && (yAmount == 0))) {
// Chunk isn't loaded, so load it in
- Graphics::Surface s = _backSurface.lockSurface();
+ Graphics::ManagedSurface s = _backSurface.lockSurface();
GfxSurface::loadScreenSection(s, xp - xHalfOffset, yp - yHalfOffset, xp, yp);
_backSurface.unlockSurface();
changedFlag = true;
diff --git a/engines/tsage/screen.cpp b/engines/tsage/screen.cpp
new file mode 100644
index 0000000000..f11c384797
--- /dev/null
+++ b/engines/tsage/screen.cpp
@@ -0,0 +1,46 @@
+/* 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 "tsage/screen.h"
+
+namespace TsAGE {
+
+Screen::Screen(): GfxSurface(), Graphics::Screen() {
+ create(SCREEN_WIDTH, SCREEN_HEIGHT);
+}
+
+void Screen::update() {
+ // When dialogs are active, the screen surface may be remapped to
+ // sub-sections of the screen. But for drawing we'll need to temporarily
+ // remove any such remappings and use the entirety of the screen
+ Rect clipBounds = getBounds();
+ setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+ // Update the screen
+ Graphics::Screen::update();
+
+ // Reset the clipping
+ setBounds(clipBounds);
+}
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/screen.h b/engines/tsage/screen.h
new file mode 100644
index 0000000000..bf5057e4d6
--- /dev/null
+++ b/engines/tsage/screen.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 TSAGE_SCREEN_H
+#define TSAGE_SCREEN_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "graphics/screen.h"
+#include "tsage/graphics.h"
+
+namespace TsAGE {
+
+#define SCREEN_WIDTH 320
+#define SCREEN_HEIGHT 200
+#define SCREEN_CENTER_X 160
+#define SCREEN_CENTER_Y 100
+#define UI_INTERFACE_Y 168
+
+class Screen : virtual public Graphics::Screen, virtual public GfxSurface {
+public:
+ /**
+ * Constructor
+ */
+ Screen();
+
+ /**
+ * Destructor
+ */
+ virtual ~Screen() {}
+
+ /**
+ * Update the screen
+ */
+ virtual void update();
+};
+
+} // End of namespace TsAGE
+
+#endif /* MADS_SCREEN_H */
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
index 667a8daa59..1a29700a10 100644
--- a/engines/tsage/tsage.h
+++ b/engines/tsage/tsage.h
@@ -62,12 +62,6 @@ enum {
struct tSageGameDescription;
-#define SCREEN_WIDTH 320
-#define SCREEN_HEIGHT 200
-#define SCREEN_CENTER_X 160
-#define SCREEN_CENTER_Y 100
-#define UI_INTERFACE_Y 168
-
class TSageEngine : public Engine {
private:
const tSageGameDescription *_gameDescription;
diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp
index 3ee585d5ef..fffc0dc16c 100644
--- a/engines/tsage/user_interface.cpp
+++ b/engines/tsage/user_interface.cpp
@@ -253,7 +253,7 @@ void UICollection::show() {
void UICollection::erase() {
if (_clearScreen) {
Rect tempRect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT);
- GLOBALS._screenSurface.fillRect(tempRect, 0);
+ GLOBALS._screen.fillRect(tempRect, 0);
GLOBALS._sceneManager._scene->_backSurface.fillRect(tempRect, 0);
_clearScreen = false;
}
@@ -274,7 +274,7 @@ void UICollection::draw() {
_objList[idx]->draw();
// Draw the resulting UI onto the screen
- GLOBALS._screenSurface.copyFrom(GLOBALS._sceneManager._scene->_backSurface,
+ GLOBALS._screen.copyFrom(GLOBALS._sceneManager._scene->_backSurface,
Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT),
Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT));
@@ -293,12 +293,12 @@ void UICollection::r2rDrawFrame() {
GfxSurface vertLineRight = visage.getFrame(3);
GfxSurface horizLine = visage.getFrame(2);
- GLOBALS._screenSurface.copyFrom(horizLine, 0, 0);
- GLOBALS._screenSurface.copyFrom(vertLineLeft, 0, 3);
- GLOBALS._screenSurface.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3);
+ GLOBALS._screen.copyFrom(horizLine, 0, 0);
+ GLOBALS._screen.copyFrom(vertLineLeft, 0, 3);
+ GLOBALS._screen.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3);
// Restrict drawing area to exclude the borders at the edge of the screen
- R2_GLOBALS._screenSurface._clipRect = Rect(4, 3, SCREEN_WIDTH - 4,
+ R2_GLOBALS._screen._clipRect = Rect(4, 3, SCREEN_WIDTH - 4,
SCREEN_HEIGHT - 3);
}
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index 3d7859e4fd..2447e15d6b 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -116,7 +116,7 @@ class TuckerMetaEngine : public AdvancedMetaEngine {
public:
TuckerMetaEngine() : AdvancedMetaEngine(tuckerGameDescriptions, sizeof(ADGameDescription), tuckerGames) {
_md5Bytes = 512;
- _singleid = "tucker";
+ _singleId = "tucker";
}
virtual const char *getName() const {
@@ -182,6 +182,8 @@ public:
saveList.push_back(SaveStateDescriptor(slot, description));
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 9cba7b523d..d7b75e39c1 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -662,9 +662,11 @@ void TuckerEngine::loadData3() {
void TuckerEngine::loadData4() {
loadFile("data4.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
- t.findNextToken(kDataTokenDw);
- _gameDebug = t.getNextInteger() != 0;
- _displayGameHints = t.getNextInteger() != 0;
+ if ((_gameFlags & kGameFlagDemo) == 0) {
+ t.findNextToken(kDataTokenDw);
+ _gameDebug = t.getNextInteger() != 0;
+ _displayGameHints = t.getNextInteger() != 0;
+ }
_locationObjectsCount = 0;
if (t.findIndex(_locationNum)) {
while (t.findNextToken(kDataTokenDw)) {
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index d9f284e443..0151c55eb1 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -54,6 +54,7 @@ void TuckerEngine::handleCreditsSequence() {
int counter2 = 0;
int counter1 = 0;
loadCharset2();
+ showCursor(false);
stopSounds();
_locationNum = 74;
_flagsTable[236] = 74;
@@ -159,12 +160,16 @@ void TuckerEngine::handleCreditsSequence() {
redrawScreen(0);
waitForTimer(2);
} while (_fadePaletteCounter > 0);
+ showCursor(true);
}
void TuckerEngine::handleCongratulationsSequence() {
+ // This method is only called right before the program terminates,
+ // so it doesn't bother restoring the palette
_timerCounter2 = 0;
_fadePaletteCounter = 0;
stopSounds();
+ showCursor(false);
loadImage("congrat.pcx", _loadTempBuf, 1);
Graphics::copyRect(_locationBackgroundGfxBuf, 640, _loadTempBuf, 320, 320, 200);
_fullRedraw = true;
@@ -176,11 +181,13 @@ void TuckerEngine::handleCongratulationsSequence() {
}
waitForTimer(3);
}
+ showCursor(true);
}
void TuckerEngine::handleNewPartSequence() {
char filename[40];
+ showCursor(false);
stopSounds();
if (_flagsTable[219] == 1) {
_flagsTable[219] = 0;
@@ -244,7 +251,7 @@ void TuckerEngine::handleNewPartSequence() {
_inputKeys[kInputKeyEscape] = false;
break;
}
- } while (isSpeechSoundPlaying());
+ } while (isSpeechSoundPlaying() && !_quitGame);
stopSpeechSound();
do {
if (_fadePaletteCounter > 0) {
@@ -257,8 +264,9 @@ void TuckerEngine::handleNewPartSequence() {
drawSprite(0);
redrawScreen(0);
waitForTimer(3);
- } while (_fadePaletteCounter > 0);
+ } while (_fadePaletteCounter > 0 && !_quitGame);
_locationNum = currentLocation;
+ showCursor(true);
}
void TuckerEngine::handleMeanwhileSequence() {
@@ -280,8 +288,9 @@ void TuckerEngine::handleMeanwhileSequence() {
strcpy(filename, "loc80.pcx");
}
loadImage(filename, _quadBackgroundGfxBuf + 89600, 1);
+ showCursor(false);
_fadePaletteCounter = 0;
- for (int i = 0; i < 60; ++i) {
+ for (int i = 0; i < 60 && !_quitGame; ++i) {
if (_fadePaletteCounter < 16) {
fadeOutPalette();
++_fadePaletteCounter;
@@ -290,7 +299,10 @@ void TuckerEngine::handleMeanwhileSequence() {
_fullRedraw = true;
redrawScreen(0);
waitForTimer(3);
- ++i;
+ if (_inputKeys[kInputKeyEscape]) {
+ _inputKeys[kInputKeyEscape] = false;
+ break;
+ }
}
do {
if (_fadePaletteCounter > 0) {
@@ -301,9 +313,10 @@ void TuckerEngine::handleMeanwhileSequence() {
_fullRedraw = true;
redrawScreen(0);
waitForTimer(3);
- } while (_fadePaletteCounter > 0);
+ } while (_fadePaletteCounter > 0 && !_quitGame);
memcpy(_currentPalette, backupPalette, 256 * 3);
_fullRedraw = true;
+ showCursor(true);
}
void TuckerEngine::handleMapSequence() {
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index de555cd7b6..ad455c5ded 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -710,6 +710,10 @@ void TuckerEngine::setCursorType(int type) {
CursorMan.showMouse(_cursorType < 2);
}
+void TuckerEngine::showCursor(bool visible) {
+ CursorMan.showMouse(visible);
+}
+
void TuckerEngine::setupNewLocation() {
debug(2, "setupNewLocation() current %d next %d", _locationNum, _nextLocationNum);
_locationNum = _nextLocationNum;
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index 3bbf6a57f5..2ab94dedbc 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -300,6 +300,7 @@ protected:
void updateCursorPos(int x, int y);
void setCursorNum(int num);
void setCursorType(int type);
+ void showCursor(bool visible);
void setupNewLocation();
void copyLocBitmap(const char *filename, int offset, bool isMask);
void updateMouseState();
diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp
index 62b37346da..d5d58a2fd3 100644
--- a/engines/voyeur/animation.cpp
+++ b/engines/voyeur/animation.cpp
@@ -470,7 +470,7 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
if (hasDirtyPalette()) {
const byte *palette = getPalette();
- vm->_graphicsManager->setPalette128(palette, paletteStart, paletteCount);
+ vm->_screen->setPalette128(palette, paletteStart, paletteCount);
}
if (needsUpdate()) {
@@ -482,15 +482,14 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32,
READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20);
- vm->_graphicsManager->sDrawPic(newPic, &videoFrame, pt);
+ vm->_screen->sDrawPic(newPic, &videoFrame, pt);
++picCtr;
}
}
// Decode the next frame and display
const Graphics::Surface *frame = decodeNextFrame();
- Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
- (byte *)vm->_graphicsManager->_screenSurface.getPixels());
+ vm->_screen->blitFrom(*frame);
}
vm->_eventsManager->getMouseInfo();
diff --git a/engines/voyeur/data.cpp b/engines/voyeur/data.cpp
index b8c987f18b..4d6e32436d 100644
--- a/engines/voyeur/data.cpp
+++ b/engines/voyeur/data.cpp
@@ -240,10 +240,10 @@ void SVoy::reviewAnEvidEvent(int eventIndex) {
int frameOff = e._computerOff;
if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
- _vm->_graphicsManager->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
- _vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
- _vm->_graphicsManager->_vPort->setupViewPort(_vm->_graphicsManager->_backgroundPage);
- _vm->_graphicsManager->_backColors->startFade();
+ _vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
+ _vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
+ _vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
+ _vm->_screen->_backColors->startFade();
_vm->doEvidDisplay(frameOff, e._dead);
_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
@@ -262,10 +262,10 @@ void SVoy::reviewComputerEvent(int eventIndex) {
_computerTextId = e._computerOn;
if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
- _vm->_graphicsManager->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
- _vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
- _vm->_graphicsManager->_vPort->setupViewPort(_vm->_graphicsManager->_backgroundPage);
- _vm->_graphicsManager->_backColors->startFade();
+ _vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
+ _vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
+ _vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
+ _vm->_screen->_backColors->startFade();
_vm->flipPageAndWaitForFade();
_vm->getComputerBrush();
diff --git a/engines/voyeur/debugger.cpp b/engines/voyeur/debugger.cpp
index e9a12180da..ebfa123eb6 100644
--- a/engines/voyeur/debugger.cpp
+++ b/engines/voyeur/debugger.cpp
@@ -21,7 +21,7 @@
*/
#include "voyeur/debugger.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/voyeur.h"
#include "voyeur/staticres.h"
diff --git a/engines/voyeur/detection.cpp b/engines/voyeur/detection.cpp
index 80a23d3c35..9e5320aac8 100644
--- a/engines/voyeur/detection.cpp
+++ b/engines/voyeur/detection.cpp
@@ -117,7 +117,6 @@ SaveStateList VoyeurMetaEngine::listSaves(const char *target) const {
Common::String pattern = Common::String::format("%s.0##", target);
filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
SaveStateList saveList;
Voyeur::VoyeurSavegameHeader header;
@@ -139,6 +138,8 @@ SaveStateList VoyeurMetaEngine::listSaves(const char *target) const {
}
}
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp
index 34ef507ad3..020fe4b692 100644
--- a/engines/voyeur/events.cpp
+++ b/engines/voyeur/events.cpp
@@ -111,18 +111,18 @@ void EventsManager::mainVoyeurIntFunc() {
}
void EventsManager::sWaitFlip() {
- Common::Array<ViewPortResource *> &viewPorts = _vm->_graphicsManager->_viewPortListPtr->_entries;
+ Common::Array<ViewPortResource *> &viewPorts = _vm->_screen->_viewPortListPtr->_entries;
for (uint idx = 0; idx < viewPorts.size(); ++idx) {
ViewPortResource &viewPort = *viewPorts[idx];
- if (_vm->_graphicsManager->_saveBack && (viewPort._flags & DISPFLAG_40)) {
- Common::Rect *clipPtr = _vm->_graphicsManager->_clipPtr;
- _vm->_graphicsManager->_clipPtr = &viewPort._clipRect;
+ if (_vm->_screen->_saveBack && (viewPort._flags & DISPFLAG_40)) {
+ Common::Rect *clipPtr = _vm->_screen->_clipPtr;
+ _vm->_screen->_clipPtr = &viewPort._clipRect;
if (viewPort._restoreFn)
- (_vm->_graphicsManager->*viewPort._restoreFn)(&viewPort);
+ (_vm->_screen->*viewPort._restoreFn)(&viewPort);
- _vm->_graphicsManager->_clipPtr = clipPtr;
+ _vm->_screen->_clipPtr = clipPtr;
viewPort._rectListCount[viewPort._pageIndex] = 0;
viewPort._rectListPtr[viewPort._pageIndex]->clear();
viewPort._flags &= ~DISPFLAG_40;
@@ -158,9 +158,7 @@ void EventsManager::checkForNextFrameCounter() {
showMousePosition();
// Display the frame
- g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(),
- SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- g_system->updateScreen();
+ _vm->_screen->update();
// Signal the ScummVM debugger
_vm->_debugger->onFrame();
@@ -178,10 +176,8 @@ void EventsManager::showMousePosition() {
mousePos += Common::String::format(" - (%d,%d)", pt.x, pt.y);
}
- _vm->_graphicsManager->_screenSurface.fillRect(
- Common::Rect(0, 0, 110, font.getFontHeight()), 0);
- font.drawString(&_vm->_graphicsManager->_screenSurface, mousePos,
- 0, 0, 110, 63);
+ _vm->_screen->fillRect(Common::Rect(0, 0, 110, font.getFontHeight()), 0);
+ font.drawString(_vm->_screen, mousePos, 0, 0, 110, 63);
}
void EventsManager::voyeurTimer() {
@@ -299,11 +295,11 @@ void EventsManager::startFade(CMapResource *cMap) {
if (cMap->_steps > 0) {
_fadeStatus = cMap->_fadeStatus | 1;
- byte *vgaP = &_vm->_graphicsManager->_VGAColors[_fadeFirstCol * 3];
+ byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
int mapIndex = 0;
for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
- ViewPortPalEntry &palEntry = _vm->_graphicsManager->_viewPortListPtr->_palette[idx];
+ ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[idx];
palEntry._rEntry = vgaP[0] << 8;
int rDiff = (cMap->_entries[mapIndex * 3] << 8) - palEntry._rEntry;
palEntry._rChange = rDiff / cMap->_steps;
@@ -325,7 +321,7 @@ void EventsManager::startFade(CMapResource *cMap) {
_intPtr._skipFading = true;
_fadeIntNode._flags &= ~1;
} else {
- byte *vgaP = &_vm->_graphicsManager->_VGAColors[_fadeFirstCol * 3];
+ byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
int mapIndex = 0;
for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
@@ -371,8 +367,8 @@ void EventsManager::vDoFadeInt() {
}
for (int i = _fadeFirstCol; i <= _fadeLastCol; ++i) {
- ViewPortPalEntry &palEntry = _vm->_graphicsManager->_viewPortListPtr->_palette[i];
- byte *vgaP = &_vm->_graphicsManager->_VGAColors[palEntry._palIndex * 3];
+ ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[i];
+ byte *vgaP = &_vm->_screen->_VGAColors[palEntry._palIndex * 3];
palEntry._rEntry += palEntry._rChange;
palEntry._gEntry += palEntry._gChange;
@@ -395,7 +391,7 @@ void EventsManager::vDoCycleInt() {
for (int idx = 3; idx >= 0; --idx) {
if (_cyclePtr->_type[idx] && --_cycleTime[idx] <= 0) {
byte *pSrc = _cycleNext[idx];
- byte *pPal = _vm->_graphicsManager->_VGAColors;
+ byte *pPal = _vm->_screen->_VGAColors;
if (_cyclePtr->_type[idx] != 1) {
// New palette data being specified - loop to set entries
@@ -521,7 +517,7 @@ void EventsManager::setCursor(PictureResource *pic) {
cursor._bounds = pic->_bounds;
cursor._flags = DISPFLAG_CURSOR;
- _vm->_graphicsManager->sDrawPic(pic, &cursor, Common::Point());
+ _vm->_screen->sDrawPic(pic, &cursor, Common::Point());
}
void EventsManager::setCursor(byte *cursorData, int width, int height, int keyColor) {
@@ -531,16 +527,16 @@ void EventsManager::setCursor(byte *cursorData, int width, int height, int keyCo
void EventsManager::setCursorColor(int idx, int mode) {
switch (mode) {
case 0:
- _vm->_graphicsManager->setColor(idx, 90, 90, 232);
+ _vm->_screen->setColor(idx, 90, 90, 232);
break;
case 1:
- _vm->_graphicsManager->setColor(idx, 232, 90, 90);
+ _vm->_screen->setColor(idx, 232, 90, 90);
break;
case 2:
- _vm->_graphicsManager->setColor(idx, 90, 232, 90);
+ _vm->_screen->setColor(idx, 90, 232, 90);
break;
case 3:
- _vm->_graphicsManager->setColor(idx, 90, 232, 232);
+ _vm->_screen->setColor(idx, 90, 232, 232);
break;
default:
break;
@@ -564,12 +560,12 @@ void EventsManager::getMouseInfo() {
if (_cursorBlinked) {
_cursorBlinked = false;
- _vm->_graphicsManager->setOneColor(128, 220, 20, 20);
- _vm->_graphicsManager->setColor(128, 220, 20, 20);
+ _vm->_screen->setOneColor(128, 220, 20, 20);
+ _vm->_screen->setColor(128, 220, 20, 20);
} else {
_cursorBlinked = true;
- _vm->_graphicsManager->setOneColor(128, 220, 220, 220);
- _vm->_graphicsManager->setColor(128, 220, 220, 220);
+ _vm->_screen->setOneColor(128, 220, 220, 220);
+ _vm->_screen->setColor(128, 220, 220, 220);
}
}
}
@@ -585,11 +581,11 @@ void EventsManager::getMouseInfo() {
void EventsManager::startCursorBlink() {
if (_vm->_voy->_eventFlags & EVTFLAG_RECORDING) {
- _vm->_graphicsManager->setOneColor(128, 55, 5, 5);
- _vm->_graphicsManager->setColor(128, 220, 20, 20);
+ _vm->_screen->setOneColor(128, 55, 5, 5);
+ _vm->_screen->setColor(128, 220, 20, 20);
_intPtr._hasPalette = true;
- _vm->_graphicsManager->drawDot();
+ _vm->_screen->drawDot();
//copySection();
}
}
diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp
index 300e086f75..46b195ecaf 100644
--- a/engines/voyeur/files.cpp
+++ b/engines/voyeur/files.cpp
@@ -21,7 +21,7 @@
*/
#include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/voyeur.h"
#include "voyeur/staticres.h"
@@ -359,7 +359,7 @@ void BoltFile::resolveIt(uint32 id, byte **p) {
}
}
-void BoltFile::resolveFunction(uint32 id, GraphicMethodPtr *fn) {
+void BoltFile::resolveFunction(uint32 id, ScreenMethodPtr *fn) {
if ((int32)id == -1)
*fn = NULL;
else
@@ -485,8 +485,8 @@ void BVoyBoltFile::initViewPortList() {
_state._curMemberPtr->_viewPortListResource = res = new ViewPortListResource(
_state, _state._curMemberPtr->_data);
- _state._vm->_graphicsManager->_viewPortListPtr = res;
- _state._vm->_graphicsManager->_vPort = res->_entries[0];
+ _state._vm->_screen->_viewPortListPtr = res;
+ _state._vm->_screen->_vPort = res->_entries[0];
}
void BVoyBoltFile::initFontInfo() {
@@ -752,24 +752,24 @@ DisplayResource::DisplayResource(VoyeurEngine *vm) {
void DisplayResource::sFillBox(int width, int height) {
assert(_vm);
- bool saveBack = _vm->_graphicsManager->_saveBack;
- _vm->_graphicsManager->_saveBack = false;
+ bool saveBack = _vm->_screen->_saveBack;
+ _vm->_screen->_saveBack = false;
PictureResource pr;
pr._flags = DISPFLAG_1;
pr._select = 0xff;
pr._pick = 0;
- pr._onOff = _vm->_graphicsManager->_drawPtr->_penColor;
+ pr._onOff = _vm->_screen->_drawPtr->_penColor;
pr._bounds = Common::Rect(0, 0, width, height);
- _vm->_graphicsManager->sDrawPic(&pr, this, _vm->_graphicsManager->_drawPtr->_pos);
- _vm->_graphicsManager->_saveBack = saveBack;
+ _vm->_screen->sDrawPic(&pr, this, _vm->_screen->_drawPtr->_pos);
+ _vm->_screen->_saveBack = saveBack;
}
bool DisplayResource::clipRect(Common::Rect &rect) {
Common::Rect clippingRect;
- if (_vm->_graphicsManager->_clipPtr) {
- clippingRect = *_vm->_graphicsManager->_clipPtr;
+ if (_vm->_screen->_clipPtr) {
+ clippingRect = *_vm->_screen->_clipPtr;
} else if (_flags & DISPFLAG_VIEWPORT) {
clippingRect = ((ViewPortResource *)this)->_clipRect;
} else {
@@ -804,18 +804,18 @@ bool DisplayResource::clipRect(Common::Rect &rect) {
}
int DisplayResource::drawText(const Common::String &msg) {
- GraphicsManager &gfxManager = *_vm->_graphicsManager;
- assert(gfxManager._fontPtr);
- assert(gfxManager._fontPtr->_curFont);
- FontInfoResource &fontInfo = *gfxManager._fontPtr;
- PictureResource &fontChar = *_vm->_graphicsManager->_fontChar;
+ Screen &screen = *_vm->_screen;
+ assert(screen._fontPtr);
+ assert(screen._fontPtr->_curFont);
+ FontInfoResource &fontInfo = *screen._fontPtr;
+ PictureResource &fontChar = *_vm->_screen->_fontChar;
FontResource &fontData = *fontInfo._curFont;
int xShadows[9] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
int yShadows[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
- Common::Rect *clipPtr = gfxManager._clipPtr;
+ Common::Rect *clipPtr = screen._clipPtr;
if (!(fontInfo._picFlags & DISPFLAG_1))
- gfxManager._clipPtr = NULL;
+ screen._clipPtr = NULL;
int minChar = fontData._minChar;
int padding = fontData._padding;
@@ -834,7 +834,7 @@ int DisplayResource::drawText(const Common::String &msg) {
(ViewPortResource *)this;
if ((fontInfo._fontFlags & DISPFLAG_1) || fontInfo._justify ||
- (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT))) {
+ (screen._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT))) {
msgWidth = viewPort->textWidth(msg);
yp = pos.y;
xp = pos.x;
@@ -898,18 +898,18 @@ int DisplayResource::drawText(const Common::String &msg) {
}
}
- if (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) {
+ if (screen._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) {
viewPort->addSaveRect(viewPort->_pageIndex, viewPort->_fontRect);
}
if (fontInfo._fontFlags & DISPFLAG_1) {
- gfxManager._drawPtr->_pos = Common::Point(viewPort->_fontRect.left, viewPort->_fontRect.top);
- gfxManager._drawPtr->_penColor = fontInfo._backColor;
+ screen._drawPtr->_pos = Common::Point(viewPort->_fontRect.left, viewPort->_fontRect.top);
+ screen._drawPtr->_penColor = fontInfo._backColor;
sFillBox(viewPort->_fontRect.width(), viewPort->_fontRect.height());
}
- bool saveBack = gfxManager._saveBack;
- gfxManager._saveBack = false;
+ bool saveBack = screen._saveBack;
+ screen._saveBack = false;
int count = 0;
if (fontInfo._fontFlags & DISPFLAG_4)
@@ -970,7 +970,7 @@ int DisplayResource::drawText(const Common::String &msg) {
uint16 offset = READ_LE_UINT16(fontData._charOffsets + charValue * 2);
fontChar._imgData = fontData._charImages + offset * 2;
- gfxManager.sDrawPic(&fontChar, this, Common::Point(xp, yp));
+ screen.sDrawPic(&fontChar, this, Common::Point(xp, yp));
fontChar._imgData = NULL;
xp += charWidth + padding;
@@ -982,8 +982,8 @@ int DisplayResource::drawText(const Common::String &msg) {
if (fontInfo._justify == ALIGN_LEFT)
fontInfo._pos.x = xp;
- gfxManager._saveBack = saveBack;
- gfxManager._clipPtr = clipPtr;
+ screen._saveBack = saveBack;
+ screen._clipPtr = clipPtr;
return msgWidth;
}
@@ -993,7 +993,7 @@ int DisplayResource::textWidth(const Common::String &msg) {
return 0;
const char *msgP = msg.c_str();
- FontResource &fontData = *_vm->_graphicsManager->_fontPtr->_curFont;
+ FontResource &fontData = *_vm->_screen->_fontPtr->_curFont;
int minChar = fontData._minChar;
int maxChar = fontData._maxChar;
int padding = fontData._padding;
@@ -1085,9 +1085,9 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
mode = 226;
}
- if (mode != state._vm->_graphicsManager->_SVGAMode) {
- state._vm->_graphicsManager->_SVGAMode = mode;
- state._vm->_graphicsManager->clearPalette();
+ if (mode != state._vm->_screen->_SVGAMode) {
+ state._vm->_screen->_SVGAMode = mode;
+ state._vm->_screen->clearPalette();
}
int screenOffset = READ_LE_UINT32(&src[18]) & 0xffff;
@@ -1096,13 +1096,14 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
if (_flags & PICFLAG_CLEAR_SCREEN) {
// Clear screen picture. That's right. This game actually has a picture
// resource flag to clear the screen! Bizarre.
- Graphics::Surface &s = state._vm->_graphicsManager->_screenSurface;
- s.fillRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ state._vm->_screen->clear();
} else {
// Direct screen loading picture. In this case, the raw data of the resource
// is directly decompressed into the screen surface. Again, bizarre.
- byte *pDest = (byte *)state._vm->_graphicsManager->_screenSurface.getPixels();
+ Screen &screen = *state._vm->_screen;
+ byte *pDest = (byte *)screen.getPixels();
state.decompress(pDest, SCREEN_WIDTH * SCREEN_HEIGHT, state._curMemberPtr->_mode);
+ screen.markAllDirty();
}
} else {
if (_flags & PICFLAG_CLEAR_SCREEN00) {
@@ -1249,13 +1250,13 @@ ViewPortResource::ViewPortResource(BoltFilesState &state, const byte *src):
ys + READ_LE_UINT16(src + 0x4C));
state._curLibPtr->resolveIt(READ_LE_UINT32(src + 0x7A), &dummy);
- state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x7E), (GraphicMethodPtr *)&_fn1);
- state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x82), (GraphicMethodPtr *)&_setupFn);
- state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x86), (GraphicMethodPtr *)&_addFn);
- state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x8A), (GraphicMethodPtr *)&_restoreFn);
+ state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x7E), (ScreenMethodPtr *)&_fn1);
+ state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x82), (ScreenMethodPtr *)&_setupFn);
+ state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x86), (ScreenMethodPtr *)&_addFn);
+ state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x8A), (ScreenMethodPtr *)&_restoreFn);
if (!_restoreFn && _addFn)
- _addFn = &GraphicsManager::addRectNoSaveBack;
+ _addFn = &Screen::addRectNoSaveBack;
}
ViewPortResource::~ViewPortResource() {
@@ -1327,19 +1328,19 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi
_restoreFn = restoreFn;
if (setupFn)
- (_state._vm->_graphicsManager->*setupFn)(this);
+ (_state._vm->_screen->*setupFn)(this);
}
void ViewPortResource::setupViewPort() {
- setupViewPort(_state._vm->_graphicsManager->_backgroundPage, NULL,
- &GraphicsManager::setupMCGASaveRect, &GraphicsManager::addRectOptSaveRect,
- &GraphicsManager::restoreMCGASaveRect);
+ setupViewPort(_state._vm->_screen->_backgroundPage, NULL,
+ &Screen::setupMCGASaveRect, &Screen::addRectOptSaveRect,
+ &Screen::restoreMCGASaveRect);
}
void ViewPortResource::setupViewPort(PictureResource *pic, Common::Rect *clippingRect) {
setupViewPort(pic, clippingRect,
- &GraphicsManager::setupMCGASaveRect, &GraphicsManager::addRectOptSaveRect,
- &GraphicsManager::restoreMCGASaveRect);
+ &Screen::setupMCGASaveRect, &Screen::addRectOptSaveRect,
+ &Screen::restoreMCGASaveRect);
}
void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
@@ -1347,7 +1348,7 @@ void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
if (clipRect(rect)) {
if (_addFn) {
- (_state._vm->_graphicsManager->*_addFn)(this, pageIndex, rect);
+ (_state._vm->_screen->*_addFn)(this, pageIndex, rect);
} else if (_rectListCount[pageIndex] != -1) {
_rectListPtr[pageIndex]->push_back(rect);
}
@@ -1355,26 +1356,26 @@ void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
}
void ViewPortResource::fillPic(byte onOff) {
- _state._vm->_graphicsManager->fillPic(this, onOff);
+ _state._vm->_screen->fillPic(this, onOff);
}
void ViewPortResource::drawIfaceTime() {
// Hour display
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
(_state._vm->_gameHour / 10) == 0 ? 10 : _state._vm->_gameHour / 10,
Common::Point(161, 25));
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
_state._vm->_gameHour % 10, Common::Point(172, 25));
// Minute display
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
_state._vm->_gameMinute / 10, Common::Point(190, 25));
- _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+ _state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
_state._vm->_gameMinute % 10, Common::Point(201, 25));
// AM/PM indicator
PictureResource *pic = _state._vm->_bVoy->boltEntry(_state._vm->_voy->_isAM ? 272 : 273)._picResource;
- _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort,
+ _state._vm->_screen->sDrawPic(pic, _state._vm->_screen->_vPort,
Common::Point(215, 27));
}
@@ -1382,9 +1383,9 @@ void ViewPortResource::drawPicPerm(PictureResource *pic, const Common::Point &pt
Common::Rect bounds = pic->_bounds;
bounds.translate(pt.x, pt.y);
- bool saveBack = _state._vm->_graphicsManager->_saveBack;
- _state._vm->_graphicsManager->_saveBack = false;
- _state._vm->_graphicsManager->sDrawPic(pic, this, pt);
+ bool saveBack = _state._vm->_screen->_saveBack;
+ _state._vm->_screen->_saveBack = false;
+ _state._vm->_screen->sDrawPic(pic, this, pt);
clipRect(bounds);
for (int pageIndex = 0; pageIndex < _pageCount; ++pageIndex) {
@@ -1393,7 +1394,7 @@ void ViewPortResource::drawPicPerm(PictureResource *pic, const Common::Point &pt
}
}
- _state._vm->_graphicsManager->_saveBack = saveBack;
+ _state._vm->_screen->_saveBack = saveBack;
}
/*------------------------------------------------------------------------*/
@@ -1526,7 +1527,7 @@ CMapResource::CMapResource(BoltFilesState &state, const byte *src): _vm(state._v
_entries = new byte[count * 3];
Common::copy(src + 6, src + 6 + 3 * count, _entries);
- int palIndex = state._vm->_graphicsManager->_viewPortListPtr->_palIndex;
+ int palIndex = state._vm->_screen->_viewPortListPtr->_palIndex;
if (_end > palIndex)
_end = palIndex;
if (_start > palIndex)
diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h
index eef5df497c..8726b38ddf 100644
--- a/engines/voyeur/files.h
+++ b/engines/voyeur/files.h
@@ -27,7 +27,7 @@
#include "common/file.h"
#include "common/rect.h"
#include "common/str.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
namespace Voyeur {
@@ -112,7 +112,7 @@ public:
byte *memberAddr(uint32 id);
byte *memberAddrOffset(uint32 id);
void resolveIt(uint32 id, byte **p);
- void resolveFunction(uint32 id, GraphicMethodPtr *fn);
+ void resolveFunction(uint32 id, ScreenMethodPtr *fn);
BoltEntry &boltEntry(uint16 id);
BoltEntry &getBoltEntryFromLong(uint32 id);
@@ -340,7 +340,7 @@ public:
int _rectListCount[3];
Common::Rect _clipRect;
- GraphicMethodPtr _fn1;
+ ScreenMethodPtr _fn1;
ViewPortSetupPtr _setupFn;
ViewPortAddPtr _addFn;
ViewPortRestorePtr _restoreFn;
diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp
index 9908324043..bbd3dfe4e9 100644
--- a/engines/voyeur/files_threads.cpp
+++ b/engines/voyeur/files_threads.cpp
@@ -21,7 +21,7 @@
*/
#include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/voyeur.h"
#include "voyeur/staticres.h"
@@ -461,7 +461,7 @@ void ThreadResource::parsePlayCommands() {
pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + i * 2)._picResource;
pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + i * 2 + 1)._cMapResource;
- _vm->_graphicsManager->_vPort->setupViewPort(pic);
+ _vm->_screen->_vPort->setupViewPort(pic);
pal->startFade();
_vm->flipPageAndWaitForFade();
@@ -980,10 +980,10 @@ int ThreadResource::doApt() {
_vm->_soundManager->startVOCPlay(_vm->_soundManager->getVOCFileName(_vm->_currentVocId));
_vm->_currentVocId = 151;
- _vm->_graphicsManager->setColor(129, 82, 82, 82);
- _vm->_graphicsManager->setColor(130, 112, 112, 112);
- _vm->_graphicsManager->setColor(131, 215, 215, 215);
- _vm->_graphicsManager->setColor(132, 235, 235, 235);
+ _vm->_screen->setColor(129, 82, 82, 82);
+ _vm->_screen->setColor(130, 112, 112, 112);
+ _vm->_screen->setColor(131, 215, 215, 215);
+ _vm->_screen->setColor(132, 235, 235, 235);
_vm->_eventsManager->_intPtr._hasPalette = true;
@@ -1044,7 +1044,7 @@ int ThreadResource::doApt() {
// Draw the text description for the highlighted hotspot
pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId +
hotspotId + 6)._picResource;
- _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
+ _vm->_screen->sDrawPic(pic, _vm->_screen->_vPort,
Common::Point(106, 200));
}
@@ -1112,10 +1112,10 @@ void ThreadResource::doRoom() {
if (!vm._bVoy->getBoltGroup(vm._playStampGroupId))
return;
- vm._graphicsManager->_backColors = vm._bVoy->boltEntry(vm._playStampGroupId + 1)._cMapResource;
- vm._graphicsManager->_backgroundPage = vm._bVoy->boltEntry(vm._playStampGroupId)._picResource;
- vm._graphicsManager->_vPort->setupViewPort(vm._graphicsManager->_backgroundPage);
- vm._graphicsManager->_backColors->startFade();
+ vm._screen->_backColors = vm._bVoy->boltEntry(vm._playStampGroupId + 1)._cMapResource;
+ vm._screen->_backgroundPage = vm._bVoy->boltEntry(vm._playStampGroupId)._picResource;
+ vm._screen->_vPort->setupViewPort(vm._screen->_backgroundPage);
+ vm._screen->_backColors->startFade();
voy._fadingStep1 = 2;
voy._fadingStep2 = 0;
@@ -1144,7 +1144,7 @@ void ThreadResource::doRoom() {
bool breakFlag = false;
while (!vm.shouldQuit() && !breakFlag) {
_vm->_voyeurArea = AREA_ROOM;
- vm._graphicsManager->setColor(128, 0, 255, 0);
+ vm._screen->setColor(128, 0, 255, 0);
vm._eventsManager->_intPtr._hasPalette = true;
do {
@@ -1186,7 +1186,7 @@ void ThreadResource::doRoom() {
}
vm._eventsManager->_intPtr._hasPalette = true;
- vm._graphicsManager->flipPage();
+ vm._screen->flipPage();
vm._eventsManager->sWaitFlip();
} while (!vm.shouldQuit() && !vm._eventsManager->_mouseClicked);
@@ -1234,13 +1234,13 @@ void ThreadResource::doRoom() {
// WORKAROUND: Skipped code from the original, that freed the group,
// reloaded it, and reloaded the cursors
- vm._graphicsManager->_backColors = vm._bVoy->boltEntry(
+ vm._screen->_backColors = vm._bVoy->boltEntry(
vm._playStampGroupId + 1)._cMapResource;
- vm._graphicsManager->_backgroundPage = vm._bVoy->boltEntry(
+ vm._screen->_backgroundPage = vm._bVoy->boltEntry(
vm._playStampGroupId)._picResource;
- vm._graphicsManager->_vPort->setupViewPort();
- vm._graphicsManager->_backColors->startFade();
+ vm._screen->_vPort->setupViewPort();
+ vm._screen->_backColors->startFade();
_vm->flipPageAndWait();
while (!vm.shouldQuit() && (vm._eventsManager->_fadeStatus & 1))
@@ -1265,7 +1265,7 @@ void ThreadResource::doRoom() {
_vm->flipPageAndWait();
- vm._graphicsManager->fadeUpICF1();
+ vm._screen->fadeUpICF1();
voy._eventFlags &= EVTFLAG_RECORDING;
vm._eventsManager->showCursor();
}
@@ -1350,7 +1350,7 @@ int ThreadResource::doInterface() {
_vm->_soundManager->startVOCPlay(fname);
_vm->_eventsManager->getMouseInfo();
- _vm->_graphicsManager->setColor(240, 220, 220, 220);
+ _vm->_screen->setColor(240, 220, 220, 220);
_vm->_eventsManager->_intPtr._hasPalette = true;
_vm->_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
@@ -1424,20 +1424,20 @@ int ThreadResource::doInterface() {
// Regularly update the time display
if (_vm->_voy->_RTANum & 2) {
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_screen->drawANumber(_vm->_screen->_vPort,
_vm->_gameMinute / 10, Common::Point(190, 25));
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_screen->drawANumber(_vm->_screen->_vPort,
_vm->_gameMinute % 10, Common::Point(201, 25));
if (_vm->_voy->_RTANum & 4) {
int v = _vm->_gameHour / 10;
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_screen->drawANumber(_vm->_screen->_vPort,
v == 0 ? 10 : v, Common::Point(161, 25));
- _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+ _vm->_screen->drawANumber(_vm->_screen->_vPort,
_vm->_gameHour % 10, Common::Point(172, 25));
pic = _vm->_bVoy->boltEntry(_vm->_voy->_isAM ? 272 : 273)._picResource;
- _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
+ _vm->_screen->sDrawPic(pic, _vm->_screen->_vPort,
Common::Point(215, 27));
}
}
@@ -1605,16 +1605,16 @@ void ThreadResource::loadTheApt() {
_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId);
_vm->_voy->_aptLoadMode = -1;
- _vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(
+ _vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(
_vm->_playStampGroupId + 5)._picResource;
- _vm->_graphicsManager->_vPort->setupViewPort(
- _vm->_graphicsManager->_backgroundPage);
+ _vm->_screen->_vPort->setupViewPort(
+ _vm->_screen->_backgroundPage);
} else {
_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId);
- _vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(
+ _vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(
_vm->_playStampGroupId + 5)._picResource;
- _vm->_graphicsManager->_vPort->setupViewPort(
- _vm->_graphicsManager->_backgroundPage);
+ _vm->_screen->_vPort->setupViewPort(
+ _vm->_screen->_backgroundPage);
}
CMapResource *pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4)._cMapResource;
@@ -1624,10 +1624,10 @@ void ThreadResource::loadTheApt() {
}
void ThreadResource::freeTheApt() {
- _vm->_graphicsManager->fadeDownICF1(5);
+ _vm->_screen->fadeDownICF1(5);
_vm->flipPageAndWaitForFade();
- _vm->_graphicsManager->fadeUpICF1();
+ _vm->_screen->fadeUpICF1();
if (_vm->_currentVocId != -1) {
_vm->_soundManager->stopVOCPlay();
@@ -1635,17 +1635,17 @@ void ThreadResource::freeTheApt() {
}
if (_vm->_voy->_aptLoadMode == -1) {
- _vm->_graphicsManager->fadeDownICF(6);
+ _vm->_screen->fadeDownICF(6);
} else {
doAptAnim(2);
}
if (_vm->_voy->_aptLoadMode == 140) {
- _vm->_graphicsManager->screenReset();
- _vm->_graphicsManager->resetPalette();
+ _vm->_screen->screenReset();
+ _vm->_screen->resetPalette();
}
- _vm->_graphicsManager->_vPort->setupViewPort(nullptr);
+ _vm->_screen->_vPort->setupViewPort(nullptr);
_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
_vm->_playStampGroupId = -1;
_vm->_voy->_viewBounds = nullptr;
@@ -1705,7 +1705,7 @@ void ThreadResource::doAptAnim(int mode) {
for (int idx = 0; (idx < 6) && !_vm->shouldQuit(); ++idx) {
PictureResource *pic = _vm->_bVoy->boltEntry(id + idx + 1)._picResource;
- _vm->_graphicsManager->_vPort->setupViewPort(pic);
+ _vm->_screen->_vPort->setupViewPort(pic);
pal->startFade();
_vm->flipPageAndWait();
diff --git a/engines/voyeur/module.mk b/engines/voyeur/module.mk
index aab254cf36..a38bdd9ab2 100644
--- a/engines/voyeur/module.mk
+++ b/engines/voyeur/module.mk
@@ -8,7 +8,7 @@ MODULE_OBJS := \
events.o \
files.o \
files_threads.o \
- graphics.o \
+ screen.o \
sound.o \
staticres.o \
voyeur.o \
diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/screen.cpp
index a20e9f6006..62f609c5c7 100644
--- a/engines/voyeur/graphics.cpp
+++ b/engines/voyeur/screen.cpp
@@ -20,7 +20,7 @@
*
*/
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/voyeur.h"
#include "voyeur/staticres.h"
#include "engines/util.h"
@@ -38,7 +38,8 @@ DrawInfo::DrawInfo(int penColor, const Common::Point &pos) {
/*------------------------------------------------------------------------*/
-GraphicsManager::GraphicsManager(VoyeurEngine *vm) : _defaultDrawInfo(1, Common::Point()), _drawPtr(&_defaultDrawInfo), _vm(vm) {
+Screen::Screen(VoyeurEngine *vm) : Graphics::Screen(), _vm(vm), _drawPtr(&_defaultDrawInfo),
+ _defaultDrawInfo(1, Common::Point()) {
_SVGAMode = 0;
_planeSelect = 0;
_saveBack = true;
@@ -52,18 +53,17 @@ GraphicsManager::GraphicsManager(VoyeurEngine *vm) : _defaultDrawInfo(1, Common:
_backColors = nullptr;
}
-void GraphicsManager::sInitGraphics() {
+void Screen::sInitGraphics() {
initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false);
- _screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
+ create(SCREEN_WIDTH, SCREEN_HEIGHT);
clearPalette();
}
-GraphicsManager::~GraphicsManager() {
- _screenSurface.free();
+Screen::~Screen() {
delete _fontChar;
}
-void GraphicsManager::setupMCGASaveRect(ViewPortResource *viewPort) {
+void Screen::setupMCGASaveRect(ViewPortResource *viewPort) {
if (viewPort->_activePage) {
viewPort->_activePage->_flags |= DISPFLAG_1;
Common::Rect *clipRect = _clipPtr;
@@ -77,7 +77,7 @@ void GraphicsManager::setupMCGASaveRect(ViewPortResource *viewPort) {
viewPort->_rectListCount[1] = -1;
}
-void GraphicsManager::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
+void Screen::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
if (viewPort->_rectListCount[idx] == -1)
return;
@@ -86,7 +86,7 @@ void GraphicsManager::addRectOptSaveRect(ViewPortResource *viewPort, int idx, co
++viewPort->_rectListCount[idx];
}
-void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) {
+void Screen::restoreMCGASaveRect(ViewPortResource *viewPort) {
if (viewPort->_rectListCount[0] != -1) {
for (int i = 0; i < viewPort->_rectListCount[0]; ++i) {
addRectOptSaveRect(viewPort, 1, (*viewPort->_rectListPtr[0])[i]);
@@ -106,11 +106,11 @@ void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) {
viewPort->_rectListCount[1] = count;
}
-void GraphicsManager::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
+void Screen::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
// Stubbed/dummy method in the original.
}
-void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay,
+void Screen::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay,
const Common::Point &initialOffset) {
int width1, width2;
int widthDiff, widthDiff2;
@@ -128,7 +128,8 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
int runLength;
byte *srcImgData, *destImgData;
- byte *srcP, *destP;
+ const byte *srcP;
+ byte *destP;
byte byteVal, byteVal2;
PictureResource *srcPic;
@@ -292,7 +293,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
// loc_2566F
if (srcFlags & DISPFLAG_2) {
// loc_256FA
- srcP = (byte *)_screenSurface.getPixels() + srcOffset;
+ srcP = (const byte *)getPixels() + srcOffset;
for (int yp = 0; yp < height1; ++yp) {
for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
@@ -325,13 +326,16 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
}
} else {
// loc_25829
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::copy(srcP, srcP + width2, destP);
srcP += width2 + widthDiff;
destP += width2 + widthDiff2;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
}
} else {
@@ -341,13 +345,16 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
error("TODO: sDrawPic variation");
} else {
// loc_2606D
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::copy(srcP, srcP + width2, destP);
destP += width2 + widthDiff2;
srcP += width2 + widthDiff;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
}
} else {
@@ -530,11 +537,14 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
// loc_27477
if (destFlags & DISPFLAG_8) {
// loc_27481
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
Common::fill(destP, destP + width2, onOff);
destP += width2 + widthDiff2;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
} else {
// loc_2753C
destP = destImgData + screenOffset;
@@ -561,7 +571,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
if (srcFlags & PICFLAG_100) {
if (isClipped) {
// loc_266E3
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
int xMax = tmpWidth + width2;
tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
@@ -592,9 +602,12 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
if (yp >= tmpHeight)
destP += widthDiff2;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
} else {
// loc_26815
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
for (int xi = 0; xi < width2; ++xi, ++destP) {
@@ -618,10 +631,13 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
destP += widthDiff2;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
} else {
// Direct screen write
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
@@ -631,6 +647,9 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
destP += widthDiff2;
srcP += widthDiff;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
} else if (srcFlags & PICFLAG_100) {
srcP = srcImgData;
@@ -663,7 +682,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
}
} else {
// loc_26BD5
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
byteVal2 = 0;
@@ -684,10 +703,13 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
destP += widthDiff2;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
} else {
// loc_26C9A
- destP = (byte *)_screenSurface.getPixels() + screenOffset;
+ destP = (byte *)getPixels() + screenOffset;
for (int yp = 0; yp < height1; ++yp) {
for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
@@ -696,6 +718,9 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
destP += widthDiff2;
srcP += widthDiff;
}
+
+ addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+ offset.y + height1));
}
} else {
// loc_26D2F
@@ -850,12 +875,12 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des
}
}
-void GraphicsManager::drawANumber(DisplayResource *display, int num, const Common::Point &pt) {
+void Screen::drawANumber(DisplayResource *display, int num, const Common::Point &pt) {
PictureResource *pic = _vm->_bVoy->boltEntry(num + 261)._picResource;
sDrawPic(pic, display, pt);
}
-void GraphicsManager::fillPic(DisplayResource *display, byte onOff) {
+void Screen::fillPic(DisplayResource *display, byte onOff) {
PictureResource *pic;
if (display->_flags & DISPFLAG_VIEWPORT) {
pic = ((ViewPortResource *)display)->_currentPic;
@@ -876,11 +901,11 @@ void GraphicsManager::fillPic(DisplayResource *display, byte onOff) {
/**
* Queues the given picture for display
*/
-void GraphicsManager::sDisplayPic(PictureResource *pic) {
+void Screen::sDisplayPic(PictureResource *pic) {
_vm->_eventsManager->_intPtr._flipWait = true;
}
-void GraphicsManager::flipPage() {
+void Screen::flipPage() {
Common::Array<ViewPortResource *> &viewPorts = _viewPortListPtr->_entries;
bool flipFlag = false;
@@ -907,7 +932,7 @@ void GraphicsManager::flipPage() {
}
}
-void GraphicsManager::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
+void Screen::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
PictureResource *srcPic, PictureResource *destPic) {
// WORKAROUND: Since _backgroundPage can point to a resource freed at the end of display methods,
// I'm now explicitly resetting it to null in screenReset(), so at this point it can be null
@@ -929,33 +954,26 @@ void GraphicsManager::restoreBack(Common::Array<Common::Rect> &rectList, int rec
_saveBack = saveBack;
}
-void GraphicsManager::clearPalette() {
- byte palette[768];
- Common::fill(&palette[0], &palette[768], 0);
- g_system->getPaletteManager()->setPalette(&palette[0], 0, 256);
-}
-
-void GraphicsManager::setPalette(const byte *palette, int start, int count) {
- g_system->getPaletteManager()->setPalette(palette, start, count);
+void Screen::setPalette(const byte *palette, int start, int count) {
+ Graphics::Screen::setPalette(palette, start, count);
_vm->_eventsManager->_gameData._hasPalette = false;
}
-void GraphicsManager::setPalette128(const byte *palette, int start, int count) {
+void Screen::setPalette128(const byte *palette, int start, int count) {
byte rgb[3];
- g_system->getPaletteManager()->grabPalette(&rgb[0], 128, 1);
- g_system->getPaletteManager()->setPalette(palette, start, count);
- g_system->getPaletteManager()->setPalette(&rgb[0], 128, 1);
+ getPalette(&rgb[0], 128, 1);
+ Graphics::Screen::setPalette(palette, start, count);
+ Graphics::Screen::setPalette(&rgb[0], 128, 1);
}
-
-void GraphicsManager::resetPalette() {
+void Screen::resetPalette() {
for (int i = 0; i < 256; ++i)
setColor(i, 0, 0, 0);
_vm->_eventsManager->_intPtr._hasPalette = true;
}
-void GraphicsManager::setColor(int idx, byte r, byte g, byte b) {
+void Screen::setColor(int idx, byte r, byte g, byte b) {
byte *vgaP = &_VGAColors[idx * 3];
vgaP[0] = r;
vgaP[1] = g;
@@ -965,7 +983,7 @@ void GraphicsManager::setColor(int idx, byte r, byte g, byte b) {
_vm->_eventsManager->_intPtr._palEndIndex = MAX(_vm->_eventsManager->_intPtr._palEndIndex, idx);
}
-void GraphicsManager::setOneColor(int idx, byte r, byte g, byte b) {
+void Screen::setOneColor(int idx, byte r, byte g, byte b) {
byte palEntry[3];
palEntry[0] = r;
palEntry[1] = g;
@@ -973,7 +991,7 @@ void GraphicsManager::setOneColor(int idx, byte r, byte g, byte b) {
g_system->getPaletteManager()->setPalette(&palEntry[0], idx, 1);
}
-void GraphicsManager::setColors(int start, int count, const byte *pal) {
+void Screen::setColors(int start, int count, const byte *pal) {
for (int i = 0; i < count; ++i) {
if ((i + start) != 128) {
const byte *rgb = pal + i * 3;
@@ -984,7 +1002,7 @@ void GraphicsManager::setColors(int start, int count, const byte *pal) {
_vm->_eventsManager->_intPtr._hasPalette = true;
}
-void GraphicsManager::screenReset() {
+void Screen::screenReset() {
resetPalette();
_backgroundPage = NULL;
@@ -994,7 +1012,7 @@ void GraphicsManager::screenReset() {
_vm->flipPageAndWait();
}
-void GraphicsManager::fadeDownICF1(int steps) {
+void Screen::fadeDownICF1(int steps) {
if (steps > 0) {
int stepAmount = _vm->_voy->_fadingAmount2 / steps;
@@ -1007,7 +1025,7 @@ void GraphicsManager::fadeDownICF1(int steps) {
_vm->_voy->_fadingAmount2 = 0;
}
-void GraphicsManager::fadeUpICF1(int steps) {
+void Screen::fadeUpICF1(int steps) {
if (steps > 0) {
int stepAmount = (63 - _vm->_voy->_fadingAmount2) / steps;
@@ -1020,7 +1038,7 @@ void GraphicsManager::fadeUpICF1(int steps) {
_vm->_voy->_fadingAmount2 = 63;
}
-void GraphicsManager::fadeDownICF(int steps) {
+void Screen::fadeDownICF(int steps) {
if (steps > 0) {
_vm->_eventsManager->hideCursor();
int stepAmount1 = _vm->_voy->_fadingAmount1 / steps;
@@ -1037,14 +1055,19 @@ void GraphicsManager::fadeDownICF(int steps) {
_vm->_voy->_fadingAmount2 = 0;
}
-void GraphicsManager::drawDot() {
- for (int y = 0; y < 9; ++y) {
- byte *pDest = (byte *)_screenSurface.getPixels() + DOT_LINE_START[y] + DOT_LINE_OFFSET[y];
- Common::fill(pDest, pDest + DOT_LINE_LENGTH[y], 0x80);
+void Screen::drawDot() {
+ for (int idx = 0; idx < 9; ++idx) {
+ uint offset = DOT_LINE_START[idx] + DOT_LINE_OFFSET[idx];
+ int xp = offset % SCREEN_WIDTH;
+ int yp = offset / SCREEN_WIDTH;
+
+ byte *pDest = (byte *)getPixels() + offset;
+ Common::fill(pDest, pDest + DOT_LINE_LENGTH[idx], 0x80);
+ addDirtyRect(Common::Rect(xp, yp, xp + DOT_LINE_LENGTH[idx], yp + 1));
}
}
-void GraphicsManager::synchronize(Common::Serializer &s) {
+void Screen::synchronize(Common::Serializer &s) {
s.syncBytes(&_VGAColors[0], PALETTE_SIZE);
}
diff --git a/engines/voyeur/graphics.h b/engines/voyeur/screen.h
index e4d0b38650..aaf61747a4 100644
--- a/engines/voyeur/graphics.h
+++ b/engines/voyeur/screen.h
@@ -27,17 +27,15 @@
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
-#include "graphics/surface.h"
+#include "graphics/screen.h"
namespace Voyeur {
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
-#define PALETTE_COUNT 256
-#define PALETTE_SIZE (256 * 3)
class VoyeurEngine;
-class GraphicsManager;
+class Screen;
class DisplayResource;
class PictureResource;
class ViewPortResource;
@@ -54,12 +52,12 @@ public:
DrawInfo(int penColor, const Common::Point &pos);
};
-typedef void (GraphicsManager::*GraphicMethodPtr)();
-typedef void (GraphicsManager::*ViewPortSetupPtr)(ViewPortResource *);
-typedef void (GraphicsManager::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
-typedef void (GraphicsManager::*ViewPortRestorePtr)(ViewPortResource *);
+typedef void (Screen::*ScreenMethodPtr)();
+typedef void (Screen::*ViewPortSetupPtr)(ViewPortResource *);
+typedef void (Screen::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
+typedef void (Screen::*ViewPortRestorePtr)(ViewPortResource *);
-class GraphicsManager {
+class Screen: public Graphics::Screen {
public:
byte _VGAColors[PALETTE_SIZE];
PictureResource *_backgroundPage;
@@ -69,7 +67,6 @@ public:
bool _saveBack;
Common::Rect *_clipPtr;
uint _planeSelect;
- Graphics::Surface _screenSurface;
CMapResource *_backColors;
FontInfoResource *_fontPtr;
PictureResource *_fontChar;
@@ -81,8 +78,8 @@ private:
void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
PictureResource *srcPic, PictureResource *destPic);
public:
- GraphicsManager(VoyeurEngine *vm);
- ~GraphicsManager();
+ Screen(VoyeurEngine *vm);
+ virtual ~Screen();
void sInitGraphics();
@@ -96,7 +93,6 @@ public:
void sDisplayPic(PictureResource *pic);
void drawANumber(DisplayResource *display, int num, const Common::Point &pt);
void flipPage();
- void clearPalette();
void setPalette(const byte *palette, int start, int count);
void setPalette128(const byte *palette, int start, int count);
void resetPalette();
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index cbb6846340..01b76a72d1 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -22,7 +22,7 @@
#include "voyeur/voyeur.h"
#include "voyeur/animation.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/staticres.h"
#include "common/scummsys.h"
#include "common/config-manager.h"
@@ -40,7 +40,7 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc)
_debugger = nullptr;
_eventsManager = nullptr;
_filesManager = nullptr;
- _graphicsManager = nullptr;
+ _screen = nullptr;
_soundManager = nullptr;
_voy = nullptr;
_bVoy = NULL;
@@ -65,13 +65,6 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc)
DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
- _debugger = new Debugger(this);
- _eventsManager = new EventsManager(this);
- _filesManager = new FilesManager(this);
- _graphicsManager = new GraphicsManager(this);
- _soundManager = new SoundManager(_mixer);
- _voy = new SVoy(this);
-
_stampLibPtr = nullptr;
_controlGroupPtr = nullptr;
_stampData = nullptr;
@@ -88,7 +81,7 @@ VoyeurEngine::~VoyeurEngine() {
delete _bVoy;
delete _voy;
delete _soundManager;
- delete _graphicsManager;
+ delete _screen;
delete _filesManager;
delete _eventsManager;
delete _debugger;
@@ -126,15 +119,22 @@ void VoyeurEngine::ESP_Init() {
}
void VoyeurEngine::globalInitBolt() {
+ _debugger = new Debugger(this);
+ _eventsManager = new EventsManager(this);
+ _filesManager = new FilesManager(this);
+ _screen = new Screen(this);
+ _soundManager = new SoundManager(_mixer);
+ _voy = new SVoy(this);
+
initBolt();
_filesManager->openBoltLib("bvoy.blt", _bVoy);
_bVoy->getBoltGroup(0x000);
_bVoy->getBoltGroup(0x100);
- _graphicsManager->_fontPtr = &_defaultFontInfo;
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
- assert(_graphicsManager->_fontPtr->_curFont);
+ _screen->_fontPtr = &_defaultFontInfo;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+ assert(_screen->_fontPtr->_curFont);
// Setup default flags
_voy->_viewBounds = nullptr;
@@ -144,13 +144,13 @@ void VoyeurEngine::globalInitBolt() {
void VoyeurEngine::initBolt() {
vInitInterrupts();
- _graphicsManager->sInitGraphics();
+ _screen->sInitGraphics();
_eventsManager->vInitColor();
initInput();
}
void VoyeurEngine::vInitInterrupts() {
- _eventsManager->_intPtr._palette = &_graphicsManager->_VGAColors[0];
+ _eventsManager->_intPtr._palette = &_screen->_VGAColors[0];
}
void VoyeurEngine::initInput() {
@@ -213,8 +213,8 @@ bool VoyeurEngine::doHeadTitle() {
}
void VoyeurEngine::showConversionScreen() {
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x502)._picResource;
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_backgroundPage = _bVoy->boltEntry(0x502)._picResource;
+ _screen->_vPort->setupViewPort();
flipPageAndWait();
// Immediate palette load to show the initial screen
@@ -237,7 +237,7 @@ void VoyeurEngine::showConversionScreen() {
flipPageAndWaitForFade();
- _graphicsManager->screenReset();
+ _screen->screenReset();
}
bool VoyeurEngine::doLock() {
@@ -249,28 +249,28 @@ bool VoyeurEngine::doLock() {
if (_bVoy->getBoltGroup(0x700)) {
Common::String password = "3333";
- _graphicsManager->_backgroundPage = _bVoy->getPictureResource(0x700);
- _graphicsManager->_backColors = _bVoy->getCMapResource(0x701);
+ _screen->_backgroundPage = _bVoy->getPictureResource(0x700);
+ _screen->_backColors = _bVoy->getCMapResource(0x701);
PictureResource *cursorPic = _bVoy->getPictureResource(0x702);
_voy->_viewBounds = _bVoy->boltEntry(0x704)._rectResource;
Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(0x705)._rectResource->_entries;
assert(cursorPic);
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_vPort->setupViewPort();
- _graphicsManager->_backColors->startFade();
- _graphicsManager->_vPort->_parent->_flags |= DISPFLAG_8;
- _graphicsManager->flipPage();
+ _screen->_backColors->startFade();
+ _screen->_vPort->_parent->_flags |= DISPFLAG_8;
+ _screen->flipPage();
_eventsManager->sWaitFlip();
while (!shouldQuit() && (_eventsManager->_fadeStatus & 1))
_eventsManager->delay(1);
_eventsManager->setCursorColor(127, 0);
- _graphicsManager->setColor(1, 64, 64, 64);
- _graphicsManager->setColor(2, 96, 96, 96);
- _graphicsManager->setColor(3, 160, 160, 160);
- _graphicsManager->setColor(4, 224, 224, 224);
+ _screen->setColor(1, 64, 64, 64);
+ _screen->setColor(2, 96, 96, 96);
+ _screen->setColor(3, 160, 160, 160);
+ _screen->setColor(4, 224, 224, 224);
// Set up the cursor
_eventsManager->setCursor(cursorPic);
@@ -278,9 +278,9 @@ bool VoyeurEngine::doLock() {
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x708)._fontResource;
- _graphicsManager->_fontPtr->_fontSaveBack = 0;
- _graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x708)._fontResource;
+ _screen->_fontPtr->_fontSaveBack = 0;
+ _screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
Common::String dateString = "ScummVM";
Common::String displayString = Common::String::format("Last Play %s", dateString.c_str());
@@ -288,16 +288,16 @@ bool VoyeurEngine::doLock() {
bool firstLoop = true;
bool breakFlag = false;
while (!breakFlag && !shouldQuit()) {
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_vPort->setupViewPort();
flipPageAndWait();
// Display the last play time
- _graphicsManager->_fontPtr->_pos = Common::Point(0, 97);
- _graphicsManager->_fontPtr->_justify = ALIGN_CENTER;
- _graphicsManager->_fontPtr->_justifyWidth = 384;
- _graphicsManager->_fontPtr->_justifyHeight = 97;
+ _screen->_fontPtr->_pos = Common::Point(0, 97);
+ _screen->_fontPtr->_justify = ALIGN_CENTER;
+ _screen->_fontPtr->_justifyWidth = 384;
+ _screen->_fontPtr->_justifyHeight = 97;
- _graphicsManager->_vPort->drawText(displayString);
+ _screen->_vPort->drawText(displayString);
flipPageAndWait();
if (firstLoop) {
@@ -356,7 +356,7 @@ bool VoyeurEngine::doLock() {
} else if (key == 11) {
// New code
if ((password.empty() && displayString.empty()) || (password != displayString)) {
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_vPort->setupViewPort();
password = displayString;
displayString = "";
continue;
@@ -373,9 +373,9 @@ bool VoyeurEngine::doLock() {
_soundManager->playVOCMap(wrongVoc, wrongVocSize);
}
- _graphicsManager->fillPic(_graphicsManager->_vPort, 0);
+ _screen->fillPic(_screen->_vPort, 0);
flipPageAndWait();
- _graphicsManager->resetPalette();
+ _screen->resetPalette();
_voy->_viewBounds = nullptr;
_bVoy->freeBoltGroup(0x700);
@@ -393,9 +393,9 @@ void VoyeurEngine::showTitleScreen() {
if (!_bVoy->getBoltGroup(0x500))
return;
- _graphicsManager->_backgroundPage = _bVoy->getPictureResource(0x500);
+ _screen->_backgroundPage = _bVoy->getPictureResource(0x500);
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_vPort->setupViewPort();
flipPageAndWait();
// Immediate palette load to show the initial screen
@@ -422,18 +422,18 @@ void VoyeurEngine::showTitleScreen() {
return;
}
- _graphicsManager->screenReset();
+ _screen->screenReset();
_eventsManager->delayClick(200);
// Voyeur title
playRL2Video("a1100100.rl2");
- _graphicsManager->screenReset();
+ _screen->screenReset();
_bVoy->freeBoltGroup(0x500);
}
void VoyeurEngine::doOpening() {
- _graphicsManager->screenReset();
+ _screen->screenReset();
if (!_bVoy->getBoltGroup(0x200))
return;
@@ -459,10 +459,10 @@ void VoyeurEngine::doOpening() {
_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
for (int i = 0; i < 256; ++i)
- _graphicsManager->setColor(i, 8, 8, 8);
+ _screen->setColor(i, 8, 8, 8);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_vPort->setupViewPort();
+ _screen->_vPort->setupViewPort();
flipPageAndWait();
RL2Decoder decoder;
@@ -472,14 +472,12 @@ void VoyeurEngine::doOpening() {
while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) {
if (decoder.hasDirtyPalette()) {
const byte *palette = decoder.getPalette();
- _graphicsManager->setPalette(palette, 0, 256);
+ _screen->setPalette(palette, 0, 256);
}
if (decoder.needsUpdate()) {
const Graphics::Surface *frame = decoder.decodeNextFrame();
-
- Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
- (byte *)_graphicsManager->_screenSurface.getPixels());
+ _screen->blitFrom(*frame);
if (decoder.getCurFrame() >= (int32)READ_LE_UINT32(frameTable + frameIndex * 4)) {
if (creditShow) {
@@ -499,7 +497,7 @@ void VoyeurEngine::doOpening() {
}
if (textPic) {
- _graphicsManager->sDrawPic(textPic, _graphicsManager->_vPort, textPos);
+ _screen->sDrawPic(textPic, _screen->_vPort, textPos);
}
flipPageAndWait();
@@ -527,14 +525,12 @@ void VoyeurEngine::playRL2Video(const Common::String &filename) {
while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) {
if (decoder.hasDirtyPalette()) {
const byte *palette = decoder.getPalette();
- _graphicsManager->setPalette(palette, 0, 256);
+ _screen->setPalette(palette, 0, 256);
}
if (decoder.needsUpdate()) {
const Graphics::Surface *frame = decoder.decodeNextFrame();
-
- Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
- (byte *)_graphicsManager->_screenSurface.getPixels());
+ _screen->blitFrom(*frame);
}
_eventsManager->getMouseInfo();
@@ -573,17 +569,16 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
(decoder.getCurFrame() < endFrame)) {
if (decoder.needsUpdate()) {
const Graphics::Surface *frame = decoder.decodeNextFrame();
+ _screen->blitFrom(*frame);
- Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
- (byte *)_graphicsManager->_screenSurface.getPixels());
if (_voy->_eventFlags & EVTFLAG_RECORDING)
- _graphicsManager->drawDot();
+ _screen->drawDot();
}
if (decoder.hasDirtyPalette()) {
const byte *palette = decoder.getPalette();
- _graphicsManager->setPalette(palette, 0, decoder.getPaletteCount());
- _graphicsManager->setOneColor(128, 220, 20, 20);
+ _screen->setPalette(palette, 0, decoder.getPaletteCount());
+ _screen->setOneColor(128, 220, 20, 20);
}
_eventsManager->getMouseInfo();
@@ -591,13 +586,13 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
}
// RL2 finished
- _graphicsManager->screenReset();
+ _screen->screenReset();
_voy->_eventFlags &= ~EVTFLAG_RECORDING;
if (_voy->_eventFlags & EVTFLAG_8) {
assert(pic);
- byte *imgData = _graphicsManager->_vPort->_currentPic->_imgData;
- _graphicsManager->_vPort->_currentPic->_imgData = pic->_imgData;
+ byte *imgData = _screen->_vPort->_currentPic->_imgData;
+ _screen->_vPort->_currentPic->_imgData = pic->_imgData;
pic->_imgData = imgData;
_voy->_eventFlags &= ~EVTFLAG_8;
}
@@ -608,13 +603,13 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
void VoyeurEngine::playAudio(int audioId) {
_bVoy->getBoltGroup(0x7F00);
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
+ _screen->_backgroundPage = _bVoy->boltEntry(0x7F00 +
BLIND_TABLE[audioId] * 2)._picResource;
- _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
+ _screen->_backColors = _bVoy->boltEntry(0x7F01 +
BLIND_TABLE[audioId] * 2)._cMapResource;
- _graphicsManager->_vPort->setupViewPort();
- _graphicsManager->_backColors->startFade();
+ _screen->_vPort->setupViewPort();
+ _screen->_backColors->startFade();
flipPageAndWaitForFade();
_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
@@ -633,26 +628,26 @@ void VoyeurEngine::playAudio(int audioId) {
_soundManager->stopVOCPlay();
_bVoy->freeBoltGroup(0x7F00);
- _graphicsManager->_vPort->setupViewPort(NULL);
+ _screen->_vPort->setupViewPort(NULL);
_voy->_eventFlags &= ~EVTFLAG_RECORDING;
_voy->_playStampMode = 129;
}
void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::String &location) {
- _graphicsManager->setColor(128, 16, 16, 16);
- _graphicsManager->setColor(224, 220, 220, 220);
+ _screen->setColor(128, 16, 16, 16);
+ _screen->setColor(224, 220, 220, 220);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_vPort->setupViewPort(NULL);
- _graphicsManager->_vPort->fillPic(0x80);
- _graphicsManager->flipPage();
+ _screen->_vPort->setupViewPort(NULL);
+ _screen->_vPort->fillPic(0x80);
+ _screen->flipPage();
_eventsManager->sWaitFlip();
flipPageAndWait();
- _graphicsManager->_vPort->fillPic(0x80);
+ _screen->_vPort->fillPic(0x80);
- FontInfoResource &fi = *_graphicsManager->_fontPtr;
+ FontInfoResource &fi = *_screen->_fontPtr;
fi._curFont = _bVoy->boltEntry(257)._fontResource;
fi._foreColor = 224;
fi._fontSaveBack = 0;
@@ -661,7 +656,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St
fi._justifyWidth = 384;
fi._justifyHeight = 120;
- _graphicsManager->_vPort->drawText(time);
+ _screen->_vPort->drawText(time);
if (!location.empty()) {
fi._pos = Common::Point(0, 138);
@@ -669,7 +664,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St
fi._justifyWidth = 384;
fi._justifyHeight = 140;
- _graphicsManager->_vPort->drawText(location);
+ _screen->_vPort->drawText(location);
}
flipPageAndWait();
@@ -680,8 +675,8 @@ void VoyeurEngine::saveLastInplay() {
}
void VoyeurEngine::flipPageAndWait() {
- _graphicsManager->_vPort->_flags |= DISPFLAG_8;
- _graphicsManager->flipPage();
+ _screen->_vPort->_flags |= DISPFLAG_8;
+ _screen->flipPage();
_eventsManager->sWaitFlip();
}
@@ -702,7 +697,7 @@ void VoyeurEngine::showEndingNews() {
PictureResource *pic = _bVoy->boltEntry(_playStampGroupId)._picResource;
CMapResource *pal = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
- _graphicsManager->_vPort->setupViewPort(pic);
+ _screen->_vPort->setupViewPort(pic);
pal->startFade();
flipPageAndWaitForFade();
@@ -717,7 +712,7 @@ void VoyeurEngine::showEndingNews() {
pal = _bVoy->boltEntry(_playStampGroupId + idx * 2 + 1)._cMapResource;
}
- _graphicsManager->_vPort->setupViewPort(pic);
+ _screen->_vPort->setupViewPort(pic);
pal->startFade();
flipPageAndWaitForFade();
@@ -852,7 +847,7 @@ void VoyeurEngine::synchronize(Common::Serializer &s) {
// Sub-systems
_voy->synchronize(s);
- _graphicsManager->synchronize(s);
+ _screen->synchronize(s);
_mainThread->synchronize(s);
_controlPtr->_state->synchronize(s);
}
@@ -906,8 +901,8 @@ void VoyeurSavegameHeader::write(Common::OutSaveFile *f, VoyeurEngine *vm, const
// Create a thumbnail and save it
Graphics::Surface *thumb = new Graphics::Surface();
- ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(),
- SCREEN_WIDTH, SCREEN_HEIGHT, vm->_graphicsManager->_VGAColors);
+ ::createThumbnail(thumb, (const byte *)vm->_screen->getPixels(),
+ SCREEN_WIDTH, SCREEN_HEIGHT, vm->_screen->_VGAColors);
Graphics::saveThumbnail(*f, *thumb);
thumb->free();
delete thumb;
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index e0bb734fa8..9cda85fd51 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -27,7 +27,7 @@
#include "voyeur/data.h"
#include "voyeur/events.h"
#include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
#include "voyeur/sound.h"
#include "common/scummsys.h"
#include "common/system.h"
@@ -164,7 +164,7 @@ public:
Debugger *_debugger;
EventsManager *_eventsManager;
FilesManager *_filesManager;
- GraphicsManager *_graphicsManager;
+ Screen *_screen;
SoundManager *_soundManager;
SVoy *_voy;
diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp
index 13ef31839a..e9591955fc 100644
--- a/engines/voyeur/voyeur_game.cpp
+++ b/engines/voyeur/voyeur_game.cpp
@@ -149,8 +149,8 @@ void VoyeurEngine::playStamp() {
case 130: {
// user selected to send the tape
if (_bVoy->getBoltGroup(_playStampGroupId)) {
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(_playStampGroupId)._picResource;
- _graphicsManager->_backColors = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
+ _screen->_backgroundPage = _bVoy->boltEntry(_playStampGroupId)._picResource;
+ _screen->_backColors = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
buttonId = getChooseButton();
if (_eventsManager->_rightClick)
@@ -158,7 +158,7 @@ void VoyeurEngine::playStamp() {
buttonId = 4;
_bVoy->freeBoltGroup(_playStampGroupId);
- _graphicsManager->screenReset();
+ _screen->screenReset();
_playStampGroupId = -1;
flag = true;
@@ -232,8 +232,8 @@ void VoyeurEngine::closeStamp() {
}
void VoyeurEngine::doTailTitle() {
- _graphicsManager->_vPort->setupViewPort(NULL);
- _graphicsManager->screenReset();
+ _screen->_vPort->setupViewPort(NULL);
+ _screen->screenReset();
if (_bVoy->getBoltGroup(0x600)) {
RL2Decoder decoder;
@@ -245,12 +245,12 @@ void VoyeurEngine::doTailTitle() {
doClosingCredits();
if (!shouldQuit() && !_eventsManager->_mouseClicked) {
- _graphicsManager->screenReset();
+ _screen->screenReset();
PictureResource *pic = _bVoy->boltEntry(0x602)._picResource;
CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource;
- _graphicsManager->_vPort->setupViewPort(pic);
+ _screen->_vPort->setupViewPort(pic);
pal->startFade();
flipPageAndWaitForFade();
_eventsManager->delayClick(300);
@@ -258,7 +258,7 @@ void VoyeurEngine::doTailTitle() {
pic = _bVoy->boltEntry(0x604)._picResource;
pal = _bVoy->boltEntry(0x605)._cMapResource;
- _graphicsManager->_vPort->setupViewPort(pic);
+ _screen->_vPort->setupViewPort(pic);
pal->startFade();
flipPageAndWaitForFade();
_eventsManager->delayClick(120);
@@ -283,26 +283,26 @@ void VoyeurEngine::doClosingCredits() {
const char *msg = (const char *)_bVoy->memberAddr(0x404);
const byte *creditList = (const byte *)_bVoy->memberAddr(0x405);
- _graphicsManager->_vPort->setupViewPort(NULL);
- _graphicsManager->setColor(1, 180, 180, 180);
- _graphicsManager->setColor(2, 200, 200, 200);
+ _screen->_vPort->setupViewPort(NULL);
+ _screen->setColor(1, 180, 180, 180);
+ _screen->setColor(2, 200, 200, 200);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x402)._fontResource;
- _graphicsManager->_fontPtr->_foreColor = 2;
- _graphicsManager->_fontPtr->_backColor = 2;
- _graphicsManager->_fontPtr->_fontSaveBack = false;
- _graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x402)._fontResource;
+ _screen->_fontPtr->_foreColor = 2;
+ _screen->_fontPtr->_backColor = 2;
+ _screen->_fontPtr->_fontSaveBack = false;
+ _screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
_soundManager->startVOCPlay(152);
- FontInfoResource &fi = *_graphicsManager->_fontPtr;
+ FontInfoResource &fi = *_screen->_fontPtr;
for (int idx = 0; idx < 78; ++idx) {
const byte *entry = creditList + idx * 6;
int flags = READ_LE_UINT16(entry + 4);
if (flags & 0x10)
- _graphicsManager->_vPort->fillPic(0);
+ _screen->_vPort->fillPic(0);
if (flags & 1) {
fi._foreColor = 1;
@@ -312,7 +312,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(0, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
@@ -324,7 +324,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(0, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
@@ -336,7 +336,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(38, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
fi._foreColor = 2;
@@ -345,7 +345,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(198, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
@@ -357,7 +357,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(0, READ_LE_UINT16(entry));
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
fi._foreColor = 2;
@@ -367,7 +367,7 @@ void VoyeurEngine::doClosingCredits() {
fi._justifyHeight = 240;
fi._pos = Common::Point(0, READ_LE_UINT16(entry) + 13);
- _graphicsManager->_vPort->drawText(msg);
+ _screen->_vPort->drawText(msg);
msg += strlen(msg) + 1;
}
@@ -381,19 +381,19 @@ void VoyeurEngine::doClosingCredits() {
}
_soundManager->stopVOCPlay();
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
_bVoy->freeBoltGroup(0x400);
}
void VoyeurEngine::doPiracy() {
- _graphicsManager->screenReset();
- _graphicsManager->setColor(1, 0, 0, 0);
- _graphicsManager->setColor(2, 255, 255, 255);
+ _screen->screenReset();
+ _screen->setColor(1, 0, 0, 0);
+ _screen->setColor(2, 255, 255, 255);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_vPort->setupViewPort(NULL);
- _graphicsManager->_vPort->fillPic(1);
+ _screen->_vPort->setupViewPort(NULL);
+ _screen->_vPort->fillPic(1);
- FontInfoResource &fi = *_graphicsManager->_fontPtr;
+ FontInfoResource &fi = *_screen->_fontPtr;
fi._curFont = _bVoy->boltEntry(0x101)._fontResource;
fi._foreColor = 2;
fi._backColor = 2;
@@ -406,7 +406,7 @@ void VoyeurEngine::doPiracy() {
// Loop through the piracy message array to draw each line
for (int idx = 0, yp = 33; idx < 10; ++idx) {
fi._pos = Common::Point(0, yp);
- _graphicsManager->_vPort->drawText(PIRACY_MESSAGE[idx]);
+ _screen->_vPort->drawText(PIRACY_MESSAGE[idx]);
yp += fi._curFont->_fontHeight + 4;
}
@@ -439,27 +439,27 @@ void VoyeurEngine::reviewTape() {
_voy->_viewBounds = _bVoy->boltEntry(0x907)._rectResource;
Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(0x906)._rectResource->_entries;
- _graphicsManager->_backColors = _bVoy->boltEntry(0x902)._cMapResource;
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x901)._picResource;
- _graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
- _graphicsManager->_backColors->startFade();
+ _screen->_backColors = _bVoy->boltEntry(0x902)._cMapResource;
+ _screen->_backgroundPage = _bVoy->boltEntry(0x901)._picResource;
+ _screen->_vPort->setupViewPort(_screen->_backgroundPage);
+ _screen->_backColors->startFade();
flipPageAndWaitForFade();
- _graphicsManager->setColor(1, 32, 32, 32);
- _graphicsManager->setColor(2, 96, 96, 96);
- _graphicsManager->setColor(3, 160, 160, 160);
- _graphicsManager->setColor(4, 224, 224, 224);
- _graphicsManager->setColor(9, 24, 64, 24);
- _graphicsManager->setColor(10, 64, 132, 64);
- _graphicsManager->setColor(11, 100, 192, 100);
- _graphicsManager->setColor(12, 120, 248, 120);
+ _screen->setColor(1, 32, 32, 32);
+ _screen->setColor(2, 96, 96, 96);
+ _screen->setColor(3, 160, 160, 160);
+ _screen->setColor(4, 224, 224, 224);
+ _screen->setColor(9, 24, 64, 24);
+ _screen->setColor(10, 64, 132, 64);
+ _screen->setColor(11, 100, 192, 100);
+ _screen->setColor(12, 120, 248, 120);
_eventsManager->setCursorColor(128, 1);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x909)._fontResource;
- _graphicsManager->_fontPtr->_fontSaveBack = false;
- _graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x909)._fontResource;
+ _screen->_fontPtr->_fontSaveBack = false;
+ _screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
_eventsManager->getMouseInfo();
if (newX == -1) {
@@ -481,37 +481,37 @@ void VoyeurEngine::reviewTape() {
needRedraw = false;
flipPageAndWait();
- _graphicsManager->_drawPtr->_penColor = 0;
- _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
- _graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
+ _screen->_drawPtr->_penColor = 0;
+ _screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
+ _screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
int yp = 45;
int eventNum = eventStart;
for (int lineNum = 0; lineNum < 8 && eventNum < _voy->_eventCount; ++lineNum, ++eventNum) {
- _graphicsManager->_fontPtr->_picFlags = DISPFLAG_NONE;
- _graphicsManager->_fontPtr->_picSelect = 0xff;
- _graphicsManager->_fontPtr->_picPick = 7;
- _graphicsManager->_fontPtr->_picOnOff = (lineNum == eventLine) ? 8 : 0;
- _graphicsManager->_fontPtr->_pos = Common::Point(68, yp);
- _graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
- _graphicsManager->_fontPtr->_justifyWidth = 0;
- _graphicsManager->_fontPtr->_justifyHeight = 0;
+ _screen->_fontPtr->_picFlags = DISPFLAG_NONE;
+ _screen->_fontPtr->_picSelect = 0xff;
+ _screen->_fontPtr->_picPick = 7;
+ _screen->_fontPtr->_picOnOff = (lineNum == eventLine) ? 8 : 0;
+ _screen->_fontPtr->_pos = Common::Point(68, yp);
+ _screen->_fontPtr->_justify = ALIGN_LEFT;
+ _screen->_fontPtr->_justifyWidth = 0;
+ _screen->_fontPtr->_justifyHeight = 0;
Common::String msg = _eventsManager->getEvidString(eventNum);
- _graphicsManager->_backgroundPage->drawText(msg);
+ _screen->_backgroundPage->drawText(msg);
yp += 15;
}
- _graphicsManager->_vPort->addSaveRect(
- _graphicsManager->_vPort->_lastPage, tempRect);
+ _screen->_vPort->addSaveRect(
+ _screen->_vPort->_lastPage, tempRect);
flipPageAndWait();
- _graphicsManager->_vPort->addSaveRect(
- _graphicsManager->_vPort->_lastPage, tempRect);
+ _screen->_vPort->addSaveRect(
+ _screen->_vPort->_lastPage, tempRect);
}
- _graphicsManager->sDrawPic(cursor, _graphicsManager->_vPort,
+ _screen->sDrawPic(cursor, _screen->_vPort,
_eventsManager->getMousePos());
flipPageAndWait();
@@ -543,34 +543,34 @@ void VoyeurEngine::reviewTape() {
flipPageAndWait();
- _graphicsManager->_drawPtr->_penColor = 0;
- _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
- _graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
+ _screen->_drawPtr->_penColor = 0;
+ _screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
+ _screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
int yp = 45;
int eventNum = eventStart;
for (int idx = 0; idx < 8 && eventNum < _voy->_eventCount; ++idx, ++eventNum) {
- _graphicsManager->_fontPtr->_picFlags = DISPFLAG_NONE;
- _graphicsManager->_fontPtr->_picSelect = 0xff;
- _graphicsManager->_fontPtr->_picPick = 7;
- _graphicsManager->_fontPtr->_picOnOff = (idx == eventLine) ? 8 : 0;
- _graphicsManager->_fontPtr->_pos = Common::Point(68, yp);
- _graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
- _graphicsManager->_fontPtr->_justifyWidth = 0;
- _graphicsManager->_fontPtr->_justifyHeight = 0;
+ _screen->_fontPtr->_picFlags = DISPFLAG_NONE;
+ _screen->_fontPtr->_picSelect = 0xff;
+ _screen->_fontPtr->_picPick = 7;
+ _screen->_fontPtr->_picOnOff = (idx == eventLine) ? 8 : 0;
+ _screen->_fontPtr->_pos = Common::Point(68, yp);
+ _screen->_fontPtr->_justify = ALIGN_LEFT;
+ _screen->_fontPtr->_justifyWidth = 0;
+ _screen->_fontPtr->_justifyHeight = 0;
Common::String msg = _eventsManager->getEvidString(eventNum);
- _graphicsManager->_backgroundPage->drawText(msg);
+ _screen->_backgroundPage->drawText(msg);
yp += 15;
}
- _graphicsManager->_vPort->addSaveRect(
- _graphicsManager->_vPort->_lastPage, tempRect);
+ _screen->_vPort->addSaveRect(
+ _screen->_vPort->_lastPage, tempRect);
flipPageAndWait();
- _graphicsManager->_vPort->addSaveRect(
- _graphicsManager->_vPort->_lastPage, tempRect);
+ _screen->_vPort->addSaveRect(
+ _screen->_vPort->_lastPage, tempRect);
flipPageAndWait();
_eventsManager->getMouseInfo();
@@ -650,7 +650,7 @@ void VoyeurEngine::reviewTape() {
newY = _eventsManager->getMousePos().y;
_voy->_fadingType = 0;
_voy->_viewBounds = nullptr;
- _graphicsManager->_vPort->setupViewPort(NULL);
+ _screen->_vPort->setupViewPort(NULL);
if (_currentVocId != -1) {
_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
@@ -673,13 +673,13 @@ void VoyeurEngine::reviewTape() {
_voy->_vocSecondsOffset = e._computerOn;
_bVoy->getBoltGroup(0x7F00);
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
+ _screen->_backgroundPage = _bVoy->boltEntry(0x7F00 +
BLIND_TABLE[_audioVideoId])._picResource;
- _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
+ _screen->_backColors = _bVoy->boltEntry(0x7F01 +
BLIND_TABLE[_audioVideoId])._cMapResource;
- _graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
- _graphicsManager->_backColors->startFade();
+ _screen->_vPort->setupViewPort(_screen->_backgroundPage);
+ _screen->_backColors->startFade();
flipPageAndWaitForFade();
_eventsManager->_intPtr._flashStep = 1;
@@ -725,16 +725,16 @@ void VoyeurEngine::reviewTape() {
}
}
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
- _graphicsManager->_vPort->fillPic(0);
+ _screen->_vPort->fillPic(0);
flipPageAndWait();
_bVoy->freeBoltGroup(0x900);
}
void VoyeurEngine::doGossip() {
- _graphicsManager->resetPalette();
- _graphicsManager->screenReset();
+ _screen->resetPalette();
+ _screen->screenReset();
if (!_bVoy->getBoltGroup(0x300))
return;
@@ -752,7 +752,7 @@ void VoyeurEngine::doGossip() {
// Transfer initial background to video decoder
PictureResource videoFrame(decoder.getRL2VideoTrack()->getBackSurface());
bgPic->_bounds.moveTo(0, 0);
- _graphicsManager->sDrawPic(bgPic, &videoFrame, Common::Point(0, 0));
+ _screen->sDrawPic(bgPic, &videoFrame, Common::Point(0, 0));
byte *frameNumsP = _bVoy->memberAddr(0x309);
byte *posP = _bVoy->boltEntry(0x30A)._data;
@@ -762,8 +762,8 @@ void VoyeurEngine::doGossip() {
decoder.close();
// Reset the palette and clear the screen
- _graphicsManager->resetPalette();
- _graphicsManager->screenReset();
+ _screen->resetPalette();
+ _screen->screenReset();
// Play interview video
RL2Decoder decoder2;
@@ -775,7 +775,7 @@ void VoyeurEngine::doGossip() {
decoder2.close();
_bVoy->freeBoltGroup(0x300);
- _graphicsManager->screenReset();
+ _screen->screenReset();
}
void VoyeurEngine::doTapePlaying() {
@@ -783,14 +783,14 @@ void VoyeurEngine::doTapePlaying() {
return;
_eventsManager->getMouseInfo();
- _graphicsManager->_backColors = _bVoy->boltEntry(0xA01)._cMapResource;
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0xA00)._picResource;
+ _screen->_backColors = _bVoy->boltEntry(0xA01)._cMapResource;
+ _screen->_backgroundPage = _bVoy->boltEntry(0xA00)._picResource;
PictureResource *pic = _bVoy->boltEntry(0xA02)._picResource;
VInitCycleResource *cycle = _bVoy->boltEntry(0xA05)._vInitCycleResource;
- _graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(57, 30));
- _graphicsManager->_backColors->startFade();
+ _screen->_vPort->setupViewPort(_screen->_backgroundPage);
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(57, 30));
+ _screen->_backColors->startFade();
flipPageAndWaitForFade();
cycle->vStartCycle();
@@ -932,9 +932,9 @@ int VoyeurEngine::getChooseButton() {
+ 6)._rectResource->_entries;
int selectedIndex = -1;
- _graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
- _graphicsManager->_backColors->_steps = 0;
- _graphicsManager->_backColors->startFade();
+ _screen->_vPort->setupViewPort(_screen->_backgroundPage);
+ _screen->_backColors->_steps = 0;
+ _screen->_backColors->startFade();
flipPageAndWait();
_voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId + 7)._rectResource;
@@ -955,7 +955,7 @@ int VoyeurEngine::getChooseButton() {
selectedIndex = idx;
if (selectedIndex != prevIndex) {
PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 8 + idx)._picResource;
- _graphicsManager->sDrawPic(btnPic, _graphicsManager->_vPort,
+ _screen->sDrawPic(btnPic, _screen->_vPort,
Common::Point(106, 200));
cursorPic = _bVoy->boltEntry(_playStampGroupId + 4)._picResource;
@@ -967,11 +967,11 @@ int VoyeurEngine::getChooseButton() {
if (selectedIndex == -1) {
cursorPic = _bVoy->boltEntry(_playStampGroupId + 2)._picResource;
PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 12)._picResource;
- _graphicsManager->sDrawPic(btnPic, _graphicsManager->_vPort,
+ _screen->sDrawPic(btnPic, _screen->_vPort,
Common::Point(106, 200));
}
- _graphicsManager->sDrawPic(cursorPic, _graphicsManager->_vPort,
+ _screen->sDrawPic(cursorPic, _screen->_vPort,
Common::Point(pt.x + 13, pt.y - 12));
flipPageAndWait();
@@ -982,9 +982,9 @@ int VoyeurEngine::getChooseButton() {
}
void VoyeurEngine::makeViewFinder() {
- _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
- _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage,
- _graphicsManager->_vPort, Common::Point(0, 0));
+ _screen->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
+ _screen->sDrawPic(_screen->_backgroundPage,
+ _screen->_vPort, Common::Point(0, 0));
CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource;
int palOffset = 0;
@@ -1016,22 +1016,22 @@ void VoyeurEngine::makeViewFinder() {
break;
}
- _graphicsManager->_vPort->drawIfaceTime();
+ _screen->_vPort->drawIfaceTime();
doTimeBar();
pal->startFade();
flipPageAndWaitForFade();
- _graphicsManager->setColor(241, 105, 105, 105);
- _graphicsManager->setColor(242, 105, 105, 105);
- _graphicsManager->setColor(243, 105, 105, 105);
- _graphicsManager->setColor(palOffset + 241, 219, 235, 235);
+ _screen->setColor(241, 105, 105, 105);
+ _screen->setColor(242, 105, 105, 105);
+ _screen->setColor(243, 105, 105, 105);
+ _screen->setColor(palOffset + 241, 219, 235, 235);
_eventsManager->_intPtr._hasPalette = true;
}
void VoyeurEngine::makeViewFinderP() {
- _graphicsManager->screenReset();
+ _screen->screenReset();
}
void VoyeurEngine::initIFace() {
@@ -1077,7 +1077,7 @@ void VoyeurEngine::initIFace() {
void VoyeurEngine::doScroll(const Common::Point &pt) {
Common::Rect clipRect(72, 47, 72 + 240, 47 + 148);
- _graphicsManager->_vPort->setupViewPort(NULL, &clipRect);
+ _screen->_vPort->setupViewPort(NULL, &clipRect);
int base = 0;
switch (_voy->_transitionId) {
@@ -1101,18 +1101,18 @@ void VoyeurEngine::doScroll(const Common::Point &pt) {
if (base) {
PictureResource *pic = _bVoy->boltEntry(base + 3)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 104));
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 104));
pic = _bVoy->boltEntry(base + 4)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 44));
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 44));
pic = _bVoy->boltEntry(base + 5)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 16));
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 16));
pic = _bVoy->boltEntry(base + 6)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 76));
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 76));
pic = _bVoy->boltEntry(base + 7)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 136));
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 136));
}
- _graphicsManager->_vPort->setupViewPort(NULL);
+ _screen->_vPort->setupViewPort(NULL);
}
void VoyeurEngine::checkTransition() {
@@ -1124,7 +1124,7 @@ void VoyeurEngine::checkTransition() {
// Only proceed if a valid day string was returned
if (!day.empty()) {
- _graphicsManager->fadeDownICF(6);
+ _screen->fadeDownICF(6);
// Get the time of day string
time = getTimeOfDay();
@@ -1163,7 +1163,7 @@ Common::String VoyeurEngine::getTimeOfDay() {
}
int VoyeurEngine::doComputerText(int maxLen) {
- FontInfoResource &font = *_graphicsManager->_fontPtr;
+ FontInfoResource &font = *_screen->_fontPtr;
int totalChars = 0;
font._curFont = _bVoy->boltEntry(0x4910)._fontResource;
@@ -1180,7 +1180,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
font._justifyWidth = 384;
font._justifyHeight = 100;
font._pos = Common::Point(128, 100);
- _graphicsManager->_vPort->drawText(END_OF_MESSAGE);
+ _screen->_vPort->drawText(END_OF_MESSAGE);
} else if (_voy->_RTVNum < _voy->_computerTimeMin && maxLen == 9999) {
if (_currentVocId != -1)
_soundManager->startVOCPlay(_currentVocId);
@@ -1188,7 +1188,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
font._justifyWidth = 384;
font._justifyHeight = 100;
font._pos = Common::Point(120, 100);
- _graphicsManager->_vPort->drawText(START_OF_MESSAGE);
+ _screen->_vPort->drawText(START_OF_MESSAGE);
} else {
char *msg = (char *)_bVoy->memberAddr(0x4900 + _voy->_computerTextId);
font._pos = Common::Point(96, 60);
@@ -1206,14 +1206,14 @@ int VoyeurEngine::doComputerText(int maxLen) {
if (c == '\0') {
if (showEnd) {
_eventsManager->delay(90);
- _graphicsManager->_drawPtr->_pos = Common::Point(96, 54);
- _graphicsManager->_drawPtr->_penColor = 254;
- _graphicsManager->_vPort->sFillBox(196, 124);
- _graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
- _graphicsManager->_fontPtr->_justifyWidth = 384;
- _graphicsManager->_fontPtr->_justifyHeight = 100;
- _graphicsManager->_fontPtr->_pos = Common::Point(128, 100);
- _graphicsManager->_vPort->drawText(END_OF_MESSAGE);
+ _screen->_drawPtr->_pos = Common::Point(96, 54);
+ _screen->_drawPtr->_penColor = 254;
+ _screen->_vPort->sFillBox(196, 124);
+ _screen->_fontPtr->_justify = ALIGN_LEFT;
+ _screen->_fontPtr->_justifyWidth = 384;
+ _screen->_fontPtr->_justifyHeight = 100;
+ _screen->_fontPtr->_pos = Common::Point(128, 100);
+ _screen->_vPort->drawText(END_OF_MESSAGE);
}
break;
}
@@ -1223,20 +1223,20 @@ int VoyeurEngine::doComputerText(int maxLen) {
yp += 10;
} else {
_eventsManager->delay(90);
- _graphicsManager->_drawPtr->_pos = Common::Point(96, 54);
- _graphicsManager->_drawPtr->_penColor = 255;
- _graphicsManager->_vPort->sFillBox(196, 124);
+ _screen->_drawPtr->_pos = Common::Point(96, 54);
+ _screen->_drawPtr->_penColor = 255;
+ _screen->_vPort->sFillBox(196, 124);
yp = 60;
}
- _graphicsManager->_fontPtr->_pos = Common::Point(96, yp);
+ _screen->_fontPtr->_pos = Common::Point(96, yp);
} else if (c == '_') {
showEnd = false;
} else {
- _graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
- _graphicsManager->_fontPtr->_justifyWidth = 0;
- _graphicsManager->_fontPtr->_justifyHeight = 0;
- _graphicsManager->_vPort->drawText(Common::String(c));
+ _screen->_fontPtr->_justify = ALIGN_LEFT;
+ _screen->_fontPtr->_justifyWidth = 0;
+ _screen->_fontPtr->_justifyHeight = 0;
+ _screen->_vPort->drawText(Common::String(c));
_eventsManager->delay(4);
}
@@ -1251,7 +1251,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
flipPageAndWait();
- _graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+ _screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
return totalChars;
}
@@ -1263,7 +1263,7 @@ void VoyeurEngine::getComputerBrush() {
int xp = (384 - pic->_bounds.width()) / 2;
int yp = (240 - pic->_bounds.height()) / 2 - 4;
- _graphicsManager->_vPort->drawPicPerm(pic, Common::Point(xp, yp));
+ _screen->_vPort->drawPicPerm(pic, Common::Point(xp, yp));
CMapResource *pal = _bVoy->boltEntry(0x490F)._cMapResource;
pal->startFade();
@@ -1280,17 +1280,17 @@ void VoyeurEngine::doTimeBar() {
int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit;
int fullHeight = MAX(151 - height, 93);
- _graphicsManager->_drawPtr->_penColor = 134;
- _graphicsManager->_drawPtr->_pos = Common::Point(39, 92);
+ _screen->_drawPtr->_penColor = 134;
+ _screen->_drawPtr->_pos = Common::Point(39, 92);
- _graphicsManager->_vPort->sFillBox(6, fullHeight - 92);
+ _screen->_vPort->sFillBox(6, fullHeight - 92);
if (height > 0) {
- _graphicsManager->setColor(215, 238, 238, 238);
+ _screen->setColor(215, 238, 238, 238);
_eventsManager->_intPtr._hasPalette = true;
- _graphicsManager->_drawPtr->_penColor = 215;
- _graphicsManager->_drawPtr->_pos = Common::Point(39, fullHeight);
- _graphicsManager->_vPort->sFillBox(6, height);
+ _screen->_drawPtr->_penColor = 215;
+ _screen->_drawPtr->_pos = Common::Point(39, fullHeight);
+ _screen->_vPort->sFillBox(6, height);
}
}
}
@@ -1303,9 +1303,9 @@ void VoyeurEngine::flashTimeBar() {
_flashTimeVal = _eventsManager->_intPtr._flashTimer;
if (_flashTimeFlag)
- _graphicsManager->setColor(240, 220, 20, 20);
+ _screen->setColor(240, 220, 20, 20);
else
- _graphicsManager->setColor(240, 220, 220, 220);
+ _screen->setColor(240, 220, 220, 220);
_eventsManager->_intPtr._hasPalette = true;
_flashTimeFlag = !_flashTimeFlag;
@@ -1343,7 +1343,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
_bVoy->getBoltGroup(_voy->_boltGroupId2);
PictureResource *pic = _bVoy->boltEntry(_voy->_boltGroupId2 + evidId * 2)._picResource;
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(
+ _screen->sDrawPic(pic, _screen->_vPort, Common::Point(
(384 - pic->_bounds.width()) / 2, (240 - pic->_bounds.height()) / 2));
_bVoy->freeBoltMember(_voy->_boltGroupId2 + evidId * 2);
@@ -1394,7 +1394,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
continue;
pic = _voy->_evPicPtrs[arrIndex];
- _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort,
+ _screen->sDrawPic(pic, _screen->_vPort,
Common::Point((384 - pic->_bounds.width()) / 2,
(240 - pic->_bounds.height()) / 2));
_voy->_evCmPtrs[arrIndex]->startFade();
diff --git a/engines/wage/combat.cpp b/engines/wage/combat.cpp
new file mode 100644
index 0000000000..4f2956d7d2
--- /dev/null
+++ b/engines/wage/combat.cpp
@@ -0,0 +1,916 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/randomhat.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+Obj *WageEngine::getOffer() {
+ if (_offer != NULL) {
+ Chr *owner = _offer->_currentOwner;
+ if (owner == NULL || owner->_playerCharacter || owner->_currentScene != _world->_player->_currentScene) {
+ _offer = NULL;
+ }
+ }
+ return _offer;
+}
+
+Chr *WageEngine::getMonster() {
+ if (_monster != NULL && _monster->_currentScene != _world->_player->_currentScene) {
+ _monster = NULL;
+ }
+ return _monster;
+}
+
+void WageEngine::encounter(Chr *player, Chr *chr) {
+ char buf[512];
+
+ snprintf(buf, 512, "You encounter %s%s.", chr->_nameProperNoun ? "" : getIndefiniteArticle(chr->_name),
+ chr->_name.c_str());
+ appendText(buf);
+
+ if (!chr->_initialComment.empty())
+ appendText(chr->_initialComment.c_str());
+
+ if (chr->_armor[Chr::HEAD_ARMOR] != NULL) {
+ snprintf(buf, 512, "%s%s is wearing %s.", chr->getDefiniteArticle(true), chr->_name.c_str(),
+ getIndefiniteArticle(chr->_armor[Chr::HEAD_ARMOR]->_name));
+ appendText(buf);
+ }
+ if (chr->_armor[Chr::BODY_ARMOR] != NULL) {
+ snprintf(buf, 512, "%s is protected by %s%s.", getGenderSpecificPronoun(chr->_gender, true),
+ prependGenderSpecificPronoun(chr->_gender), chr->_armor[Chr::BODY_ARMOR]->_name.c_str());
+ appendText(buf);
+ }
+ if (chr->_armor[Chr::SHIELD_ARMOR] != NULL) {
+ Obj *obj = chr->_armor[Chr::SHIELD_ARMOR];
+
+ snprintf(buf, 512, "%s carries %s%s.", getGenderSpecificPronoun(chr->_gender, true),
+ obj->_namePlural ? "" : getIndefiniteArticle(obj->_name), obj->_name.c_str());
+ appendText(buf);
+ }
+}
+
+void WageEngine::performCombatAction(Chr *npc, Chr *player) {
+ if (npc->_context._frozen)
+ return;
+
+ RandomHat hat(_rnd);
+
+ bool winning = (npc->_context._statVariables[PHYS_HIT_CUR] > player->_context._statVariables[PHYS_HIT_CUR]);
+ int validMoves = getValidMoveDirections(npc);
+ ObjArray *weapons = npc->getWeapons(false);
+ ObjArray *magics = npc->getMagicalObjects();
+ // TODO: Figure out under what circumstances we need to add +1
+ // for the chance (e.g. only when all values were set to 0?).
+ if (winning) {
+ if (!_world->_weaponMenuDisabled) {
+ if (!weapons->empty())
+ hat.addTokens(kTokWeapons, npc->_winningWeapons + 1);
+ if (!magics->empty())
+ hat.addTokens(kTokMagic, npc->_winningMagic);
+ }
+ if (validMoves != 0)
+ hat.addTokens(kTokRun, npc->_winningRun + 1);
+ if (!npc->_inventory.empty())
+ hat.addTokens(kTokOffer, npc->_winningOffer + 1);
+ } else {
+ if (!_world->_weaponMenuDisabled) {
+ if (!weapons->empty())
+ hat.addTokens(kTokWeapons, npc->_losingWeapons + 1);
+ if (!magics->empty())
+ hat.addTokens(kTokMagic, npc->_losingMagic);
+ }
+ if (validMoves != 0)
+ hat.addTokens(kTokRun, npc->_losingRun + 1);
+ if (!npc->_inventory.empty())
+ hat.addTokens(kTokOffer, npc->_losingOffer + 1);
+ }
+
+ ObjList *objs = &npc->_currentScene->_objs;
+ if (npc->_inventory.size() < npc->_maximumCarriedObjects) {
+ int cnt = 0;
+ for (ObjList::const_iterator it = objs->begin(); it != objs->end(); ++it, ++cnt) {
+ if ((*it)->_type != Obj::IMMOBILE_OBJECT) {
+ // TODO: I'm not sure what the chance should be here.
+ hat.addTokens(cnt, 123);
+ }
+ }
+ }
+
+ int token = hat.drawToken();
+ switch (token) {
+ case kTokWeapons:
+ // TODO: I think the monster should choose the "best" weapon.
+ performAttack(npc, player, weapons->operator[](_rnd->getRandomNumber(weapons->size() - 1)));
+ break;
+ case kTokMagic:
+ // TODO: I think the monster should choose the "best" magic.
+ performMagic(npc, player, magics->operator[](_rnd->getRandomNumber(magics->size() - 1)));
+ break;
+ case kTokRun:
+ performMove(npc, validMoves);
+ break;
+ case kTokOffer:
+ performOffer(npc, player);
+ break;
+ case kTokNone:
+ break;
+ default:
+ {
+ int cnt = 0;
+ for (ObjList::const_iterator it = objs->begin(); it != objs->end(); ++it, ++cnt)
+ if (cnt == token)
+ performTake(npc, *it);
+ break;
+ }
+ }
+
+ delete weapons;
+ delete magics;
+}
+
+static const char *const targets[] = { "head", "chest", "side" };
+
+void WageEngine::performAttack(Chr *attacker, Chr *victim, Obj *weapon) {
+ if (_world->_weaponMenuDisabled)
+ return;
+
+ // TODO: verify that a player not aiming will always target the chest??
+ int targetIndex = -1;
+ char buf[256];
+
+ if (weapon->_type != Obj::MAGICAL_OBJECT) {
+ if (attacker->_playerCharacter) {
+ targetIndex = _aim;
+ } else {
+ targetIndex = _rnd->getRandomNumber(ARRAYSIZE(targets) - 1);
+ _opponentAim = targetIndex + 1;
+ }
+
+ if (!attacker->_playerCharacter) {
+ snprintf(buf, 256, "%s%s %ss %s%s at %s%s's %s.",
+ attacker->getDefiniteArticle(true), attacker->_name.c_str(),
+ weapon->_operativeVerb.c_str(),
+ prependGenderSpecificPronoun(attacker->_gender), weapon->_name.c_str(),
+ victim->getDefiniteArticle(true), victim->_name.c_str(),
+ targets[targetIndex]);
+ appendText(buf);
+ }
+ } else if (!attacker->_playerCharacter) {
+ snprintf(buf, 256, "%s%s %ss %s%s at %s%s.",
+ attacker->getDefiniteArticle(true), attacker->_name.c_str(),
+ weapon->_operativeVerb.c_str(),
+ prependGenderSpecificPronoun(attacker->_gender), weapon->_name.c_str(),
+ victim->getDefiniteArticle(true), victim->_name.c_str());
+ appendText(buf);
+ }
+
+ playSound(weapon->_sound);
+
+ bool usesDecremented = false;
+ int chance = _rnd->getRandomNumber(255);
+ // TODO: what about obj accuracy
+ if (chance < attacker->_physicalAccuracy) {
+ usesDecremented = attackHit(attacker, victim, weapon, targetIndex);
+ } else if (weapon->_type != Obj::MAGICAL_OBJECT) {
+ appendText("A miss!");
+ } else if (attacker->_playerCharacter) {
+ appendText("The spell has no effect.");
+ }
+
+ if (!usesDecremented) {
+ decrementUses(weapon);
+ }
+}
+
+void WageEngine::decrementUses(Obj *obj) {
+ int numberOfUses = obj->_numberOfUses;
+ if (numberOfUses != -1) {
+ numberOfUses--;
+ if (numberOfUses > 0) {
+ obj->_numberOfUses = numberOfUses;
+ } else {
+ if (!obj->_failureMessage.empty()) {
+ appendText(obj->_failureMessage.c_str());
+ }
+ if (obj->_returnToRandomScene) {
+ _world->move(obj, _world->getRandomScene());
+ } else {
+ _world->move(obj, _world->_storageScene);
+ }
+ obj->resetState(obj->_currentOwner, obj->_currentScene);
+ }
+ }
+}
+
+bool WageEngine::attackHit(Chr *attacker, Chr *victim, Obj *weapon, int targetIndex) {
+ bool receivedHitTextPrinted = false;
+ char buf[512];
+
+ if (targetIndex != -1) {
+ Obj *armor = victim->_armor[targetIndex];
+ if (armor != NULL) {
+ // TODO: Absorb some damage.
+ snprintf(buf, 512, "%s%s's %s weakens the impact of %s%s's %s.",
+ victim->getDefiniteArticle(true), victim->_name.c_str(),
+ victim->_armor[targetIndex]->_name.c_str(),
+ attacker->getDefiniteArticle(false), attacker->_name.c_str(),
+ weapon->_name.c_str());
+ appendText(buf);
+ decrementUses(armor);
+ } else {
+ snprintf(buf, 512, "A hit to the %s!", targets[targetIndex]);
+ appendText(buf);
+ }
+ playSound(attacker->_scoresHitSound);
+ appendText(attacker->_scoresHitComment.c_str());
+ playSound(victim->_receivesHitSound);
+ appendText(victim->_receivesHitComment.c_str());
+ receivedHitTextPrinted = true;
+ } else if (weapon->_type == Obj::MAGICAL_OBJECT) {
+ appendText(weapon->_useMessage.c_str());
+ appendText("The spell is effective!");
+ }
+
+ bool causesPhysicalDamage = true;
+ bool causesSpiritualDamage = false;
+ bool freezesOpponent = false;
+ bool usesDecremented = false;
+
+ if (weapon->_type == Obj::THROW_WEAPON) {
+ _world->move(weapon, victim->_currentScene);
+ } else if (weapon->_type == Obj::MAGICAL_OBJECT) {
+ int type = weapon->_attackType;
+ causesPhysicalDamage = (type == Obj::CAUSES_PHYSICAL_DAMAGE || type == Obj::CAUSES_PHYSICAL_AND_SPIRITUAL_DAMAGE);
+ causesSpiritualDamage = (type == Obj::CAUSES_SPIRITUAL_DAMAGE || type == Obj::CAUSES_PHYSICAL_AND_SPIRITUAL_DAMAGE);
+ freezesOpponent = (type == Obj::FREEZES_OPPONENT);
+ }
+
+ if (causesPhysicalDamage) {
+ victim->_context._userVariables[PHYS_HIT_CUR] -= weapon->_damage;
+
+ /* Do it here to get the right order of messages in case of death. */
+ decrementUses(weapon);
+ usesDecremented = true;
+
+ if (victim->_context._userVariables[PHYS_HIT_CUR] < 0) {
+ playSound(victim->_dyingSound);
+ appendText(victim->_dyingWords.c_str());
+ snprintf(buf, 512, "%s%s is dead!", victim->getDefiniteArticle(true), victim->_name.c_str());
+ appendText(buf);
+
+ attacker->_context._kills++;
+ attacker->_context._experience += victim->_context._userVariables[SPIR_HIT_CUR] + victim->_context._userVariables[PHYS_HIT_CUR];
+
+ if (!victim->_playerCharacter && !victim->_inventory.empty()) {
+ Scene *currentScene = victim->_currentScene;
+
+ for (int i = victim->_inventory.size() - 1; i >= 0; i--) {
+ _world->move(victim->_inventory[i], currentScene);
+ }
+ Common::String *s = getGroundItemsList(currentScene);
+ appendText(s->c_str());
+ delete s;
+ }
+ _world->move(victim, _world->_storageScene);
+ } else if (attacker->_playerCharacter && !receivedHitTextPrinted) {
+ double physicalPercent = (double)victim->_context._userVariables[SPIR_HIT_CUR] /
+ victim->_context._userVariables[SPIR_HIT_BAS];
+ snprintf(buf, 512, "%s%s's condition appears to be %s.",
+ victim->getDefiniteArticle(true), victim->_name.c_str(),
+ getPercentMessage(physicalPercent));
+ appendText(buf);
+ }
+ }
+
+ if (causesSpiritualDamage) {
+ /* TODO */
+ warning("TODO: Spiritual damage");
+ }
+
+ if (freezesOpponent) {
+ victim->_context._frozen = true;
+ }
+
+ return usesDecremented;
+}
+
+void WageEngine::performMagic(Chr *attacker, Chr *victim, Obj *magicalObject) {
+ switch (magicalObject->_attackType) {
+ case Obj::HEALS_PHYSICAL_DAMAGE:
+ case Obj::HEALS_SPIRITUAL_DAMAGE:
+ case Obj::HEALS_PHYSICAL_AND_SPIRITUAL_DAMAGE:
+ performHealingMagic(attacker, magicalObject);
+ return;
+ }
+
+ performAttack(attacker, victim, magicalObject);
+}
+
+void WageEngine::performHealingMagic(Chr *chr, Obj *magicalObject) {
+ char buf[512];
+
+ if (!chr->_playerCharacter) {
+ snprintf(buf, 512, "%s%s %ss %s%s.",
+ chr->getDefiniteArticle(true), chr->_name.c_str(),
+ magicalObject->_operativeVerb.c_str(),
+ getIndefiniteArticle(magicalObject->_name), magicalObject->_name.c_str());
+ appendText(buf);
+ }
+
+ uint chance = _rnd->getRandomNumber(255);
+ if (chance < magicalObject->_accuracy) {
+ int type = magicalObject->_attackType;
+
+ if (type == Obj::HEALS_PHYSICAL_DAMAGE || type == Obj::HEALS_PHYSICAL_AND_SPIRITUAL_DAMAGE)
+ chr->_context._statVariables[PHYS_HIT_CUR] += magicalObject->_damage;
+
+ if (type == Obj::HEALS_SPIRITUAL_DAMAGE || type == Obj::HEALS_PHYSICAL_AND_SPIRITUAL_DAMAGE)
+ chr->_context._statVariables[SPIR_HIT_CUR] += magicalObject->_damage;
+
+ playSound(magicalObject->_sound);
+ appendText(magicalObject->_useMessage.c_str());
+
+ // TODO: what if enemy heals himself?
+ if (chr->_playerCharacter) {
+ double physicalPercent = (double)chr->_context._statVariables[PHYS_HIT_CUR] / chr->_context._statVariables[PHYS_HIT_BAS];
+ double spiritualPercent = (double)chr->_context._statVariables[SPIR_HIT_CUR] / chr->_context._statVariables[SPIR_HIT_BAS];
+ snprintf(buf, 256, "Your physical condition is %s.", getPercentMessage(physicalPercent));
+ appendText(buf);
+
+ snprintf(buf, 256, "Your spiritual condition is %s.", getPercentMessage(spiritualPercent));
+ appendText(buf);
+ }
+ }
+
+ decrementUses(magicalObject);
+}
+
+static const int directionsX[] = { 0, 0, 1, -1 };
+static const int directionsY[] = { -1, 1, 0, 0 };
+static const char *const directionsS[] = { "north", "south", "east", "west" };
+
+void WageEngine::performMove(Chr *chr, int validMoves) {
+ // count how many valid moves we have
+ int numValidMoves = 0;
+
+ for (int i = 0; i < 4; i++)
+ if ((validMoves & (1 << i)) != 0)
+ numValidMoves++;
+
+ // Now pick random dir
+ int dirNum = _rnd->getRandomNumber(numValidMoves - 1);
+ int dir = 0;
+
+ // And get it
+ for (int i = 0; i < 4; i++)
+ if ((validMoves & (1 << i)) != 0) {
+ if (dirNum == 0) {
+ dir = i;
+ break;
+ }
+ dirNum--;
+ }
+
+ char buf[256];
+ snprintf(buf, 256, "%s%s runs %s.", chr->getDefiniteArticle(true), chr->_name.c_str(), directionsS[dir]);
+ appendText(buf);
+
+ _running = chr;
+ Scene *currentScene = chr->_currentScene;
+ int destX = currentScene->_worldX + directionsX[dir];
+ int destY = currentScene->_worldY + directionsY[dir];
+
+ _world->move(chr, _world->getSceneAt(destX, destY));
+}
+
+void WageEngine::performOffer(Chr *attacker, Chr *victim) {
+ /* TODO: choose in a smarter way? */
+ Obj *obj = attacker->_inventory[0];
+ char buf[512];
+
+ snprintf(buf, 512, "%s%s offers %s%s.", attacker->getDefiniteArticle(true), attacker->_name.c_str(),
+ obj->_namePlural ? "some " : getIndefiniteArticle(obj->_name), obj->_name.c_str());
+
+ appendText(buf);
+
+ _offer = obj;
+}
+
+void WageEngine::performTake(Chr *npc, Obj *obj) {
+ char buf[512];
+
+ snprintf(buf, 512, "%s%s picks up the %s%s.", npc->getDefiniteArticle(true), npc->_name.c_str(),
+ getIndefiniteArticle(obj->_name), obj->_name.c_str());
+
+ appendText(buf);
+
+ _world->move(obj, npc);
+}
+
+int WageEngine::getValidMoveDirections(Chr *npc) {
+ int directions = 0;
+ Scene *currentScene = npc->_currentScene;
+ for (int dir = 0; dir < 4; dir++) {
+ if (!currentScene->_blocked[dir]) {
+ int destX = currentScene->_worldX + directionsX[dir];
+ int destY = currentScene->_worldY + directionsY[dir];
+
+ Scene *scene = _world->getSceneAt(destX, destY);
+
+ if (scene != NULL && scene->_chrs.empty()) {
+ directions |= (1 << dir);
+ }
+ }
+ }
+
+ return directions;
+}
+
+void WageEngine::regen() {
+ Chr *player = _world->_player;
+ int curHp = player->_context._statVariables[PHYS_HIT_CUR];
+ int maxHp = player->_context._statVariables[PHYS_HIT_BAS];
+ int delta = maxHp - curHp;
+
+ if (delta > 0) {
+ int bonus = (int)(delta / (8 + _rnd->getRandomNumber(2)));
+ player->_context._statVariables[PHYS_HIT_CUR] += bonus;
+ }
+}
+
+void WageEngine::takeObj(Obj *obj) {
+ if (_world->_player->_inventory.size() >= _world->_player->_maximumCarriedObjects) {
+ appendText("Your pack is full, you must drop something.");
+ } else {
+ char buf[256];
+
+ _world->move(obj, _world->_player);
+ int type = _world->_player->wearObjIfPossible(obj);
+ if (type == Chr::HEAD_ARMOR) {
+ snprintf(buf, 256, "You are now wearing the %s.", obj->_name.c_str());
+ appendText(buf);
+ } else if (type == Chr::BODY_ARMOR) {
+ snprintf(buf, 256, "You are now wearing the %s.", obj->_name.c_str());
+ appendText(buf);
+ } else if (type == Chr::SHIELD_ARMOR) {
+ snprintf(buf, 256, "You are now wearing the %s.", obj->_name.c_str());
+ appendText(buf);
+ } else if (type == Chr::MAGIC_ARMOR) {
+ snprintf(buf, 256, "You are now wearing the %s.", obj->_name.c_str());
+ appendText(buf);
+ } else {
+ snprintf(buf, 256, "You now have the %s.", obj->_name.c_str());
+ appendText(buf);
+ }
+ appendText(obj->_clickMessage.c_str());
+ }
+}
+
+bool WageEngine::handleMoveCommand(Directions dir, const char *dirName) {
+ Scene *playerScene = _world->_player->_currentScene;
+ const char *msg = playerScene->_messages[dir].c_str();
+
+ if (!playerScene->_blocked[dir]) {
+ int destX = playerScene->_worldX + directionsX[dir];
+ int destY = playerScene->_worldY + directionsY[dir];
+
+ Scene *scene = _world->getSceneAt(destX, destY);
+
+ if (scene != NULL) {
+ if (strlen(msg) > 0) {
+ appendText(msg);
+ }
+ _world->move(_world->_player, scene);
+ return true;
+ }
+ }
+ if (strlen(msg) > 0) {
+ appendText(msg);
+ } else {
+ Common::String txt("You can't go ");
+ txt += dirName;
+ txt += ".";
+ appendText(txt.c_str());
+ }
+
+ return true;
+}
+
+bool WageEngine::handleLookCommand() {
+ appendText(_world->_player->_currentScene->_text.c_str());
+
+ Common::String *items = getGroundItemsList(_world->_player->_currentScene);
+ if (items != NULL) {
+ appendText(items->c_str());
+
+ delete items;
+ }
+
+ return true;
+}
+
+Common::String *WageEngine::getGroundItemsList(Scene *scene) {
+ ObjArray objs;
+
+ for (ObjList::const_iterator it = scene->_objs.begin(); it != scene->_objs.end(); ++it)
+ if ((*it)->_type != Obj::IMMOBILE_OBJECT)
+ objs.push_back(*it);
+
+ if (!objs.empty()) {
+ Common::String *res = new Common::String("On the ground you see ");
+ appendObjNames(*res, objs);
+ return res;
+ }
+ return NULL;
+}
+
+void WageEngine::appendObjNames(Common::String &str, const ObjArray &objs) {
+ for (uint i = 0; i < objs.size(); i++) {
+ Obj *obj = objs[i];
+
+ if (!obj->_namePlural)
+ str += getIndefiniteArticle(obj->_name);
+ else
+ str += "some ";
+
+ str += obj->_name;
+
+ if (i == objs.size() - 1) {
+ str += ".";
+ } else if (i == objs.size() - 2) {
+ if (objs.size() > 2)
+ str += ",";
+ str += " and ";
+ } else {
+ str += ", ";
+ }
+ }
+}
+
+bool WageEngine::handleInventoryCommand() {
+ Chr *player = _world->_player;
+ ObjArray objs;
+
+ for (ObjArray::const_iterator it = player->_inventory.begin(); it != player->_inventory.end(); ++it)
+ if (!player->isWearing(*it))
+ objs.push_back(*it);
+
+ if (objs.empty()) {
+ appendText("Your pack is empty.");
+ } else {
+ Common::String res("Your pack contains ");
+ appendObjNames(res, objs);
+ appendText(res.c_str());
+ }
+
+ return true;
+}
+
+static const char *const armorMessages[] = {
+ "Head protection:",
+ "Chest protection:",
+ "Shield protection:", // TODO: check message
+ "Magical protection:"
+};
+
+bool WageEngine::handleStatusCommand() {
+ Chr *player = _world->_player;
+ char buf[512];
+
+ snprintf(buf, 512, "Character name: %s%s", player->getDefiniteArticle(false), player->_name.c_str());
+ appendText(buf);
+ snprintf(buf, 512, "Experience: %d", player->_context._experience);
+ appendText(buf);
+
+ int wealth = 0;
+ for (ObjArray::const_iterator it = player->_inventory.begin(); it != player->_inventory.end(); ++it)
+ wealth += (*it)->_value;
+
+ snprintf(buf, 512, "Wealth: %d", wealth);
+ appendText(buf);
+
+ for (int i = 0; i < Chr::NUMBER_OF_ARMOR_TYPES; i++) {
+ if (player->_armor[i] != NULL) {
+ snprintf(buf, 512, "%s %s", armorMessages[i], player->_armor[i]->_name.c_str());
+ appendText(buf);
+ }
+ }
+
+ for (ObjArray::const_iterator it = player->_inventory.begin(); it != player->_inventory.end(); ++it) {
+ int uses = (*it)->_numberOfUses;
+
+ if (uses > 0) {
+ snprintf(buf, 512, "Your %s has %d uses left.", (*it)->_name.c_str(), uses);
+ appendText(buf);
+ }
+ }
+
+ printPlayerCondition(player);
+
+ _commandWasQuick = true;
+
+ return true;
+}
+
+bool WageEngine::handleRestCommand() {
+ if (getMonster() != NULL) {
+ appendText("This is no time to rest!");
+ _commandWasQuick = true;
+ } else {
+ regen();
+ printPlayerCondition(_world->_player);
+ }
+
+ return true;
+}
+
+bool WageEngine::handleAcceptCommand() {
+ Chr *chr = _offer->_currentOwner;
+
+ char buf[512];
+ snprintf(buf, 512, "%s%s lays the %s on the ground and departs peacefully.",
+ chr->getDefiniteArticle(true), chr->_name.c_str(), _offer->_name.c_str());
+ appendText(buf);
+
+ _world->move(_offer, chr->_currentScene);
+ _world->move(chr, _world->_storageScene);
+
+ return true;
+}
+
+bool WageEngine::handleTakeCommand(const char *target) {
+ Common::String t(target);
+ bool handled = false;
+
+ for (ObjList::const_iterator it = _world->_player->_currentScene->_objs.begin(); it != _world->_player->_currentScene->_objs.end(); ++it) {
+ Common::String n((*it)->_name);
+ n.toLowercase();
+
+ if (t.contains(n)) {
+ if ((*it)->_type == Obj::IMMOBILE_OBJECT) {
+ appendText("You can't move it.");
+ } else {
+ takeObj(*it);
+ }
+
+ handled = true;
+ break;
+ }
+ }
+
+ return handled;
+}
+
+bool WageEngine::handleDropCommand(const char *target) {
+ Common::String t(target);
+ bool handled = false;
+
+ t.toLowercase();
+
+ for (ObjArray::const_iterator it = _world->_player->_inventory.begin(); it != _world->_player->_inventory.end(); ++it) {
+ Common::String n((*it)->_name);
+ n.toLowercase();
+
+ if (t.contains(n)) {
+ char buf[256];
+
+ snprintf(buf, 256, "You no longer have the %s.", (*it)->_name.c_str());
+ appendText(buf);
+ _world->move(*it, _world->_player->_currentScene);
+
+ handled = true;
+ break;
+ }
+ }
+
+ return handled;
+}
+
+bool WageEngine::handleAimCommand(const char *t) {
+ bool wasHandled = true;
+ Common::String target(t);
+
+ target.toLowercase();
+
+ if (target.contains("head")) {
+ _aim = Chr::HEAD;
+ } else if (target.contains("chest")) {
+ _aim = Chr::CHEST;
+ } else if (target.contains("side")) {
+ _aim = Chr::SIDE;
+ } else {
+ wasHandled = false;
+ appendText("Please aim for the head, chest, or side.");
+ }
+
+ _commandWasQuick = true;
+
+ return wasHandled;
+}
+
+bool WageEngine::handleWearCommand(const char *t) {
+ Chr *player = _world->_player;
+ char buf[512];
+ Common::String target(t);
+ bool handled = false;
+
+ target.toLowercase();
+
+ for (ObjArray::const_iterator it = _world->_player->_inventory.begin(); it != _world->_player->_inventory.end(); ++it) {
+ Common::String n((*it)->_name);
+
+ if (target.contains(n)) {
+ if ((*it)->_type == Obj::HELMET) {
+ wearObj(*it, Chr::HEAD_ARMOR);
+ } else if ((*it)->_type == Obj::CHEST_ARMOR) {
+ wearObj(*it, Chr::BODY_ARMOR);
+ } else if ((*it)->_type == Obj::SHIELD) {
+ wearObj(*it, Chr::SHIELD_ARMOR);
+ } else if ((*it)->_type == Obj::SPIRITUAL_ARMOR) {
+ wearObj(*it, Chr::MAGIC_ARMOR);
+ } else {
+ appendText("You cannot wear that object.");
+ }
+
+ handled = true;
+ break;
+ }
+ }
+
+ for (ObjList::const_iterator it = player->_currentScene->_objs.begin(); it != player->_currentScene->_objs.end(); ++it) {
+ Common::String n((*it)->_name);
+ n.toLowercase();
+ if (target.contains(n)) {
+ snprintf(buf, 512, "First you must get the %s.", (*it)->_name.c_str());
+ appendText(buf);
+
+ handled = true;
+ break;
+ }
+ }
+
+ return handled;
+}
+
+void WageEngine::wearObj(Obj *o, int pos) {
+ Chr *player = _world->_player;
+ char buf[512];
+
+ if (player->_armor[pos] == o) {
+ snprintf(buf, 512, "You are already wearing the %s.", o->_name.c_str());
+ appendText(buf);
+ } else {
+ if (player->_armor[pos] != NULL) {
+ snprintf(buf, 512, "You are no longer wearing the %s.", player->_armor[pos]->_name.c_str());
+ appendText(buf);
+ }
+
+ player->_armor[pos] = o;
+ snprintf(buf, 512, "You are now wearing the %s.", o->_name.c_str());
+ appendText(buf);
+ }
+}
+
+
+bool WageEngine::handleOfferCommand(const char *target) {
+ Chr *player = _world->_player;
+ Chr *enemy = getMonster();
+
+ if (enemy != NULL) {
+ Common::String t(target);
+ t.toLowercase();
+
+ for (ObjArray::const_iterator it = player->_inventory.begin(); it != player->_inventory.end(); ++it) {
+ Common::String n((*it)->_name);
+ n.toLowercase();
+
+ if (t.contains(n)) {
+ if ((*it)->_value < enemy->_rejectsOffers) {
+ appendText("Your offer is rejected.");
+ } else {
+ appendText("Your offer is accepted.");
+ appendText(enemy->_acceptsOfferComment.c_str());
+ _world->move(*it, enemy);
+ _world->move(enemy, _world->_storageScene);
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool WageEngine::tryAttack(const Obj *weapon, const Common::String &input) {
+ Common::String w(weapon->_name);
+ w.toLowercase();
+ Common::String i(input);
+ i.toLowercase();
+ Common::String v(weapon->_operativeVerb);
+ v.toLowercase();
+
+ return i.contains(w) && i.contains(v);
+}
+
+bool WageEngine::handleAttack(Obj *weapon) {
+ Chr *player = _world->_player;
+ Chr *enemy = getMonster();
+
+ if (weapon->_type == Obj::MAGICAL_OBJECT) {
+ switch (weapon->_attackType) {
+ case Obj::HEALS_PHYSICAL_AND_SPIRITUAL_DAMAGE:
+ case Obj::HEALS_PHYSICAL_DAMAGE:
+ case Obj::HEALS_SPIRITUAL_DAMAGE:
+ performMagic(player, enemy, weapon);
+ return true;
+ }
+ }
+ if (enemy != NULL)
+ performAttack(player, enemy, weapon);
+ else if (weapon->_type == Obj::MAGICAL_OBJECT)
+ appendText("There is nobody to cast a spell at.");
+ else
+ appendText("There is no one to fight.");
+
+ return true;
+}
+
+const char *WageEngine::getPercentMessage(double percent) {
+ if (percent < 0.40) {
+ return "very bad";
+ } else if (percent < 0.55) {
+ return "bad";
+ } else if (percent < 0.70) {
+ return "average";
+ } else if (percent < 0.85) {
+ return "good";
+ } else if (percent <= 1.00) {
+ return "very good";
+ } else {
+ return "enhanced";
+ }
+}
+
+void WageEngine::printPlayerCondition(Chr *player) {
+ double physicalPercent = (double)player->_context._statVariables[PHYS_HIT_CUR] / player->_context._statVariables[PHYS_HIT_BAS];
+ double spiritualPercent = (double)player->_context._statVariables[SPIR_HIT_CUR] / player->_context._statVariables[SPIR_HIT_BAS];
+ char buf[256];
+
+ snprintf(buf, 256, "Your physical condition is %s.", getPercentMessage(physicalPercent));
+ appendText(buf);
+
+ snprintf(buf, 256, "Your spiritual condition is %s.", getPercentMessage(spiritualPercent));
+ appendText(buf);
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/configure.engine b/engines/wage/configure.engine
new file mode 100644
index 0000000000..6205211158
--- /dev/null
+++ b/engines/wage/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine wage "WAGE" no
diff --git a/engines/wage/debugger.cpp b/engines/wage/debugger.cpp
new file mode 100644
index 0000000000..7d01b0b85e
--- /dev/null
+++ b/engines/wage/debugger.cpp
@@ -0,0 +1,97 @@
+/* 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/file.h"
+#include "wage/wage.h"
+#include "wage/debugger.h"
+#include "wage/entities.h"
+#include "wage/script.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+Debugger::Debugger(WageEngine *engine) : GUI::Debugger(), _engine(engine) {
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("scenes", WRAP_METHOD(Debugger, Cmd_ListScenes));
+ registerCmd("script", WRAP_METHOD(Debugger, Cmd_Script));
+}
+
+Debugger::~Debugger() {
+}
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+bool Debugger::Cmd_ListScenes(int argc, const char **argv) {
+ int currentScene;
+
+ for (uint i = 1; i < _engine->_world->_orderedScenes.size(); i++) { // #0 is STORAGE@
+ if (_engine->_world->_player->_currentScene == _engine->_world->_orderedScenes[i])
+ currentScene = i;
+
+ debugPrintf("%d: %s\n", i, _engine->_world->_orderedScenes[i]->_name.c_str());
+ }
+
+ debugPrintf("\nCurrent scene is #%d: %s\n", currentScene, _engine->_world->_orderedScenes[currentScene]->_name.c_str());
+
+ return true;
+}
+
+bool Debugger::Cmd_Script(int argc, const char **argv) {
+ Script *script = _engine->_world->_player->_currentScene->_script;
+
+ if (argc >= 2) {
+ int scriptNum = strToInt(argv[1]);
+
+ if (scriptNum)
+ script = _engine->_world->_orderedScenes[scriptNum]->_script;
+ else
+ script = _engine->_world->_globalScript;
+ }
+
+ if (script == NULL) {
+ debugPrintf("There is no script for current scene\n");
+ return true;
+ }
+
+ for (uint i = 0; i < script->_scriptText.size(); i++) {
+ debugPrintf("%d [%04x]: %s\n", i, script->_scriptText[i]->offset, script->_scriptText[i]->line.c_str());
+ }
+
+ return true;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/debugger.h b/engines/wage/debugger.h
new file mode 100644
index 0000000000..90687760cb
--- /dev/null
+++ b/engines/wage/debugger.h
@@ -0,0 +1,47 @@
+/* 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 WAGE_DEBUGGER_H
+#define WAGE_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace Wage {
+
+class WageEngine;
+
+class Debugger : public GUI::Debugger {
+protected:
+ WageEngine *_engine;
+
+ bool Cmd_ListScenes(int argc, const char **argv);
+ bool Cmd_Script(int argc, const char **argv);
+
+public:
+ Debugger(WageEngine *engine);
+ virtual ~Debugger();
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp
new file mode 100644
index 0000000000..907a1ec435
--- /dev/null
+++ b/engines/wage/design.cpp
@@ -0,0 +1,599 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "graphics/primitives.h"
+#include "wage/wage.h"
+#include "wage/design.h"
+
+namespace Wage {
+
+struct PlotData {
+ Graphics::Surface *surface;
+ Patterns *patterns;
+ uint fillType;
+ int thickness;
+ Design *design;
+
+ PlotData(Graphics::Surface *s, Patterns *p, int f, int t, Design *d) :
+ surface(s), patterns(p), fillType(f), thickness(t), design(d) {}
+};
+
+void drawPixel(int x, int y, int color, void *data);
+void drawPixelPlain(int x, int y, int color, void *data);
+
+Design::Design(Common::SeekableReadStream *data) {
+ _len = data->readUint16BE() - 2;
+ _data = (byte *)malloc(_len);
+ data->read(_data, _len);
+
+ _surface = NULL;
+ _bounds = NULL;
+
+ _boundsCalculationMode = false;
+}
+
+Design::~Design() {
+ free(_data);
+ if (_surface)
+ _surface->free();
+ delete _surface;
+}
+
+void Design::paint(Graphics::Surface *surface, Patterns &patterns, int x, int y) {
+ bool needRender = false;
+
+ if (_surface == NULL) {
+ _boundsCalculationMode = true;
+ _bounds->debugPrint(4, "Internal bounds:");
+ render(patterns);
+ _boundsCalculationMode = false;
+ if (_bounds->right == -10000) {
+ _bounds->left = _bounds->top = _bounds->right = _bounds->bottom = 0;
+ }
+ _bounds->debugPrint(4, "Calculated bounds:");
+
+ _surface = new Graphics::Surface;
+ _surface->create(_bounds->width(), _bounds->height(), Graphics::PixelFormat::createFormatCLUT8());
+
+ Common::Rect r(0, 0, _bounds->width(), _bounds->height());
+ _surface->fillRect(r, kColorGreen);
+
+ needRender = true;
+ }
+
+ _bounds->debugPrint(4, "Using bounds:");
+#if 0
+ PlotData pd(_surface, &patterns, 8, 1, this);
+ int x1 = 50, y1 = 50, x2 = 200, y2 = 200, borderThickness = 30;
+ Common::Rect inn(x1-5, y1-5, x2+5, y2+5);
+ drawRoundRect(inn, 6, kColorGray, false, drawPixelPlain, &pd);
+
+ drawThickLine(x1, y1, x2-borderThickness, y1, borderThickness, kColorBlack, drawPixel, &pd);
+ drawThickLine(x2-borderThickness, y1, x2-borderThickness, y2, borderThickness, kColorBlack, drawPixel, &pd);
+ drawThickLine(x2-borderThickness, y2-borderThickness, x1, y2-borderThickness, borderThickness, kColorBlack, drawPixel, &pd);
+ drawThickLine(x1, y2-borderThickness, x1, y1, borderThickness, kColorBlack, drawPixel, &pd);
+ drawThickLine(x2+10, y2+10, x2+100, y2+100, borderThickness, kColorBlack, drawPixel, &pd);
+
+ g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, _surface->w, _surface->h);
+
+ while (true) {
+ ((WageEngine *)g_engine)->processEvents();
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+ }
+ return;
+#endif
+
+ if (needRender)
+ render(patterns);
+
+ if (_bounds->width() && _bounds->height()) {
+ const int padding = 3;
+ for (int i = padding; i < _bounds->height() - 2 * padding; i++) {
+ const byte *src = (const byte *)_surface->getBasePtr(padding, i);
+ byte *dst = (byte *)surface->getBasePtr(x + padding, y+i);
+ for (int j = padding; j < _bounds->width() - 2 * padding; j++) {
+ if (*src != kColorGreen)
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+ }
+}
+
+void Design::render(Patterns &patterns) {
+ Common::MemoryReadStream in(_data, _len);
+ bool needRender = true;
+
+ while (needRender) {
+ byte fillType = in.readByte();
+ byte borderThickness = in.readByte();
+ byte borderFillType = in.readByte();
+ int type = in.readByte();
+
+ if (in.eos())
+ break;
+
+ debug(8, "fill: %d borderFill: %d border: %d type: %d", fillType, borderFillType, borderThickness, type);
+ switch (type) {
+ case 4:
+ drawRect(_surface, in, patterns, fillType, borderThickness, borderFillType);
+ break;
+ case 8:
+ drawRoundRect(_surface, in, patterns, fillType, borderThickness, borderFillType);
+ break;
+ case 12:
+ drawOval(_surface, in, patterns, fillType, borderThickness, borderFillType);
+ break;
+ case 16:
+ case 20:
+ drawPolygon(_surface, in, patterns, fillType, borderThickness, borderFillType);
+ break;
+ case 24:
+ drawBitmap(_surface, in);
+ break;
+ default:
+ warning("Unknown type => %d", type);
+ break;
+ }
+
+ //g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, _surface->w, _surface->h);
+ //((WageEngine *)g_engine)->processEvents();
+ //g_system->updateScreen();
+ //g_system->delayMillis(500);
+ }
+}
+
+bool Design::isPointOpaque(int x, int y) {
+ if (_surface == NULL)
+ error("Surface is null");
+
+ byte pixel = ((byte *)_surface->getBasePtr(x, y))[0];
+
+ return pixel != kColorGreen;
+}
+
+void Design::adjustBounds(int16 x, int16 y) {
+ _bounds->right = MAX(x, _bounds->right);
+ _bounds->bottom = MAX(y, _bounds->bottom);
+}
+
+void drawPixel(int x, int y, int color, void *data) {
+ PlotData *p = (PlotData *)data;
+
+ if (p->fillType > p->patterns->size())
+ return;
+
+ if (p->design && p->design->isBoundsCalculation()) {
+ if (x < 0 || y < 0)
+ return;
+ if (p->thickness == 1) {
+ p->design->adjustBounds(x, y);
+ } else {
+ int x1 = x - p->thickness / 2;
+ int x2 = x1 + p->thickness;
+ int y1 = y - p->thickness / 2;
+ int y2 = y1 + p->thickness;
+
+ for (y = y1; y < y2; y++)
+ for (x = x1; x < x2; x++)
+ p->design->adjustBounds(x, y);
+ }
+
+ return;
+ }
+
+ byte *pat = p->patterns->operator[](p->fillType - 1);
+
+ if (p->thickness == 1) {
+ if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) {
+ uint xu = (uint)x; // for letting compiler optimize it
+ uint yu = (uint)y;
+
+ *((byte *)p->surface->getBasePtr(xu, yu)) =
+ (pat[yu % 8] & (1 << (7 - xu % 8))) ?
+ color : kColorWhite;
+ }
+ } else {
+ int x1 = x - p->thickness / 2;
+ int x2 = x1 + p->thickness;
+ int y1 = y - p->thickness / 2;
+ int y2 = y1 + p->thickness;
+
+ for (y = y1; y < y2; y++)
+ for (x = x1; x < x2; x++)
+ if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) {
+ uint xu = (uint)x; // for letting compiler optimize it
+ uint yu = (uint)y;
+ *((byte *)p->surface->getBasePtr(xu, yu)) =
+ (pat[yu % 8] & (1 << (7 - xu % 8))) ?
+ color : kColorWhite;
+ }
+ }
+}
+
+void drawPixelPlain(int x, int y, int color, void *data) {
+ PlotData *p = (PlotData *)data;
+
+ if (p->design && p->design->isBoundsCalculation()) {
+ p->design->adjustBounds(x, y);
+ return;
+ }
+
+ if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h)
+ *((byte *)p->surface->getBasePtr(x, y)) = (byte)color;
+}
+
+void Design::drawRect(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) {
+ int16 y1 = in.readSint16BE();
+ int16 x1 = in.readSint16BE();
+ int16 y2 = in.readSint16BE();
+ int16 x2 = in.readSint16BE();
+
+ if (x1 > x2)
+ SWAP(x1, x2);
+ if (y1 > y2)
+ SWAP(y1, y2);
+
+ Common::Rect r(x1, y1, x2, y2);
+ PlotData pd(surface, &patterns, fillType, 1, this);
+
+ if (fillType <= patterns.size())
+ Graphics::drawFilledRect(r, kColorBlack, drawPixel, &pd);
+
+ pd.fillType = borderFillType;
+ pd.thickness = borderThickness;
+
+ if (borderThickness > 0 && borderFillType <= patterns.size()) {
+ Graphics::drawLine(x1, y1, x2, y1, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x2, y1, x2, y2, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x2, y2, x1, y2, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x1, y2, x1, y1, kColorBlack, drawPixel, &pd);
+ }
+}
+
+void Design::drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) {
+ int16 y1 = in.readSint16BE();
+ int16 x1 = in.readSint16BE();
+ int16 y2 = in.readSint16BE();
+ int16 x2 = in.readSint16BE();
+ int16 arc = in.readSint16BE();
+
+ if (x1 > x2)
+ SWAP(x1, x2);
+ if (y1 > y2)
+ SWAP(y1, y2);
+
+ Common::Rect r(x1, y1, x2, y2);
+ PlotData pd(surface, &patterns, fillType, 1, this);
+
+ if (fillType <= patterns.size())
+ Graphics::drawRoundRect(r, arc / 2, kColorBlack, true, drawPixel, &pd);
+
+ pd.fillType = borderFillType;
+ pd.thickness = borderThickness;
+
+ if (borderThickness > 0 && borderFillType <= patterns.size())
+ Graphics::drawRoundRect(r, arc / 2, kColorBlack, false, drawPixel, &pd);
+}
+
+void Design::drawPolygon(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) {
+
+ byte ignored = in.readSint16BE(); // ignored
+
+ if (ignored)
+ warning("Ignored: %d", ignored);
+
+ int numBytes = in.readSint16BE(); // #bytes used by polygon data, including the numBytes
+ int16 by1 = in.readSint16BE();
+ int16 bx1 = in.readSint16BE();
+ int16 by2 = in.readSint16BE();
+ int16 bx2 = in.readSint16BE();
+ Common::Rect bbox(bx1, by1, bx2, by2);
+
+ numBytes -= 8;
+
+ int y1 = in.readSint16BE();
+ int x1 = in.readSint16BE();
+
+ Common::Array<int> xcoords;
+ Common::Array<int> ycoords;
+
+ numBytes -= 6;
+
+ while (numBytes > 0) {
+ int y2 = y1;
+ int x2 = x1;
+ int b = in.readSByte();
+ if (b == -128) {
+ y2 = in.readSint16BE();
+ numBytes -= 3;
+ } else {
+ y2 += b;
+ numBytes -= 1;
+ }
+ b = in.readSByte();
+ if (b == -128) {
+ x2 = in.readSint16BE();
+ numBytes -= 3;
+ } else {
+ x2 += b;
+ numBytes -= 1;
+ }
+ xcoords.push_back(x1);
+ ycoords.push_back(y1);
+ x1 = x2;
+ y1 = y2;
+ }
+ xcoords.push_back(x1);
+ ycoords.push_back(y1);
+
+ int npoints = xcoords.size();
+ int *xpoints = (int *)calloc(npoints, sizeof(int));
+ int *ypoints = (int *)calloc(npoints, sizeof(int));
+ for (int i = 0; i < npoints; i++) {
+ xpoints[i] = xcoords[i];
+ ypoints[i] = ycoords[i];
+ }
+
+ PlotData pd(surface, &patterns, fillType, 1, this);
+
+ if (fillType <= patterns.size()) {
+ Graphics::drawPolygonScan(xpoints, ypoints, npoints, bbox, kColorBlack, drawPixel, &pd);
+ }
+
+ pd.fillType = borderFillType;
+ pd.thickness = borderThickness;
+ if (borderThickness > 0 && borderFillType <= patterns.size()) {
+ for (int i = 1; i < npoints; i++)
+ Graphics::drawLine(xpoints[i-1], ypoints[i-1], xpoints[i], ypoints[i], kColorBlack, drawPixel, &pd);
+ }
+
+ free(xpoints);
+ free(ypoints);
+}
+
+void Design::drawOval(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) {
+ int16 y1 = in.readSint16BE();
+ int16 x1 = in.readSint16BE();
+ int16 y2 = in.readSint16BE();
+ int16 x2 = in.readSint16BE();
+ PlotData pd(surface, &patterns, fillType, 1, this);
+
+ if (fillType <= patterns.size())
+ Graphics::drawEllipse(x1, y1, x2-1, y2-1, kColorBlack, true, drawPixel, &pd);
+
+ pd.fillType = borderFillType;
+ pd.thickness = borderThickness;
+
+ if (borderThickness > 0 && borderFillType <= patterns.size())
+ Graphics::drawEllipse(x1, y1, x2-1, y2-1, kColorBlack, false, drawPixel, &pd);
+}
+
+void Design::drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream &in) {
+ int numBytes = in.readSint16BE();
+ int y1 = in.readSint16BE();
+ int x1 = in.readSint16BE();
+ int y2 = in.readSint16BE();
+ int x2 = in.readSint16BE();
+ int w = x2 - x1;
+ int h = y2 - y1;
+ Graphics::Surface tmp;
+
+ tmp.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+
+ numBytes -= 10;
+
+ int x = 0, y = 0;
+ while (numBytes > 0 && y < h) {
+ int n = in.readSByte();
+ int count;
+ int b = 0;
+ int state = 0;
+
+ numBytes--;
+
+ if ((n >= 0) && (n <= 127)) { // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
+ count = n + 1;
+ state = 1;
+ } else if ((n >= -127) && (n <= -1)) { // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
+ b = in.readByte();
+ numBytes--;
+ count = -n + 1;
+ state = 2;
+ } else { // Else if n is -128, noop.
+ count = 0;
+ }
+
+ for (int i = 0; i < count && y < h; i++) {
+ byte color = 0;
+ if (state == 1) {
+ color = in.readByte();
+ numBytes--;
+ } else if (state == 2)
+ color = b;
+
+ for (int c = 0; c < 8; c++) {
+ if (_boundsCalculationMode) {
+ adjustBounds(x1 + x, y1 + y);
+ } else if (x1 + x >= 0 && x1 + x < surface->w && y1 + y >= 0 && y1 + y < surface->h)
+ *((byte *)tmp.getBasePtr(x, y)) = (color & (1 << (7 - c % 8))) ? kColorBlack : kColorWhite;
+ x++;
+ if (x == w) {
+ y++;
+ x = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ in.skip(numBytes);
+
+ if (_boundsCalculationMode)
+ return;
+
+ FloodFill ff(&tmp, kColorWhite, kColorGreen);
+ for (int yy = 0; yy < h; yy++) {
+ ff.addSeed(0, yy);
+ ff.addSeed(w - 1, yy);
+ }
+ for (int xx = 0; xx < w; xx++) {
+ ff.addSeed(xx, 0);
+ ff.addSeed(xx, h - 1);
+ }
+ ff.fill();
+
+ for (y = 0; y < h && y1 + y < surface->h; y++) {
+ byte *src = (byte *)tmp.getBasePtr(0, y);
+ byte *dst = (byte *)surface->getBasePtr(x1, y1 + y);
+ for (x = 0; x < w; x++) {
+ if (*src != kColorGreen)
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+
+ tmp.free();
+}
+
+void Design::drawRect(Graphics::Surface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType) {
+ drawRect(surface, rect.left, rect.top, rect.right, rect.bottom, thickness, color, patterns, fillType);
+}
+
+void Design::drawRect(Graphics::Surface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType) {
+ PlotData pd(surface, &patterns, fillType, thickness, nullptr);
+
+ Graphics::drawLine(x1, y1, x2, y1, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x2, y1, x2, y2, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x2, y2, x1, y2, kColorBlack, drawPixel, &pd);
+ Graphics::drawLine(x1, y2, x1, y1, kColorBlack, drawPixel, &pd);
+}
+
+
+void Design::drawFilledRect(Graphics::Surface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType) {
+ PlotData pd(surface, &patterns, fillType, 1, nullptr);
+
+ for (int y = rect.top; y <= rect.bottom; y++)
+ Graphics::drawHLine(rect.left, rect.right, y, color, drawPixel, &pd);
+}
+
+void Design::drawFilledRoundRect(Graphics::Surface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) {
+ PlotData pd(surface, &patterns, fillType, 1, nullptr);
+
+ Graphics::drawRoundRect(rect, arc, color, true, drawPixel, &pd);
+}
+
+void Design::drawHLine(Graphics::Surface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) {
+ PlotData pd(surface, &patterns, fillType, thickness, nullptr);
+
+ Graphics::drawHLine(x1, x2, y, color, drawPixel, &pd);
+}
+
+void Design::drawVLine(Graphics::Surface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) {
+ PlotData pd(surface, &patterns, fillType, thickness, nullptr);
+
+ Graphics::drawVLine(x, y1, y2, color, drawPixel, &pd);
+}
+
+FloodFill::FloodFill(Graphics::Surface *surface, byte color1, byte color2) {
+ _surface = surface;
+ _color1 = color1;
+ _color2 = color2;
+ _w = surface->w;
+ _h = surface->h;
+
+ _visited = (byte *)calloc(_w * _h, 1);
+}
+
+FloodFill::~FloodFill() {
+ while(!_queue.empty()) {
+ Common::Point *p = _queue.front();
+
+ delete p;
+ _queue.pop_front();
+ }
+
+ free(_visited);
+}
+
+void FloodFill::addSeed(int x, int y) {
+ byte *p;
+
+ if (x >= 0 && x < _w && y >= 0 && y < _h) {
+ if (!_visited[y * _w + x] && *(p = (byte *)_surface->getBasePtr(x, y)) == _color1) {
+ _visited[y * _w + x] = 1;
+ *p = _color2;
+
+ Common::Point *pt = new Common::Point(x, y);
+
+ _queue.push_back(pt);
+ }
+ }
+}
+
+void FloodFill::fill() {
+ while (!_queue.empty()) {
+ Common::Point *p = _queue.front();
+ _queue.pop_front();
+ addSeed(p->x , p->y - 1);
+ addSeed(p->x - 1, p->y );
+ addSeed(p->x , p->y + 1);
+ addSeed(p->x + 1, p->y );
+
+ delete p;
+ }
+}
+
+
+} // End of namespace Wage
diff --git a/engines/wage/design.h b/engines/wage/design.h
new file mode 100644
index 0000000000..e8f42f4e04
--- /dev/null
+++ b/engines/wage/design.h
@@ -0,0 +1,119 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_DESIGN_H
+#define WAGE_DESIGN_H
+
+#include "graphics/surface.h"
+#include "common/memstream.h"
+#include "common/rect.h"
+
+namespace Wage {
+
+class Design {
+public:
+ Design(Common::SeekableReadStream *data);
+ ~Design();
+
+ void setBounds(Common::Rect *bounds) {
+ _bounds = bounds;
+ }
+
+ Common::Rect *getBounds() {
+ return _bounds;
+ }
+
+ void paint(Graphics::Surface *canvas, Patterns &patterns, int x, int y);
+ bool isPointOpaque(int x, int y);
+ static void drawRect(Graphics::Surface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType);
+ static void drawRect(Graphics::Surface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType);
+ static void drawFilledRect(Graphics::Surface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType);
+ static void drawFilledRoundRect(Graphics::Surface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType);
+ static void drawHLine(Graphics::Surface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType);
+ static void drawVLine(Graphics::Surface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType);
+
+ bool isBoundsCalculation() { return _boundsCalculationMode; }
+ void adjustBounds(int16 x, int16 y);
+
+private:
+ byte *_data;
+ int _len;
+ Common::Rect *_bounds;
+ Graphics::Surface *_surface;
+ bool _boundsCalculationMode;
+
+private:
+ void render(Patterns &patterns);
+ void drawRect(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType);
+ void drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType);
+ void drawPolygon(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType);
+ void drawOval(Graphics::Surface *surface, Common::ReadStream &in,
+ Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType);
+ void drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream &in);
+};
+
+class FloodFill {
+public:
+ FloodFill(Graphics::Surface *surface, byte color1, byte color2);
+ ~FloodFill();
+ void addSeed(int x, int y);
+ void fill();
+
+private:
+ Common::List<Common::Point *> _queue;
+ Graphics::Surface *_surface;
+ byte _color1, _color2;
+ byte *_visited;
+ int _w, _h;
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/detection.cpp b/engines/wage/detection.cpp
new file mode 100644
index 0000000000..512d432e54
--- /dev/null
+++ b/engines/wage/detection.cpp
@@ -0,0 +1,151 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+#include "wage/wage.h"
+
+namespace Wage {
+
+const char *WageEngine::getGameFile() const {
+ return _gameDescription->filesDescriptions[0].fileName;
+}
+
+}
+
+static const PlainGameDescriptor wageGames[] = {
+ {"afm", "Another Fine Mess"},
+ {"amot", "A Mess O' Trouble"},
+ {"cantitoe", "Camp Cantitoe"},
+ {"drakmythcastle", "Drakmyth Castle"},
+ {"raysmaze", "Ray's Maze"},
+ {"scepters", "Enchanted Scepters"},
+ {"twisted", "Twisted!"},
+ {"wage", "WAGE"},
+ {0, 0}
+};
+
+#include "wage/detection_tables.h"
+
+class WageMetaEngine : public AdvancedMetaEngine {
+public:
+ WageMetaEngine() : AdvancedMetaEngine(Wage::gameDescriptions, sizeof(ADGameDescription), wageGames) {
+ _singleId = "wage";
+ _guiOptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
+ }
+
+ virtual const char *getName() const {
+ return "World Adventure Game Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "World Builder (C) Silicon Beach Software";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual void removeSaveState(const char *target, int slot) const;
+};
+
+bool WageMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave);
+}
+
+bool Wage::WageEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+bool WageMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new Wage::WageEngine(syst, desc);
+ }
+ return desc != 0;
+}
+
+SaveStateList WageMetaEngine::listSaves(const char *target) const {
+ const uint32 WAGEflag = MKTAG('W','A','G','E');
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ char saveDesc[31];
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+
+ 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);
+ if (in) {
+ uint32 type = in->readUint32BE();
+ if (type == WAGEflag)
+ in->read(saveDesc, 31);
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
+ delete in;
+ }
+ }
+ }
+
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+ return saveList;
+}
+
+int WageMetaEngine::getMaximumSaveSlot() const { return 999; }
+
+void WageMetaEngine::removeSaveState(const char *target, int slot) const {
+ g_system->getSavefileManager()->removeSavefile(Common::String::format("%s.%03d", target, slot));
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(WAGE)
+ REGISTER_PLUGIN_DYNAMIC(WAGE, PLUGIN_TYPE_ENGINE, WageMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(WAGE, PLUGIN_TYPE_ENGINE, WageMetaEngine);
+#endif
+
+namespace Wage {
+
+bool WageEngine::canLoadGameStateCurrently() {
+ return false;
+}
+
+bool WageEngine::canSaveGameStateCurrently() {
+ return false;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/detection_tables.h b/engines/wage/detection_tables.h
new file mode 100644
index 0000000000..e164ea70cd
--- /dev/null
+++ b/engines/wage/detection_tables.h
@@ -0,0 +1,121 @@
+/* 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.
+ *
+ */
+
+namespace Wage {
+
+#define ADGF_DEFAULT (ADGF_DROPLANGUAGE|ADGF_DROPPLATFORM|ADGF_MACRESFORK)
+#define ADGF_GENERIC (ADGF_DEFAULT|ADGF_USEEXTRAASTITLE|ADGF_AUTOGENTARGET)
+#define ADGF_DEMO (ADGF_GENERIC|ADGF_DEMO)
+
+#define FANGAME(n,m,s) { "wage",n,AD_ENTRY1s(n,m,s),Common::EN_ANY,Common::kPlatformMacintosh,ADGF_GENERIC,GUIO0()}
+#define FANGAMEN(n,f,m,s) { "wage",n,AD_ENTRY1s(f,m,s),Common::EN_ANY,Common::kPlatformMacintosh,ADGF_GENERIC,GUIO0()}
+#define FANGAMEND(n,f,m,s) { "wage",n,AD_ENTRY1s(f,m,s),Common::EN_ANY,Common::kPlatformMacintosh,ADGF_DEMO,GUIO0()}
+#define BIGGAME(t,v,f,m,s) { t,v,AD_ENTRY1s(f,m,s),Common::EN_ANY,Common::kPlatformMacintosh,ADGF_DEFAULT,GUIO0()}
+
+static const ADGameDescription gameDescriptions[] = {
+ FANGAME("3rd Floor", "913812a1ac7a6b0e48dadd1afa1c7763", 281409),
+ BIGGAME("afm", "v1.8", "Another Fine Mess 1.8", "94a9c4f8b3dabd1846d76215a49bd221", 1420723),
+ BIGGAME("amot", "v1.8", "A Mess O' Trouble 1.8", "26207bdf0bb539464f136f0669af885f", 1843104),
+ FANGAME("Bug Hunt", "595117cbed33e8de1ab3714b33880205", 195699),
+ BIGGAME("cantitoe", "", "Camp Cantitoe", "913812a1ac7a6b0e48dadd1afa1c7763", 616985),
+ // Problems with letter rendering
+ FANGAME("Canal District", "a56aa3cd4a6e070e15ce1d5815c7be0a", 641470),
+ FANGAME("Carbon Copy", "913812a1ac7a6b0e48dadd1afa1c7763", 519445),
+ // Invalid rect in scene "FINALE"
+ FANGAME("Castle of Ert", "327610eb2298a9427a566288312df040", 198955),
+ FANGAME("Deep Angst", "b130b3c811cd89024dd5fdd2b71f70b8", 329550),
+ FANGAME("Deep Ennui", "913812a1ac7a6b0e48dadd1afa1c7763", 86075),
+ // Polygons with ignored byte 1
+ FANGAME("Double Trouble", "1652e36857a04c01dc560234c4818619", 542371),
+ BIGGAME("drakmythcastle", "disk I", "Drakmyth Castle disk I of II", "94a9c4f8b3dabd1846d76215a49bd221", 793784),
+ BIGGAME("drakmythcastle", "disk II", "Drakmyth Castle II", "cc978cc9a5256724702463cb5aaaffa0", 1685659),
+ // Crash at start in GUI rendering
+ FANGAME("Dune Eternity", "94a9c4f8b3dabd1846d76215a49bd221", 290201), // Original file name is "***DUNE ETERNITY*** "
+ FANGAMEN("Dungeon World II", "DungeonWorld2", "0154ea11d3cbb536c13b4ae9e6902d48", 230199),
+ FANGAME("Eidisi I", "595117cbed33e8de1ab3714b33880205", 172552),
+ // Problems(?) with text on the first screen
+ FANGAMEN("Enchanted Pencils", "Enchanted Pencils 0.99 (PG)", "595117cbed33e8de1ab3714b33880205", 408913),
+ FANGAME("Escape from School!", "913812a1ac7a6b0e48dadd1afa1c7763", 50105),
+ FANGAME("Exploration Zeta!", "c477921aeee6ed0f8997ba44447eb2d0", 366599),
+ // Crash in console rendering on the first scene
+ FANGAME("Fantasy Quest", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 762754),
+ FANGAME("Find the Heart", "595117cbed33e8de1ab3714b33880205", 106235), // From Joshua's Worlds 1.0
+ // Problems with window overlay
+ FANGAMEN("Jumble", "LSJUMBLE", "e12ec4d76d48bdc86567c5e63750547e", 647339), // Original file name is "LSJUMBLE† "
+ FANGAME("Karth of the Jungle", "595117cbed33e8de1ab3714b33880205", 96711),
+ FANGAME("Karth of the Jungle", "595117cbed33e8de1ab3714b33880205", 96960), // Alternative version
+ FANGAME("Karth of the Jungle II", "c106835ab4436de054e03aec3ce904ce", 201053),
+ FANGAMEN("Little Pythagoras", "Little Pythagoras 1.1.1", "94a9c4f8b3dabd1846d76215a49bd221", 628821),
+ FANGAME("Lost Crystal", "8174c81ea1858d0079ae040dae2cefd3", 771072),
+ FANGAME("Magic Rings", "913812a1ac7a6b0e48dadd1afa1c7763", 109044),
+ // No way to click on the house
+ FANGAME("Messy House", "913812a1ac7a6b0e48dadd1afa1c7763", 177120),
+ FANGAME("Midnight Snack", "913812a1ac7a6b0e48dadd1afa1c7763", 67952),
+ FANGAME("Midnight Snack", "913812a1ac7a6b0e48dadd1afa1c7763", 67966), // Alt version
+ FANGAME("Minitorian", "913812a1ac7a6b0e48dadd1afa1c7763", 586464),
+ // No way to pass through the first screen
+ FANGAME("Nightcrawler Ned", "94a9c4f8b3dabd1846d76215a49bd221", 366542),
+ FANGAME("Pavilion", "4d991d7d1534d48d90598d86ea6d5d97", 231687),
+ // Polygons with byte 1
+ FANGAME("Periapt", "913812a1ac7a6b0e48dadd1afa1c7763", 406006),
+ FANGAME("Puzzle Piece Search", "595117cbed33e8de1ab3714b33880205", 247693), // From Joshua's Worlds 1.0
+ // Empty(?) first scene
+ FANGAME("Pyramid of No Return", "77a55a45f794b4d4a56703d3acce871e", 385145),
+ FANGAME("Queen Quest", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 57026),
+ FANGAME("Quest for T-Rex", "913812a1ac7a6b0e48dadd1afa1c7763", 592584),
+ // Crash in console rendering on the initial scene
+ FANGAME("Quest for the Dark Sword", "b35dd0c078da9f35fc25a455f56bb129", 572576),
+ FANGAME("Radical Castle", "677bfee4afeca2f7152eb8b76c85ca8d", 355601),
+ FANGAME("Radical Castle 1.0", "677bfee4afeca2f7152eb8b76c85ca8d", 347278),
+ BIGGAME("raysmaze", "v1.5", "Ray's Maze1.5", "064b16d8c20724f8debbbdc3aafde538", 1408516),
+ BIGGAME("raysmaze", "v1.5/alt", "Ray's Maze1.5", "92cca777800c3d31a77b5ed7f6ee49ad", 1408516),
+ BIGGAME("scepters", "", "Scepters", "3311deef8bf82f0b4b1cfa15a3b3289d", 346595),
+ // ??? problems with dog bitmap?
+ FANGAMEN("Space Adventure", "SpaceAdventure", "f9f3f1c419f56955f7966355b34ea5c8", 155356),
+ FANGAMEN("Spear of Destiny", "SpearOfDestiny", "913812a1ac7a6b0e48dadd1afa1c7763", 333665), // Original file name "SpearOfDestiny†"
+ FANGAME("Star Trek", "44aaef4806578700429de5aaf95c266e", 53320),
+ FANGAME("Strange Disappearance", "d81f2d03a1e863f04fb1e3a5495b720e", 772282),
+ // Code 0x03 in text
+ FANGAME("Swamp Witch", "913812a1ac7a6b0e48dadd1afa1c7763", 739781), // Original file name "Swamp Witch†"
+ FANGAME("Sweetspace Now!", "e12ec4d76d48bdc86567c5e63750547e", 123813), // Comes with Jumble
+ FANGAME("Time Bomb", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 64564),
+ FANGAME("Time Bomb", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 64578), // Alt version
+ FANGAMEND("The Ashland Revolution", "The Ashland Revolution Demo", "913812a1ac7a6b0e48dadd1afa1c7763", 145023), // Original file name "The Ashland Revolution Demo†"
+ FANGAMEN("The Hotel Caper", "The Hotel Caper V1.0", "595117cbed33e8de1ab3714b33880205", 231969),
+ // Invalid rect in scene "Access Tube 1"
+ FANGAMEN("The Phoenix v1.2", "The Phoenix", "4b0e1a1fbaaa4930accd0f9f0e1519c7", 431640),
+ FANGAME("The Sultan's Palace", "358799d446ee4fc12f793febd6c94b95", 456855),
+ // Admission for on 3rd screen is messed up
+ FANGAME("The Tower", "435f420b9dff895ae1ddf1338040c51d", 556539),
+ // Polygons with ignored byte 1 and 2 on second scene
+ FANGAME("The Village", "913812a1ac7a6b0e48dadd1afa1c7763", 314828),
+ // Doesn't go past first scene
+ BIGGAME("twisted", "", "Twisted! 1.6", "26207bdf0bb539464f136f0669af885f", 960954),
+ FANGAME("Wishing Well", "913812a1ac7a6b0e48dadd1afa1c7763", 103688),
+ FANGAME("Wizard's Warehouse", "913812a1ac7a6b0e48dadd1afa1c7763", 159748),
+ FANGAME("ZikTuria", "418e74ca71029a1e9db80d0eb30c0843", 52972),
+ FANGAME("Zoony", "539a64151426edc92da5eedadf39f23c", 154990), // original filename "Zoonyâ„¢"
+
+ AD_TABLE_END_MARKER
+};
+
+} // End of namespace Wage
diff --git a/engines/wage/dialog.cpp b/engines/wage/dialog.cpp
new file mode 100644
index 0000000000..263570bddc
--- /dev/null
+++ b/engines/wage/dialog.cpp
@@ -0,0 +1,241 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+
+#include "wage/wage.h"
+#include "wage/design.h"
+#include "wage/gui.h"
+#include "wage/dialog.h"
+
+namespace Wage {
+
+enum {
+ kDialogHeight = 113
+};
+
+Dialog::Dialog(Gui *gui, int width, const char *text, DialogButtonArray *buttons, uint defaultButton) :
+ _gui(gui), _text(text), _buttons(buttons), _defaultButton(defaultButton) {
+ assert(_gui->_engine);
+ assert(_gui->_engine->_world);
+
+ _font = getDialogFont();
+
+ _tempSurface.create(width + 1, kDialogHeight + 1, Graphics::PixelFormat::createFormatCLUT8());
+
+ _bbox.left = (_gui->_screen.w - width) / 2;
+ _bbox.top = (_gui->_screen.h - kDialogHeight) / 2;
+ _bbox.right = (_gui->_screen.w + width) / 2;
+ _bbox.bottom = (_gui->_screen.h + kDialogHeight) / 2;
+
+ _pressedButton = -1;
+
+ _mouseOverPressedButton = false;
+
+ // Adjust button positions
+ for (uint i = 0; i < _buttons->size(); i++)
+ _buttons->operator[](i)->bounds.translate(_bbox.left, _bbox.top);
+
+ _needsRedraw = true;
+}
+
+Dialog::~Dialog() {
+}
+
+const Graphics::Font *Dialog::getDialogFont() {
+ return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont);
+}
+
+void Dialog::paint() {
+ Design::drawFilledRect(&_gui->_screen, _bbox, kColorWhite, _gui->_patterns, kPatternSolid);
+ _font->drawString(&_gui->_screen, _text, _bbox.left + 24, _bbox.top + 16, _bbox.width(), kColorBlack);
+
+ static int boxOutline[] = { 1, 0, 0, 1, 1 };
+ drawOutline(_bbox, boxOutline, ARRAYSIZE(boxOutline));
+
+ for (uint i = 0; i < _buttons->size(); i++) {
+ DialogButton *button = _buttons->operator[](i);
+ static int buttonOutline[] = { 0, 0, 0, 0, 1 };
+
+ if (i == _defaultButton) {
+ buttonOutline[0] = buttonOutline[1] = 1;
+ } else {
+ buttonOutline[0] = buttonOutline[1] = 0;
+ }
+
+ int color = kColorBlack;
+
+ if ((int)i == _pressedButton && _mouseOverPressedButton) {
+ Common::Rect bb(button->bounds.left + 5, button->bounds.top + 5,
+ button->bounds.right - 5, button->bounds.bottom - 5);
+
+ Design::drawFilledRect(&_gui->_screen, bb, kColorBlack, _gui->_patterns, kPatternSolid);
+
+ color = kColorWhite;
+ }
+ int w = _font->getStringWidth(button->text);
+ int x = button->bounds.left + (button->bounds.width() - w) / 2;
+ int y = button->bounds.top + 6;
+
+ _font->drawString(&_gui->_screen, button->text, x, y, _bbox.width(), color);
+
+ drawOutline(button->bounds, buttonOutline, ARRAYSIZE(buttonOutline));
+ }
+
+ g_system->copyRectToScreen(_gui->_screen.getBasePtr(_bbox.left, _bbox.top), _gui->_screen.pitch,
+ _bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1);
+
+ _needsRedraw = false;
+}
+
+void Dialog::drawOutline(Common::Rect &bounds, int *spec, int speclen) {
+ for (int i = 0; i < speclen; i++)
+ if (spec[i] != 0)
+ Design::drawRect(&_gui->_screen, bounds.left + i, bounds.top + i, bounds.right - i, bounds.bottom - i,
+ 1, kColorBlack, _gui->_patterns, kPatternSolid);
+}
+
+int Dialog::run() {
+ bool shouldQuit = false;
+ Common::Rect r(_bbox);
+
+ _tempSurface.copyRectToSurface(_gui->_screen.getBasePtr(_bbox.left, _bbox.top), _gui->_screen.pitch, 0, 0, _bbox.width() + 1, _bbox.height() + 1);
+ _gui->pushArrowCursor();
+
+ while (!shouldQuit) {
+ Common::Event event;
+
+ while (_gui->_engine->_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ _gui->_engine->_shouldQuit = true;
+ shouldQuit = true;
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ mouseMove(event.mouse.x, event.mouse.y);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ mouseClick(event.mouse.x, event.mouse.y);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ shouldQuit = mouseRaise(event.mouse.x, event.mouse.y);
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ _pressedButton = -1;
+ shouldQuit = true;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (_needsRedraw)
+ paint();
+
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+ }
+
+ _gui->_screen.copyRectToSurface(_tempSurface.getBasePtr(0, 0), _tempSurface.pitch, _bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1);
+ g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1);
+
+ _gui->popCursor();
+
+ return _pressedButton;
+}
+
+int Dialog::matchButton(int x, int y) {
+ for (uint i = 0; i < _buttons->size(); i++)
+ if (_buttons->operator[](i)->bounds.contains(x, y))
+ return i;
+
+ return -1;
+}
+
+void Dialog::mouseMove(int x, int y) {
+ if (_pressedButton != -1) {
+ int match = matchButton(x, y);
+
+ if (_mouseOverPressedButton && match != _pressedButton) {
+ _mouseOverPressedButton = false;
+ _needsRedraw = true;
+ } else if (!_mouseOverPressedButton && match == _pressedButton) {
+ _mouseOverPressedButton = true;
+ _needsRedraw = true;
+ }
+ }
+}
+
+void Dialog::mouseClick(int x, int y) {
+ int match = matchButton(x, y);
+
+ if (match != -1) {
+ _pressedButton = match;
+ _mouseOverPressedButton = true;
+
+ _needsRedraw = true;
+ }
+}
+
+int Dialog::mouseRaise(int x, int y) {
+ bool res = false;
+
+ if (_pressedButton != -1) {
+ if (matchButton(x, y) == _pressedButton)
+ res = true;
+ }
+
+ return res;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/dialog.h b/engines/wage/dialog.h
new file mode 100644
index 0000000000..c5878acc95
--- /dev/null
+++ b/engines/wage/dialog.h
@@ -0,0 +1,101 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_DIALOG_H
+#define WAGE_DIALOG_H
+
+namespace Wage {
+
+struct DialogButton {
+ Common::String text;
+ Common::Rect bounds;
+
+ DialogButton(const char *t, int x1, int y1, int w, int h) {
+ text = t;
+ bounds.left = x1;
+ bounds.top = y1;
+ bounds.right = x1 + w - 1;
+ bounds.bottom = y1 + h - 1;
+ }
+};
+
+typedef Common::Array<DialogButton *> DialogButtonArray;
+
+class Dialog {
+public:
+ Dialog(Gui *gui, int width, const char *text, DialogButtonArray *buttons, uint defaultButton);
+ ~Dialog();
+
+ int run();
+
+private:
+ Gui *_gui;
+ Graphics::Surface _tempSurface;
+ Common::Rect _bbox;
+ Common::String _text;
+
+ const Graphics::Font *_font;
+ DialogButtonArray *_buttons;
+ int _pressedButton;
+ uint _defaultButton;
+ bool _mouseOverPressedButton;
+
+ bool _needsRedraw;
+
+private:
+ const Graphics::Font *getDialogFont();
+ void drawOutline(Common::Rect &bounds, int *spec, int speclen);
+ void paint();
+ void mouseMove(int x, int y);
+ void mouseClick(int x, int y);
+ int mouseRaise(int x, int y);
+ int matchButton(int x, int y);
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp
new file mode 100644
index 0000000000..a2648c49fe
--- /dev/null
+++ b/engines/wage/entities.cpp
@@ -0,0 +1,514 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/design.h"
+#include "wage/script.h"
+#include "wage/world.h"
+
+#include "common/memstream.h"
+
+namespace Wage {
+
+void Designed::setDesignBounds(Common::Rect *bounds) {
+ _designBounds = bounds;
+ _design->setBounds(bounds);
+}
+
+Designed::~Designed() {
+ delete _design;
+ delete _designBounds;
+}
+
+Context::Context() {
+ _visits = 0;
+ _kills = 0;
+ _experience = 0;
+ _frozen = false;
+
+ for (int i = 0; i < 26 * 9; i++)
+ _userVariables[i] = 0;
+
+ for (int i = 0; i < 18; i++)
+ _statVariables[i] = 0;
+}
+
+Scene::Scene() {
+ _script = NULL;
+ _design = NULL;
+ _textBounds = NULL;
+ _fontSize = 0;
+ _fontType = 0;
+
+ for (int i = 0; i < 4; i++)
+ _blocked[i] = false;
+
+ _soundFrequency = 0;
+ _soundType = 0;
+ _worldX = 0;
+ _worldY = 0;
+
+ _visited = false;
+}
+
+Scene::Scene(Common::String name, Common::SeekableReadStream *data) {
+ debug(9, "Creating scene: %s", name.c_str());
+
+ _name = name;
+ _classType = SCENE;
+ _design = new Design(data);
+
+ _script = NULL;
+ _textBounds = NULL;
+ _fontSize = 0;
+ _fontType = 0;
+
+ setDesignBounds(readRect(data));
+ _worldY = data->readSint16BE();
+ _worldX = data->readSint16BE();
+ _blocked[NORTH] = (data->readByte() != 0);
+ _blocked[SOUTH] = (data->readByte() != 0);
+ _blocked[EAST] = (data->readByte() != 0);
+ _blocked[WEST] = (data->readByte() != 0);
+ _soundFrequency = data->readSint16BE();
+ _soundType = data->readByte();
+ data->readByte(); // unknown
+ _messages[NORTH] = readPascalString(data);
+ _messages[SOUTH] = readPascalString(data);
+ _messages[EAST] = readPascalString(data);
+ _messages[WEST] = readPascalString(data);
+ _soundName = readPascalString(data);
+
+ _visited = false;
+
+ delete data;
+}
+
+Scene::~Scene() {
+ delete _script;
+ delete _textBounds;
+}
+
+void Scene::paint(Graphics::Surface *surface, int x, int y) {
+ Common::Rect r(x + 5, y + 5, _design->getBounds()->width() + x - 10, _design->getBounds()->height() + y - 10);
+ surface->fillRect(r, kColorWhite);
+
+ _design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y);
+
+ for (ObjList::const_iterator it = _objs.begin(); it != _objs.end(); ++it) {
+ debug(2, "paining Obj: %s", (*it)->_name.c_str());
+ (*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y);
+ }
+
+ for (ChrList::const_iterator it = _chrs.begin(); it != _chrs.end(); ++it) {
+ debug(2, "paining Chr: %s", (*it)->_name.c_str());
+ (*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y);
+ }
+}
+
+// Source: Apple IIGS Technical Note #41, "Font Family Numbers"
+// http://apple2.boldt.ca/?page=til/tn.iigs.041
+static const char *const fontNames[] = {
+ "Chicago", // system font
+ "Geneva", // application font
+ "New York",
+ "Geneva",
+
+ "Monaco",
+ "Venice",
+ "London",
+ "Athens",
+
+ "San Francisco",
+ "Toronto",
+ NULL,
+ "Cairo",
+ "Los Angeles", // 12
+
+ "Zapf Dingbats",
+ "Bookman",
+ "Helvetica Narrow",
+ "Palatino",
+ NULL,
+ "Zapf Chancery",
+ NULL,
+
+ "Times", // 20
+ "Helvetica",
+ "Courier",
+ "Symbol",
+ "Taliesin", // mobile?
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, // 30
+ NULL,
+ NULL,
+ "Avant Garde",
+ "New Century Schoolbook"
+};
+
+const char *Scene::getFontName() {
+ if (_fontType >= 0 && _fontType < ARRAYSIZE(fontNames) && fontNames[_fontType] != NULL) {
+ return fontNames[_fontType];
+ }
+ return "Unknown";
+}
+
+Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) {
+ _index = 0;
+ _namePlural = false;
+ _value = 0;
+ _attackType = 0;
+ _numberOfUses = 0;
+ _returnToRandomScene = false;
+ _type = 0;
+ _accuracy = 0;
+ _damage = 0;
+}
+
+Obj::Obj(Common::String name, Common::SeekableReadStream *data) {
+ _name = name;
+ _classType = OBJ;
+ _currentOwner = NULL;
+ _currentScene = NULL;
+
+ _index = 0;
+
+ _design = new Design(data);
+
+ setDesignBounds(readRect(data));
+
+ int16 namePlural = data->readSint16BE();
+
+ if (namePlural == 256)
+ _namePlural = true; // TODO: other flags?
+ else if (namePlural == 0)
+ _namePlural = false;
+ else
+ error("Obj <%s> had weird namePlural set (%d)", name.c_str(), namePlural);
+
+ if (data->readSint16BE() != 0)
+ error("Obj <%s> had short set", name.c_str());
+
+ if (data->readByte() != 0)
+ error("Obj <%s> had byte set", name.c_str());
+
+ _accuracy = data->readByte();
+ _value = data->readByte();
+ _type = data->readSByte();
+ _damage = data->readByte();
+ _attackType = data->readSByte();
+ _numberOfUses = data->readSint16BE();
+ int16 returnTo = data->readSint16BE();
+ if (returnTo == 256) // TODO any other possibilities?
+ _returnToRandomScene = true;
+ else if (returnTo == 0)
+ _returnToRandomScene = false;
+ else
+ error("Obj <%s> had weird returnTo set", name.c_str());
+
+ _sceneOrOwner = readPascalString(data);
+ _clickMessage = readPascalString(data);
+ _operativeVerb = readPascalString(data);
+ _failureMessage = readPascalString(data);
+ _useMessage = readPascalString(data);
+ _sound = readPascalString(data);
+
+ delete data;
+}
+
+Obj::~Obj() {
+}
+
+Chr *Obj::removeFromChr() {
+ if (_currentOwner != NULL) {
+ for (int i = (int)_currentOwner->_inventory.size() - 1; i >= 0; i--)
+ if (_currentOwner->_inventory[i] == this)
+ _currentOwner->_inventory.remove_at(i);
+
+ for (int i = 0; i < Chr::NUMBER_OF_ARMOR_TYPES; i++) {
+ if (_currentOwner->_armor[i] == this) {
+ _currentOwner->_armor[i] = NULL;
+ }
+ }
+ }
+
+ return _currentOwner;
+}
+
+Designed *Obj::removeFromCharOrScene() {
+ Designed *from = removeFromChr();
+
+ if (_currentScene != NULL) {
+ _currentScene->_objs.remove(this);
+ from = _currentScene;
+ }
+
+ return from;
+}
+
+void Obj::resetState(Chr *owner, Scene *scene) {
+ warning("STUB: Obj::resetState()");
+}
+
+Chr::Chr(Common::String name, Common::SeekableReadStream *data) {
+ _name = name;
+ _classType = CHR;
+ _design = new Design(data);
+
+ _index = 0;
+ _currentScene = NULL;
+
+ setDesignBounds(readRect(data));
+
+ _physicalStrength = data->readByte();
+ _physicalHp = data->readByte();
+ _naturalArmor = data->readByte();
+ _physicalAccuracy = data->readByte();
+
+ _spiritualStength = data->readByte();
+ _spiritialHp = data->readByte();
+ _resistanceToMagic = data->readByte();
+ _spiritualAccuracy = data->readByte();
+
+ _runningSpeed = data->readByte();
+ _rejectsOffers = data->readByte();
+ _followsOpponent = data->readByte();
+
+ data->readSByte(); // TODO: ???
+ data->readSint32BE(); // TODO: ???
+
+ _weaponDamage1 = data->readByte();
+ _weaponDamage2 = data->readByte();
+
+ data->readSByte(); // TODO: ???
+
+ if (data->readSByte() == 1)
+ _playerCharacter = true;
+ else
+ _playerCharacter = false;
+
+ _maximumCarriedObjects = data->readByte();
+ _returnTo = data->readSByte();
+
+ _winningWeapons = data->readByte();
+ _winningMagic = data->readByte();
+ _winningRun = data->readByte();
+ _winningOffer = data->readByte();
+ _losingWeapons = data->readByte();
+ _losingMagic = data->readByte();
+ _losingRun = data->readByte();
+ _losingOffer = data->readByte();
+
+ _gender = data->readSByte();
+ if (data->readSByte() == 1)
+ _nameProperNoun = true;
+ else
+ _nameProperNoun = false;
+
+ _initialScene = readPascalString(data);
+ _nativeWeapon1 = readPascalString(data);
+ _operativeVerb1 = readPascalString(data);
+ _nativeWeapon2 = readPascalString(data);
+ _operativeVerb2 = readPascalString(data);
+
+ _initialComment = readPascalString(data);
+ _scoresHitComment = readPascalString(data);
+ _receivesHitComment = readPascalString(data);
+ _makesOfferComment = readPascalString(data);
+ _rejectsOfferComment = readPascalString(data);
+ _acceptsOfferComment = readPascalString(data);
+ _dyingWords = readPascalString(data);
+
+ _initialSound = readPascalString(data);
+ _scoresHitSound = readPascalString(data);
+ _receivesHitSound = readPascalString(data);
+ _dyingSound = readPascalString(data);
+
+ _weaponSound1 = readPascalString(data);
+ _weaponSound2 = readPascalString(data);
+
+ for (int i = 0; i < NUMBER_OF_ARMOR_TYPES; i++)
+ _armor[i] = NULL;
+
+ _weapon1 = NULL;
+ _weapon2 = NULL;
+
+ // Create native weapons
+ if (!_nativeWeapon1.empty() && !_operativeVerb1.empty()) {
+ _weapon1 = new Obj;
+
+ _weapon1->_name = _nativeWeapon1;
+ _weapon1->_operativeVerb = _operativeVerb1;
+ _weapon1->_type = Obj::REGULAR_WEAPON;
+ _weapon1->_accuracy = 0;
+ _weapon1->_damage = _weaponDamage1;
+ _weapon1->_sound = _weaponSound1;
+ }
+
+ if (!_nativeWeapon2.empty() && !_operativeVerb2.empty()) {
+ _weapon2 = new Obj;
+
+ _weapon2->_name = _nativeWeapon2;
+ _weapon2->_operativeVerb = _operativeVerb2;
+ _weapon2->_type = Obj::REGULAR_WEAPON;
+ _weapon2->_accuracy = 0;
+ _weapon2->_damage = _weaponDamage2;
+ _weapon2->_sound = _weaponSound2;
+ }
+
+ delete data;
+}
+
+void Chr::resetState() {
+ _context._statVariables[PHYS_STR_BAS] = _context._statVariables[PHYS_STR_CUR] = _physicalStrength;
+ _context._statVariables[PHYS_HIT_BAS] = _context._statVariables[PHYS_HIT_CUR] = _physicalHp;
+ _context._statVariables[PHYS_ARM_BAS] = _context._statVariables[PHYS_ARM_CUR] = _naturalArmor;
+ _context._statVariables[PHYS_ACC_BAS] = _context._statVariables[PHYS_ACC_CUR] = _physicalAccuracy;
+
+ _context._statVariables[SPIR_STR_BAS] = _context._statVariables[SPIR_STR_CUR] = _spiritualStength;
+ _context._statVariables[SPIR_HIT_BAS] = _context._statVariables[SPIR_HIT_CUR] = _spiritialHp;
+ _context._statVariables[SPIR_ARM_BAS] = _context._statVariables[SPIR_ARM_CUR] = _naturalArmor;
+ _context._statVariables[SPIR_ACC_BAS] = _context._statVariables[SPIR_ACC_CUR] = _physicalAccuracy;
+
+ _context._statVariables[PHYS_SPE_BAS] = _context._statVariables[PHYS_SPE_CUR] = _runningSpeed;
+}
+
+ObjArray *Chr::getWeapons(bool includeMagic) {
+ ObjArray *list = new ObjArray;
+
+ if (_weapon1)
+ list->push_back(_weapon1);
+
+ if (_weapon2)
+ list->push_back(_weapon2);
+
+ for (uint i = 0; i < _inventory.size(); i++)
+ switch (_inventory[i]->_type) {
+ case Obj::REGULAR_WEAPON:
+ case Obj::THROW_WEAPON:
+ list->push_back(_inventory[i]);
+ break;
+ case Obj::MAGICAL_OBJECT:
+ if (includeMagic)
+ list->push_back(_inventory[i]);
+ break;
+ default:
+ break;
+ }
+
+ return list;
+}
+
+ObjArray *Chr::getMagicalObjects() {
+ ObjArray *list = new ObjArray;
+
+ for (uint i = 0; i < _inventory.size(); i++)
+ if (_inventory[i]->_type == Obj::MAGICAL_OBJECT)
+ list->push_back(_inventory[i]);
+
+ return list;
+}
+
+void Chr::wearObjs() {
+ for (uint i = 0; i < _inventory.size(); i++)
+ wearObjIfPossible(_inventory[i]);
+}
+
+int Chr::wearObjIfPossible(Obj *obj) {
+ switch (obj->_type) {
+ case Obj::HELMET:
+ if (_armor[HEAD_ARMOR] == NULL) {
+ _armor[HEAD_ARMOR] = obj;
+ return Chr::HEAD_ARMOR;
+ }
+ break;
+ case Obj::CHEST_ARMOR:
+ if (_armor[BODY_ARMOR] == NULL) {
+ _armor[BODY_ARMOR] = obj;
+ return Chr::BODY_ARMOR;
+ }
+ break;
+ case Obj::SHIELD:
+ if (_armor[SHIELD_ARMOR] == NULL) {
+ _armor[SHIELD_ARMOR] = obj;
+ return Chr::SHIELD_ARMOR;
+ }
+ break;
+ case Obj::SPIRITUAL_ARMOR:
+ if (_armor[MAGIC_ARMOR] == NULL) {
+ _armor[MAGIC_ARMOR] = obj;
+ return Chr::MAGIC_ARMOR;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return -1;
+}
+
+const char *Chr::getDefiniteArticle(bool capitalize) {
+ if (!_nameProperNoun)
+ return capitalize ? "The " : "the ";
+
+ return "";
+}
+
+bool Chr::isWearing(Obj *obj) {
+ for (int i = 0; i < NUMBER_OF_ARMOR_TYPES; i++)
+ if (_armor[i] == obj)
+ return true;
+
+ return false;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/entities.h b/engines/wage/entities.h
new file mode 100644
index 0000000000..33cf087322
--- /dev/null
+++ b/engines/wage/entities.h
@@ -0,0 +1,336 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_ENTITIES_H
+#define WAGE_ENTITIES_H
+
+namespace Graphics {
+ struct Surface;
+}
+
+namespace Wage {
+
+class Design;
+class Script;
+
+enum StatVariable {
+/** The base physical accuracy of the player. */
+ PHYS_ACC_BAS = 0,
+/** The current physical accuracy of the player. */
+ PHYS_ACC_CUR = 1,
+/** The base physical armor of the player. */
+ PHYS_ARM_BAS = 2,
+/** The current physical armor of the player. */
+ PHYS_ARM_CUR = 3,
+/** The base physical hit points of the player. */
+ PHYS_HIT_BAS = 4,
+/** The current physical hit points of the player. */
+ PHYS_HIT_CUR = 5,
+/** The base physical speed of the player. */
+ PHYS_SPE_BAS = 6,
+/** The current physical speed of the player. */
+ PHYS_SPE_CUR = 7,
+/** The base physical strength of the player. */
+ PHYS_STR_BAS = 8,
+/** The current physical strength of the player. */
+ PHYS_STR_CUR = 9,
+/** The base spiritual accuracy of the player. */
+ SPIR_ACC_BAS = 10,
+/** The current spiritual accuracy of the player. */
+ SPIR_ACC_CUR = 11,
+/** The base spiritual armor of the player. */
+ SPIR_ARM_BAS = 12,
+/** The current spiritual armor of the player. */
+ SPIR_ARM_CUR = 13,
+/** The base spiritual hit points of the player. */
+ SPIR_HIT_BAS = 14,
+/** The current spiritual hit points of the player. */
+ SPIR_HIT_CUR = 15,
+/** The base spiritual strength of the player. */
+ SPIR_STR_BAS = 16,
+/** The current spiritual strength of the player. */
+ SPIR_STR_CUR = 17
+};
+
+class Context {
+public:
+ Context();
+
+ int16 _visits; // Number of scenes visited, including repeated visits
+ int16 _kills; // Number of characters killed
+ int16 _experience;
+ bool _frozen;
+ int16 _userVariables[26 * 9];
+ int16 _statVariables[18];
+};
+
+class Designed {
+public:
+ Designed() : _design(NULL), _designBounds(NULL), _classType(UNKNOWN) {}
+ ~Designed();
+
+ Common::String _name;
+ Design *_design;
+ Common::Rect *_designBounds;
+ OperandType _classType;
+
+ Common::Rect *getDesignBounds() {
+ return _designBounds == NULL ? NULL : new Common::Rect(*_designBounds);
+ }
+
+ void setDesignBounds(Common::Rect *bounds);
+
+ Common::String toString() { if (!this) return "<NULL>"; return _name; }
+};
+
+class Chr : public Designed {
+public:
+ enum ChrDestination {
+ RETURN_TO_STORAGE = 0,
+ RETURN_TO_RANDOM_SCENE = 1,
+ RETURN_TO_INITIAL_SCENE = 2
+ };
+
+ enum ChrPart {
+ HEAD = 0,
+ CHEST = 1,
+ SIDE = 2
+ };
+
+ enum ChrArmorType {
+ HEAD_ARMOR = 0,
+ BODY_ARMOR = 1,
+ SHIELD_ARMOR = 2,
+ MAGIC_ARMOR = 3,
+ NUMBER_OF_ARMOR_TYPES = 4
+ };
+
+ Chr(Common::String name, Common::SeekableReadStream *data);
+
+ int _index;
+ Common::String _initialScene;
+ int _gender;
+ bool _nameProperNoun;
+ bool _playerCharacter;
+ uint _maximumCarriedObjects;
+ int _returnTo;
+
+ int _physicalStrength;
+ int _physicalHp;
+ int _naturalArmor;
+ int _physicalAccuracy;
+ int _spiritualStength;
+ int _spiritialHp;
+ int _resistanceToMagic;
+ int _spiritualAccuracy;
+ int _runningSpeed;
+ uint _rejectsOffers;
+ int _followsOpponent;
+
+ Common::String _initialSound;
+ Common::String _scoresHitSound;
+ Common::String _receivesHitSound;
+ Common::String _dyingSound;
+
+ Common::String _nativeWeapon1;
+ Common::String _operativeVerb1;
+ int _weaponDamage1;
+ Common::String _weaponSound1;
+
+ Common::String _nativeWeapon2;
+ Common::String _operativeVerb2;
+ int _weaponDamage2;
+ Common::String _weaponSound2;
+
+ int _winningWeapons;
+ int _winningMagic;
+ int _winningRun;
+ int _winningOffer;
+ int _losingWeapons;
+ int _losingMagic;
+ int _losingRun;
+ int _losingOffer;
+
+ Common::String _initialComment;
+ Common::String _scoresHitComment;
+ Common::String _receivesHitComment;
+ Common::String _makesOfferComment;
+ Common::String _rejectsOfferComment;
+ Common::String _acceptsOfferComment;
+ Common::String _dyingWords;
+
+ Scene *_currentScene;
+ ObjArray _inventory;
+
+ Obj *_armor[NUMBER_OF_ARMOR_TYPES];
+
+ Context _context;
+
+ ObjArray *getWeapons(bool includeMagic);
+ ObjArray *getMagicalObjects();
+ const char *getDefiniteArticle(bool capitalize);
+
+ Obj *_weapon1;
+ Obj *_weapon2;
+
+public:
+ int wearObjIfPossible(Obj *obj);
+ void wearObjs();
+
+ void resetState();
+
+ bool isWearing(Obj *obj);
+};
+
+class Obj : public Designed {
+public:
+ Obj();
+ Obj(Common::String name, Common::SeekableReadStream *data);
+ ~Obj();
+
+ enum ObjectType {
+ REGULAR_WEAPON = 1,
+ THROW_WEAPON = 2,
+ MAGICAL_OBJECT = 3,
+ HELMET = 4,
+ SHIELD = 5,
+ CHEST_ARMOR = 6,
+ SPIRITUAL_ARMOR = 7,
+ MOBILE_OBJECT = 8,
+ IMMOBILE_OBJECT = 9
+ };
+
+ enum AttackType {
+ CAUSES_PHYSICAL_DAMAGE = 0,
+ CAUSES_SPIRITUAL_DAMAGE = 1,
+ CAUSES_PHYSICAL_AND_SPIRITUAL_DAMAGE = 2,
+ HEALS_PHYSICAL_DAMAGE = 3,
+ HEALS_SPIRITUAL_DAMAGE = 4,
+ HEALS_PHYSICAL_AND_SPIRITUAL_DAMAGE = 5,
+ FREEZES_OPPONENT = 6
+ };
+
+public:
+ int _index;
+ bool _namePlural;
+ uint _value;
+ int _attackType;
+ int _numberOfUses;
+ bool _returnToRandomScene;
+ Common::String _sceneOrOwner;
+ Common::String _clickMessage;
+ Common::String _failureMessage;
+ Common::String _useMessage;
+
+ Scene *_currentScene;
+ Chr *_currentOwner;
+
+ int _type;
+ uint _accuracy;
+ Common::String _operativeVerb;
+ int _damage;
+ Common::String _sound;
+
+public:
+ void setCurrentOwner(Chr *currentOwner) {
+ _currentOwner = currentOwner;
+ if (currentOwner != NULL)
+ _currentScene = NULL;
+ }
+
+ void setCurrentScene(Scene *currentScene) {
+ _currentScene = currentScene;
+ if (currentScene != NULL)
+ _currentOwner = NULL;
+ }
+
+ Chr *removeFromChr();
+ Designed *removeFromCharOrScene();
+
+ void resetState(Chr *owner, Scene *scene);
+};
+
+class Scene : public Designed {
+public:
+ enum SceneTypes {
+ PERIODIC = 0,
+ RANDOM = 1
+ };
+
+ Script *_script;
+ Common::String _text;
+ Common::Rect *_textBounds;
+ int _fontSize;
+ int _fontType; // 3 => Geneva, 22 => Courier, param to TextFont() function
+ bool _blocked[4];
+ Common::String _messages[4];
+ int _soundFrequency; // times a minute, max 3600
+ int _soundType;
+ Common::String _soundName;
+ int _worldX;
+ int _worldY;
+ bool _visited;
+
+ ObjList _objs;
+ ChrList _chrs;
+
+ Scene();
+ Scene(Common::String name, Common::SeekableReadStream *data);
+ ~Scene();
+
+ Common::Rect *getTextBounds() {
+ return _textBounds == NULL ? NULL : new Common::Rect(*_textBounds);
+ }
+
+ void paint(Graphics::Surface *screen, int x, int y);
+
+ const char *getFontName();
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp
new file mode 100644
index 0000000000..ab5df637ec
--- /dev/null
+++ b/engines/wage/gui-console.cpp
@@ -0,0 +1,430 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/timer.h"
+#include "common/unzip.h"
+#include "graphics/cursorman.h"
+#include "graphics/fonts/bdf.h"
+#include "graphics/palette.h"
+
+#include "wage/wage.h"
+#include "wage/design.h"
+#include "wage/entities.h"
+#include "wage/menu.h"
+#include "wage/gui.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+const Graphics::Font *Gui::getConsoleFont() {
+ char fontName[128];
+ Scene *scene = _engine->_world->_player->_currentScene;
+
+ snprintf(fontName, 128, "%s-%d", scene->getFontName(), scene->_fontSize);
+
+ return getFont(fontName, Graphics::FontManager::kConsoleFont);
+}
+
+void Gui::clearOutput() {
+ _out.clear();
+ _lines.clear();
+ _consoleFullRedraw = true;
+}
+
+void Gui::appendText(const char *s) {
+ Common::String str(s);
+ _consoleDirty = true;
+
+ if (!str.contains('\n')) {
+ _out.push_back(str);
+ flowText(str);
+ return;
+ }
+
+ // Okay, we got new lines, need to split it
+ // and push substrings individually
+ Common::String tmp;
+
+ for (uint i = 0; i < str.size(); i++) {
+ if (str[i] == '\n') {
+ _out.push_back(tmp);
+ flowText(tmp);
+ tmp.clear();
+ continue;
+ }
+
+ tmp += str[i];
+ }
+
+ _out.push_back(tmp);
+ flowText(tmp);
+}
+
+enum {
+ kConWOverlap = 20,
+ kConHOverlap = 20,
+ kConWPadding = 3,
+ kConHPadding = 4,
+ kConOverscan = 3
+};
+
+void Gui::flowText(Common::String &str) {
+ Common::StringArray wrappedLines;
+ int textW = _consoleTextArea.width() - kConWPadding * 2;
+ const Graphics::Font *font = getConsoleFont();
+
+ font->wordWrapText(str, textW, wrappedLines);
+
+ if (wrappedLines.empty()) // Sometimes we have empty lines
+ _lines.push_back("");
+
+ for (Common::StringArray::const_iterator j = wrappedLines.begin(); j != wrappedLines.end(); ++j)
+ _lines.push_back(*j);
+
+ uint pos = _scrollPos;
+ _scrollPos = MAX<int>(0, (_lines.size() - 1 - _consoleNumLines) * _consoleLineHeight);
+
+ _cursorX = kConWPadding;
+
+ if (_scrollPos)
+ _cursorY = (_consoleNumLines) * _consoleLineHeight + kConHPadding;
+ else
+ _cursorY = (_lines.size() - 1) * _consoleLineHeight + kConHPadding;
+
+ if (pos != _scrollPos)
+ _consoleFullRedraw = true;
+
+ if (!_engine->_temporarilyHidden)
+ draw();
+}
+
+void Gui::renderConsole(Graphics::Surface *g, Common::Rect &r) {
+ bool fullRedraw = _consoleFullRedraw;
+ bool textReflow = false;
+ int surfW = r.width() + kConWOverlap * 2;
+ int surfH = r.height() + kConHOverlap * 2;
+
+ Common::Rect boundsR(kConWOverlap - kConOverscan, kConHOverlap - kConOverscan,
+ r.width() + kConWOverlap + kConOverscan, r.height() + kConHOverlap + kConOverscan);
+ Common::Rect fullR(0, 0, surfW, surfH);
+
+ if (_console.w != surfW || _console.h != surfH) {
+ if (_console.w != surfW)
+ textReflow = true;
+
+ _console.free();
+
+ _console.create(surfW, surfH, Graphics::PixelFormat::createFormatCLUT8());
+ fullRedraw = true;
+ }
+
+ if (fullRedraw)
+ _console.fillRect(fullR, kColorWhite);
+
+ const Graphics::Font *font = getConsoleFont();
+
+ _consoleLineHeight = font->getFontHeight();
+ int textW = r.width() - kConWPadding * 2;
+ int textH = r.height() - kConHPadding * 2;
+
+ if (textReflow) {
+ _lines.clear();
+
+ for (uint i = 0; i < _out.size(); i++)
+ flowText(_out[i]);
+ }
+
+ const int firstLine = _scrollPos / _consoleLineHeight;
+ const int lastLine = MIN((_scrollPos + textH) / _consoleLineHeight + 1, _lines.size());
+ const int xOff = kConWOverlap;
+ const int yOff = kConHOverlap;
+ int x1 = xOff + kConWPadding;
+ int y1 = yOff - (_scrollPos % _consoleLineHeight) + kConHPadding;
+
+ if (fullRedraw)
+ _consoleNumLines = (r.height() - 2 * kConWPadding) / _consoleLineHeight - 2;
+
+ for (int line = firstLine; line < lastLine; line++) {
+ const char *str = _lines[line].c_str();
+ int color = kColorBlack;
+
+ if ((line > _selectionStartY && line < _selectionEndY) ||
+ (line > _selectionEndY && line < _selectionStartY)) {
+ color = kColorWhite;
+ Common::Rect trect(0, y1, _console.w, y1 + _consoleLineHeight);
+
+ Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid);
+ }
+
+ if (line == _selectionStartY || line == _selectionEndY) {
+ if (_selectionStartY != _selectionEndY) {
+ int color1 = kColorBlack;
+ int color2 = kColorWhite;
+ int midpoint = _selectionStartX;
+
+ if (_selectionStartY > _selectionEndY)
+ SWAP(color1, color2);
+
+ if (line == _selectionEndY) {
+ SWAP(color1, color2);
+ midpoint = _selectionEndX;
+ }
+
+ Common::String beg(_lines[line].c_str(), &_lines[line].c_str()[midpoint]);
+ Common::String end(&_lines[line].c_str()[midpoint]);
+
+ int rectW = font->getStringWidth(beg) + kConWPadding + kConWOverlap;
+ Common::Rect trect(0, y1, _console.w, y1 + _consoleLineHeight);
+ if (color1 == kColorWhite)
+ trect.right = rectW;
+ else
+ trect.left = rectW;
+
+ Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid);
+
+ font->drawString(&_console, beg, x1, y1, textW, color1);
+ font->drawString(&_console, end, x1 + rectW - kConWPadding - kConWOverlap, y1, textW, color2);
+ } else {
+ int startPos = _selectionStartX;
+ int endPos = _selectionEndX;
+
+ if (startPos > endPos)
+ SWAP(startPos, endPos);
+
+ Common::String beg(_lines[line].c_str(), &_lines[line].c_str()[startPos]);
+ Common::String mid(&_lines[line].c_str()[startPos], &_lines[line].c_str()[endPos]);
+ Common::String end(&_lines[line].c_str()[endPos]);
+
+ int rectW1 = font->getStringWidth(beg) + kConWPadding + kConWOverlap;
+ int rectW2 = rectW1 + font->getStringWidth(mid);
+ Common::Rect trect(rectW1, y1, rectW2, y1 + _consoleLineHeight);
+
+ Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid);
+
+ font->drawString(&_console, beg, x1, y1, textW, kColorBlack);
+ font->drawString(&_console, mid, x1 + rectW1 - kConWPadding - kConWOverlap, y1, textW, kColorWhite);
+ font->drawString(&_console, end, x1 + rectW2 - kConWPadding - kConWOverlap, y1, textW, kColorBlack);
+ }
+ } else {
+ if (*str)
+ font->drawString(&_console, _lines[line], x1, y1, textW, color);
+ }
+
+ y1 += _consoleLineHeight;
+ }
+
+ // Now we need to clip it to the screen
+ int xcon = r.left - kConOverscan;
+ int ycon = r.top - kConOverscan;
+ if (xcon < 0) {
+ boundsR.left -= xcon;
+ xcon = 0;
+ }
+ if (ycon < 0) {
+ boundsR.top -= ycon;
+ ycon = 0;
+ }
+ if (xcon + boundsR.width() >= g->w)
+ boundsR.right -= xcon + boundsR.width() - g->w;
+ if (ycon + boundsR.height() >= g->h)
+ boundsR.bottom -= ycon + boundsR.height() - g->h;
+
+ Common::Rect rr(r);
+ if (rr.right > _screen.w - 1)
+ rr.right = _screen.w - 1;
+ if (rr.bottom > _screen.h - 1)
+ rr.bottom = _screen.h - 1;
+
+ g->copyRectToSurface(_console, xcon, ycon, boundsR);
+ g_system->copyRectToScreen(g->getBasePtr(rr.left, rr.top), g->pitch, rr.left, rr.top, rr.width(), rr.height());
+}
+
+void Gui::drawInput() {
+ if (!_screen.getPixels())
+ return;
+
+ if (_sceneIsActive) {
+ _sceneIsActive = false;
+ _bordersDirty = true;
+ }
+
+ _out.pop_back();
+ _lines.pop_back();
+ appendText(_engine->_inputText.c_str());
+ _inputTextLineNum = _out.size() - 1;
+
+ const Graphics::Font *font = getConsoleFont();
+
+ if (_engine->_inputText.contains('\n')) {
+ _consoleDirty = true;
+ } else {
+ int x = kConWPadding + _consoleTextArea.left;
+ int y = _cursorY + _consoleTextArea.top;
+
+ Common::Rect r(x, y, x + _consoleTextArea.width() - kConWPadding, y + font->getFontHeight());
+ _screen.fillRect(r, kColorWhite);
+
+ undrawCursor();
+
+ font->drawString(&_screen, _out[_inputTextLineNum], x, y, _screen.w, kColorBlack);
+
+ g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, _consoleTextArea.width(), font->getFontHeight());
+ }
+
+ _cursorX = font->getStringWidth(_out[_inputTextLineNum]) + kConHPadding;
+}
+
+void Gui::actionCopy() {
+ if (_selectionStartX == -1)
+ return;
+
+ int startX = _selectionStartX;
+ int startY = _selectionStartY;
+ int endX = _selectionEndX;
+ int endY = _selectionEndY;
+
+ if (startY > endY) {
+ SWAP(startX, endX);
+ SWAP(endX, endY);
+ }
+
+ _clipboard.clear();
+
+ for (int i = startY; i <= endY; i++) {
+ if (startY == endY) {
+ _clipboard = Common::String(&_lines[i].c_str()[startX], &_lines[i].c_str()[endX]);
+ break;
+ }
+
+ if (i == startY) {
+ _clipboard += &_lines[i].c_str()[startX];
+ _clipboard += '\n';
+ } else if (i == endY) {
+ _clipboard += Common::String(_lines[i].c_str(), &_lines[i].c_str()[endX]);
+ } else {
+ _clipboard += _lines[i];
+ _clipboard += '\n';
+ }
+ }
+
+ _menu->enableCommand(kMenuEdit, kMenuActionPaste, true);
+}
+
+void Gui::actionPaste() {
+ _undobuffer = _engine->_inputText;
+ _engine->_inputText += _clipboard;
+ drawInput();
+ _engine->_inputText = _out.back(); // Set last part of the multiline text
+
+ _menu->enableCommand(kMenuEdit, kMenuActionUndo, true);
+}
+
+void Gui::actionUndo() {
+ _engine->_inputText = _undobuffer;
+ drawInput();
+
+ _menu->enableCommand(kMenuEdit, kMenuActionUndo, false);
+}
+
+void Gui::actionClear() {
+ int startPos = _selectionStartX;
+ int endPos = _selectionEndX;
+
+ if (startPos > endPos)
+ SWAP(startPos, endPos);
+
+ Common::String beg(_lines[_selectionStartY].c_str(), &_lines[_selectionStartY].c_str()[startPos]);
+ Common::String end(&_lines[_selectionStartY].c_str()[endPos]);
+
+ _undobuffer = _engine->_inputText;
+ _engine->_inputText = beg + end;
+ drawInput();
+
+ _menu->enableCommand(kMenuEdit, kMenuActionUndo, true);
+
+ _selectionStartY = -1;
+ _selectionEndY = -1;
+}
+
+void Gui::actionCut() {
+ int startPos = _selectionStartX;
+ int endPos = _selectionEndX;
+
+ if (startPos > endPos)
+ SWAP(startPos, endPos);
+
+ Common::String beg(_lines[_selectionStartY].c_str(), &_lines[_selectionStartY].c_str()[startPos]);
+ Common::String mid(&_lines[_selectionStartY].c_str()[startPos], &_lines[_selectionStartY].c_str()[endPos]);
+ Common::String end(&_lines[_selectionStartY].c_str()[endPos]);
+
+ _undobuffer = _engine->_inputText;
+ _engine->_inputText = beg + end;
+ _clipboard = mid;
+ drawInput();
+
+ _menu->enableCommand(kMenuEdit, kMenuActionUndo, true);
+ _menu->enableCommand(kMenuEdit, kMenuActionPaste, true);
+
+ _selectionStartY = -1;
+ _selectionEndY = -1;
+}
+
+void Gui::disableUndo() {
+ _menu->enableCommand(kMenuEdit, kMenuActionUndo, false);
+}
+
+void Gui::disableAllMenus() {
+ _menu->disableAllMenus();
+}
+
+void Gui::enableNewGameMenus() {
+ _menu->enableCommand(kMenuFile, kMenuActionNew, true);
+ _menu->enableCommand(kMenuFile, kMenuActionOpen, true);
+ _menu->enableCommand(kMenuFile, kMenuActionQuit, true);
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp
new file mode 100644
index 0000000000..9dd1a24b3c
--- /dev/null
+++ b/engines/wage/gui.cpp
@@ -0,0 +1,675 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/timer.h"
+#include "common/unzip.h"
+#include "graphics/cursorman.h"
+#include "graphics/fonts/bdf.h"
+#include "graphics/palette.h"
+
+#include "wage/wage.h"
+#include "wage/design.h"
+#include "wage/entities.h"
+#include "wage/menu.h"
+#include "wage/gui.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+static const byte palette[] = {
+ 0, 0, 0, // Black
+ 0x80, 0x80, 0x80, // Gray
+ 0xff, 0xff, 0xff, // White
+ 0x00, 0xff, 0x00 // Green
+};
+
+static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid
+ { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes
+ { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, // kPatternCheckers
+ { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } // kPatternCheckers2
+};
+
+static const byte macCursorArrow[] = {
+ 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3,
+ 2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3,
+ 2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3,
+ 2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3,
+ 2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3,
+ 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3,
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3,
+ 2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3,
+ 2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3,
+ 2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3,
+ 3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3
+};
+
+static const byte macCursorBeam[] = {
+ 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3,
+ 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3,
+ 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3,
+};
+
+static void cursorTimerHandler(void *refCon) {
+ Gui *gui = (Gui *)refCon;
+
+ int x = gui->_cursorX;
+ int y = gui->_cursorY;
+
+ if (x == 0 && y == 0)
+ return;
+
+ if (!gui->_screen.getPixels())
+ return;
+
+ x += gui->_consoleTextArea.left;
+ y += gui->_consoleTextArea.top;
+
+ gui->_screen.vLine(x, y, y + kCursorHeight, gui->_cursorState ? kColorBlack : kColorWhite);
+
+ if (!gui->_cursorOff)
+ gui->_cursorState = !gui->_cursorState;
+
+ gui->_cursorRect.left = x;
+ gui->_cursorRect.right = MIN<uint16>(x + 1, gui->_screen.w);
+ gui->_cursorRect.top = y;
+ gui->_cursorRect.bottom = MIN<uint16>(y + kCursorHeight, gui->_screen.h);
+
+ gui->_cursorDirty = true;
+}
+
+Gui::Gui(WageEngine *engine) {
+ _engine = engine;
+ _scene = NULL;
+ _sceneDirty = true;
+ _consoleDirty = true;
+ _bordersDirty = true;
+ _menuDirty = true;
+ _cursorDirty = false;
+ _consoleFullRedraw = true;
+ _screen.create(g_system->getWidth(), g_system->getHeight(), Graphics::PixelFormat::createFormatCLUT8());
+
+ _scrollPos = 0;
+ _consoleLineHeight = 8; // Dummy value which makes sense
+ _consoleNumLines = 24; // Dummy value
+ _builtInFonts = false;
+ _sceneIsActive = false;
+
+ _cursorX = 0;
+ _cursorY = 0;
+ _cursorState = false;
+ _cursorOff = false;
+
+ _inTextSelection = false;
+ _selectionStartX = _selectionStartY = -1;
+ _selectionEndX = _selectionEndY = -1;
+
+ _inputTextLineNum = 0;
+
+ g_system->getPaletteManager()->setPalette(palette, 0, 4);
+
+ CursorMan.replaceCursorPalette(palette, 0, 4);
+ CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3);
+ _cursorIsArrow = true;
+ CursorMan.showMouse(true);
+
+ for (int i = 0; i < ARRAYSIZE(fillPatterns); i++)
+ _patterns.push_back(fillPatterns[i]);
+
+ loadFonts();
+
+ g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "wageCursor");
+
+ _menu = new Menu(this);
+}
+
+Gui::~Gui() {
+ _screen.free();
+ _console.free();
+ g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler);
+ delete _menu;
+}
+
+void Gui::undrawCursor() {
+ _cursorOff = true;
+ _cursorState = false;
+ cursorTimerHandler(this);
+ _cursorOff = false;
+}
+
+const Graphics::Font *Gui::getFont(const char *name, Graphics::FontManager::FontUsage fallback) {
+ const Graphics::Font *font = 0;
+
+ if (!_builtInFonts) {
+ font = FontMan.getFontByName(name);
+
+ if (!font)
+ warning("Cannot load font %s", name);
+ }
+
+ if (_builtInFonts || !font)
+ font = FontMan.getFontByUsage(fallback);
+
+ return font;
+}
+
+const Graphics::Font *Gui::getTitleFont() {
+ return getFont("Chicago-12", Graphics::FontManager::kBigGUIFont);
+}
+
+void Gui::drawDesktop() {
+ // Draw desktop
+ Common::Rect r(0, 0, _screen.w - 1, _screen.h - 1);
+ Design::drawFilledRoundRect(&_screen, r, kDesktopArc, kColorBlack, _patterns, kPatternCheckers);
+ g_system->copyRectToScreen(_screen.getPixels(), _screen.pitch, 0, 0, _screen.w, _screen.h);
+}
+
+void Gui::draw() {
+ if (_engine->_isGameOver) {
+ if (_menuDirty) {
+ drawDesktop();
+ _menu->render();
+ }
+
+ _menuDirty = false;
+
+ return;
+ }
+
+ if (_scene != _engine->_world->_player->_currentScene || _sceneDirty) {
+ _scene = _engine->_world->_player->_currentScene;
+
+ drawDesktop();
+
+ _sceneDirty = true;
+ _consoleDirty = true;
+ _menuDirty = true;
+ _consoleFullRedraw = true;
+
+ _scene->paint(&_screen, _scene->_designBounds->left, _scene->_designBounds->top);
+
+ _sceneArea.left = _scene->_designBounds->left + kBorderWidth - 2;
+ _sceneArea.top = _scene->_designBounds->top + kBorderWidth - 2;
+ _sceneArea.setWidth(_scene->_designBounds->width() - 2 * kBorderWidth);
+ _sceneArea.setHeight(_scene->_designBounds->height() - 2 * kBorderWidth);
+
+ _consoleTextArea.left = _scene->_textBounds->left + kBorderWidth - 2;
+ _consoleTextArea.top = _scene->_textBounds->top + kBorderWidth - 2;
+ _consoleTextArea.setWidth(_scene->_textBounds->width() - 2 * kBorderWidth);
+ _consoleTextArea.setHeight(_scene->_textBounds->height() - 2 * kBorderWidth);
+ }
+
+ if (_scene && (_bordersDirty || _sceneDirty))
+ paintBorder(&_screen, _sceneArea, kWindowScene);
+
+ // Render console
+ if (_consoleDirty || _consoleFullRedraw)
+ renderConsole(&_screen, _consoleTextArea);
+
+ if (_bordersDirty || _consoleDirty || _consoleFullRedraw)
+ paintBorder(&_screen, _consoleTextArea, kWindowConsole);
+
+ if (_menuDirty)
+ _menu->render();
+
+ if (_cursorDirty) {
+ g_system->copyRectToScreen(_screen.getBasePtr(_cursorRect.left, _cursorRect.top), _screen.pitch,
+ _cursorRect.left, _cursorRect.top, _cursorRect.width(), _cursorRect.height());
+
+ _cursorDirty = false;
+ }
+
+ _sceneDirty = false;
+ _consoleDirty = false;
+ _bordersDirty = false;
+ _menuDirty = false;
+ _consoleFullRedraw = false;
+}
+
+void Gui::drawBox(Graphics::Surface *g, int x, int y, int w, int h) {
+ Common::Rect r(x, y, x + w + 1, y + h + 1);
+
+ g->fillRect(r, kColorWhite);
+ g->frameRect(r, kColorBlack);
+}
+
+void Gui::fillRect(Graphics::Surface *g, int x, int y, int w, int h, int color) {
+ Common::Rect r(x, y, x + w, y + h);
+
+ g->fillRect(r, color);
+}
+
+#define ARROW_W 12
+#define ARROW_H 6
+const int arrowPixels[ARROW_H][ARROW_W] = {
+ {0,0,0,0,0,1,1,0,0,0,0,0},
+ {0,0,0,0,1,1,1,1,0,0,0,0},
+ {0,0,0,1,1,1,1,1,1,0,0,0},
+ {0,0,1,1,1,1,1,1,1,1,0,0},
+ {0,1,1,1,1,1,1,1,1,1,1,0},
+ {1,1,1,1,1,1,1,1,1,1,1,1}};
+
+void Gui::paintBorder(Graphics::Surface *g, Common::Rect &r, WindowType windowType, int highlightedPart) {
+ bool active = false, scrollable = false, closeable = false, drawTitle = false;
+ const int size = kBorderWidth;
+ int x = r.left - size;
+ int y = r.top - size;
+ int width = r.width() + 2 * size;
+ int height = r.height() + 2 * size;
+
+ switch (windowType) {
+ case kWindowScene:
+ active = _sceneIsActive;
+ scrollable = false;
+ closeable = _sceneIsActive;
+ drawTitle = true;
+ break;
+ case kWindowConsole:
+ active = !_sceneIsActive;
+ scrollable = true;
+ closeable = !_sceneIsActive;
+ drawTitle = false;
+ break;
+ }
+
+ drawBox(g, x, y, size, size);
+ drawBox(g, x + width - size - 1, y, size, size);
+ drawBox(g, x + width - size - 1, y + height - size - 1, size, size);
+ drawBox(g, x, y + height - size - 1, size, size);
+ drawBox(g, x + size, y + 2, width - 2 * size - 1, size - 4);
+ drawBox(g, x + size, y + height - size + 1, width - 2 * size - 1, size - 4);
+ drawBox(g, x + 2, y + size, size - 4, height - 2 * size - 1);
+ drawBox(g, x + width - size + 1, y + size, size - 4, height - 2 * size - 1);
+
+ if (active) {
+ fillRect(g, x + size, y + 5, width - 2 * size - 1, 8);
+ fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8);
+ fillRect(g, x + 5, y + size, 8, height - 2 * size - 1);
+ if (!scrollable) {
+ fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1);
+ } else {
+ int x1 = x + width - 15;
+ int y1 = y + size + 1;
+ int color1 = kColorBlack;
+ int color2 = kColorWhite;
+ if (highlightedPart == kBorderScrollUp) {
+ SWAP(color1, color2);
+ fillRect(g, x + width - kBorderWidth + 2, y + size, size - 4, r.height() / 2);
+ }
+ for (int yy = 0; yy < ARROW_H; yy++) {
+ for (int xx = 0; xx < ARROW_W; xx++) {
+ if (arrowPixels[yy][xx] != 0) {
+ g->hLine(x1 + xx, y1 + yy, x1 + xx, color1);
+ } else {
+ g->hLine(x1 + xx, y1 + yy, x1 + xx, color2);
+ }
+ }
+ }
+ fillRect(g, x + width - 13, y + size + ARROW_H, 8, r.height() / 2 - ARROW_H, color1);
+
+ color1 = kColorBlack;
+ color2 = kColorWhite;
+ if (highlightedPart == kBorderScrollDown) {
+ SWAP(color1, color2);
+ fillRect(g, x + width - kBorderWidth + 2, y + size + r.height() / 2, size - 4, r.height() / 2);
+ }
+ fillRect(g, x + width - 13, y + size + r.height() / 2, 8, r.height() / 2 - ARROW_H, color1);
+ y1 += height - 2 * size - ARROW_H - 2;
+ for (int yy = 0; yy < ARROW_H; yy++) {
+ for (int xx = 0; xx < ARROW_W; xx++) {
+ if (arrowPixels[ARROW_H - yy - 1][xx] != 0) {
+ g->hLine(x1 + xx, y1 + yy, x1 + xx, color1);
+ } else {
+ g->hLine(x1 + xx, y1 + yy, x1 + xx, color2);
+ }
+ }
+ }
+ }
+ if (closeable) {
+ if (highlightedPart == kBorderCloseButton) {
+ fillRect(g, x + 6, y + 6, 6, 6);
+ } else {
+ drawBox(g, x + 5, y + 5, 7, 7);
+ }
+ }
+ }
+
+ if (drawTitle) {
+ const Graphics::Font *font = getTitleFont();
+ int yOff = _builtInFonts ? 3 : 1;
+
+ int w = font->getStringWidth(_scene->_name) + 10;
+ int maxWidth = width - size * 2 - 7;
+ if (w > maxWidth)
+ w = maxWidth;
+ drawBox(g, x + (width - w) / 2, y, w, size);
+ font->drawString(g, _scene->_name, x + (width - w) / 2 + 5, y + yOff, w, kColorBlack);
+ }
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (x + width > _screen.w)
+ width = _screen.w - x;
+ if (y + height > _screen.h)
+ height = _screen.h - y;
+
+ g_system->copyRectToScreen(g->getBasePtr(x, y), g->pitch, x, y, width, height);
+}
+
+void Gui::loadFonts() {
+ Common::Archive *dat;
+
+ dat = Common::makeZipArchive("wage.dat");
+
+ if (!dat) {
+ warning("Could not find wage.dat. Falling back to built-in fonts");
+ _builtInFonts = true;
+
+ return;
+ }
+
+ Common::ArchiveMemberList list;
+ dat->listMembers(list);
+
+ for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) {
+ Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName());
+
+ Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream);
+
+ delete stream;
+
+ Common::String fontName = (*it)->getName();
+
+ // Trim the .bdf extension
+ for (int i = fontName.size() - 1; i >= 0; --i) {
+ if (fontName[i] == '.') {
+ while ((uint)i < fontName.size()) {
+ fontName.deleteLastChar();
+ }
+ break;
+ }
+ }
+
+ FontMan.assignFontToName(fontName, font);
+
+ debug(2, " %s", fontName.c_str());
+ }
+
+ _builtInFonts = false;
+
+ delete dat;
+}
+
+void Gui::regenCommandsMenu() {
+ _menu->regenCommandsMenu();
+}
+
+void Gui::regenWeaponsMenu() {
+ _menu->regenWeaponsMenu();
+}
+
+void Gui::processMenuShortCut(byte flags, uint16 ascii) {
+ _menu->processMenuShortCut(flags, ascii);
+}
+
+void Gui::mouseMove(int x, int y) {
+ if (_menu->_menuActivated) {
+ if (_menu->mouseMove(x, y))
+ _menuDirty = true;
+
+ return;
+ }
+
+ if (_inTextSelection) {
+ updateTextSelection(x, y);
+ return;
+ }
+
+ if (_consoleTextArea.contains(x, y)) {
+ if (_cursorIsArrow) {
+ CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3);
+ _cursorIsArrow = false;
+ }
+ } else if (_cursorIsArrow == false) {
+ CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3);
+ _cursorIsArrow = true;
+ }
+}
+
+void Gui::pushArrowCursor() {
+ CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3);
+}
+
+void Gui::popCursor() {
+ CursorMan.popCursor();
+}
+
+static int isInBorder(Common::Rect &rect, int x, int y) {
+ if (x >= rect.left - kBorderWidth && x < rect.left && y >= rect.top - kBorderWidth && y < rect.top)
+ return kBorderCloseButton;
+
+ if (x >= rect.right && x < rect.right + kBorderWidth) {
+ if (y < rect.top - kBorderWidth)
+ return kBorderNone;
+
+ if (y >= rect.bottom + kBorderWidth)
+ return kBorderNone;
+
+ if (y >= rect.top + rect.height() / 2)
+ return kBorderScrollDown;
+
+ return kBorderScrollUp;
+ }
+
+ return kBorderNone;
+}
+
+Designed *Gui::mouseUp(int x, int y) {
+ if (_menu->_menuActivated) {
+ if (_menu->mouseRelease(x, y)) {
+ _sceneDirty = true;
+ _consoleDirty = true;
+ _bordersDirty = true;
+ _menuDirty = true;
+ }
+
+ return NULL;
+ }
+
+ if (_inTextSelection) {
+ _inTextSelection = false;
+
+ if (_selectionEndY == -1 ||
+ (_selectionEndX == _selectionStartX && _selectionEndY == _selectionStartY)) {
+ _selectionStartY = _selectionEndY = -1;
+ _consoleFullRedraw = true;
+ _menu->enableCommand(kMenuEdit, kMenuActionCopy, false);
+ } else {
+ _menu->enableCommand(kMenuEdit, kMenuActionCopy, true);
+
+ bool cutAllowed = false;
+
+ if (_selectionStartY == _selectionEndY && _selectionStartY == (int)_lines.size() - 1)
+ cutAllowed = true;
+
+ _menu->enableCommand(kMenuEdit, kMenuActionCut, cutAllowed);
+ _menu->enableCommand(kMenuEdit, kMenuActionClear, cutAllowed);
+ }
+ }
+
+ int borderClick;
+
+ if (_sceneArea.contains(x, y)) {
+ if (!_sceneIsActive) {
+ _sceneIsActive = true;
+ _bordersDirty = true;
+ }
+
+ for (ObjList::const_iterator it = _scene->_objs.begin(); it != _scene->_objs.end(); ++it) {
+ if ((*it)->_design->isPointOpaque(x - _sceneArea.left + kBorderWidth, y - _sceneArea.top + kBorderWidth))
+ return *it;
+ }
+
+ for (ChrList::const_iterator it = _scene->_chrs.begin(); it != _scene->_chrs.end(); ++it) {
+ if ((*it)->_design->isPointOpaque(x - _sceneArea.left + kBorderWidth, y - _sceneArea.top + kBorderWidth))
+ return *it;
+ }
+ } else if (_consoleTextArea.contains(x, y)) {
+ if (_sceneIsActive) {
+ _sceneIsActive = false;
+ _bordersDirty = true;
+ }
+ } else if ((borderClick = isInBorder(_consoleTextArea, x, y)) != kBorderNone) {
+ _bordersDirty = true;
+ int _oldScrollPos = _scrollPos;
+
+ switch (borderClick) {
+ case kBorderScrollUp:
+ _scrollPos = MAX<int>(0, _scrollPos - _consoleLineHeight);
+ undrawCursor();
+ _cursorY -= (_scrollPos - _oldScrollPos);
+ _consoleDirty = true;
+ _consoleFullRedraw = true;
+ break;
+ case kBorderScrollDown:
+ _scrollPos = MIN<int>((_lines.size() - 2) * _consoleLineHeight, _scrollPos + _consoleLineHeight);
+ undrawCursor();
+ _cursorY -= (_scrollPos - _oldScrollPos);
+ _consoleDirty = true;
+ _consoleFullRedraw = true;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+void Gui::mouseDown(int x, int y) {
+ int borderClick;
+
+ if (_menu->mouseClick(x, y)) {
+ _menuDirty = true;
+ } else if (_consoleTextArea.contains(x, y)) {
+ startMarking(x, y);
+ } else if ((borderClick = isInBorder(_consoleTextArea, x, y)) != kBorderNone) {
+ paintBorder(&_screen, _consoleTextArea, kWindowConsole, borderClick);
+ }
+}
+
+int Gui::calcTextX(int x, int textLine) {
+ const Graphics::Font *font = getConsoleFont();
+
+ if ((uint)textLine >= _lines.size())
+ return 0;
+
+ Common::String str = _lines[textLine];
+
+ x -= _consoleTextArea.left;
+
+ for (int i = str.size(); i >= 0; i--) {
+ if (font->getStringWidth(str) < x) {
+ return i;
+ }
+
+ str.deleteLastChar();
+ }
+
+ return 0;
+}
+
+int Gui::calcTextY(int y) {
+ y -= _consoleTextArea.top;
+
+ if (y < 0)
+ y = 0;
+
+ const int firstLine = _scrollPos / _consoleLineHeight;
+ int textLine = (y - _scrollPos % _consoleLineHeight) / _consoleLineHeight + firstLine;
+
+ return textLine;
+}
+
+void Gui::startMarking(int x, int y) {
+ _selectionStartY = calcTextY(y);
+ _selectionStartX = calcTextX(x, _selectionStartY);
+
+ _selectionEndY = -1;
+
+ _inTextSelection = true;
+}
+
+void Gui::updateTextSelection(int x, int y) {
+ _selectionEndY = calcTextY(y);
+ _selectionEndX = calcTextX(x, _selectionEndY);
+
+ _consoleFullRedraw = true;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/gui.h b/engines/wage/gui.h
new file mode 100644
index 0000000000..73814d39b4
--- /dev/null
+++ b/engines/wage/gui.h
@@ -0,0 +1,189 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_GUI_H
+#define WAGE_GUI_H
+
+#include "common/str-array.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
+#include "graphics/surface.h"
+#include "common/rect.h"
+
+namespace Wage {
+
+class Menu;
+
+enum WindowType {
+ kWindowScene,
+ kWindowConsole
+};
+
+enum {
+ kMenuHeight = 20,
+ kMenuLeftMargin = 7,
+ kMenuSpacing = 13,
+ kMenuPadding = 16,
+ kMenuDropdownPadding = 14,
+ kMenuDropdownItemHeight = 16,
+ kMenuItemHeight = 20,
+ kBorderWidth = 17,
+ kDesktopArc = 7,
+ kComponentsPadding = 10,
+ kCursorHeight = 12
+};
+
+enum {
+ kPatternSolid = 1,
+ kPatternStripes = 2,
+ kPatternCheckers = 3,
+ kPatternCheckers2 = 4
+};
+
+enum {
+ kBorderNone = 0,
+ kBorderScrollUp,
+ kBorderScrollDown,
+ kBorderCloseButton
+};
+
+class Gui {
+public:
+ Gui(WageEngine *engine);
+ ~Gui();
+
+ void draw();
+ void appendText(const char *str);
+ void clearOutput();
+ void mouseMove(int x, int y);
+ void mouseDown(int x, int y);
+ Designed *mouseUp(int x, int y);
+ void drawInput();
+ void setSceneDirty() { _sceneDirty = true; }
+ const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback);
+ void regenCommandsMenu();
+ void regenWeaponsMenu();
+ void processMenuShortCut(byte flags, uint16 ascii);
+ void pushArrowCursor();
+ void popCursor();
+
+ void actionCopy();
+ void actionPaste();
+ void actionUndo();
+ void actionClear();
+ void actionCut();
+ void disableUndo();
+ void disableAllMenus();
+ void enableNewGameMenus();
+
+private:
+ void undrawCursor();
+ void drawDesktop();
+ void paintBorder(Graphics::Surface *g, Common::Rect &r, WindowType windowType, int highlightedPart = kBorderNone);
+ void renderConsole(Graphics::Surface *g, Common::Rect &r);
+ void drawBox(Graphics::Surface *g, int x, int y, int w, int h);
+ void fillRect(Graphics::Surface *g, int x, int y, int w, int h, int color = kColorBlack);
+ void loadFonts();
+ void flowText(Common::String &str);
+ const Graphics::Font *getConsoleFont();
+ const Graphics::Font *getTitleFont();
+ void startMarking(int x, int y);
+ int calcTextX(int x, int textLine);
+ int calcTextY(int y);
+ void updateTextSelection(int x, int y);
+
+public:
+ Graphics::Surface _screen;
+ int _cursorX, _cursorY;
+ bool _cursorState;
+ Common::Rect _consoleTextArea;
+
+ bool _builtInFonts;
+ WageEngine *_engine;
+
+ Patterns _patterns;
+
+ bool _cursorDirty;
+ Common::Rect _cursorRect;
+ bool _cursorOff;
+
+ bool _menuDirty;
+
+private:
+ Graphics::Surface _console;
+ Menu *_menu;
+ Scene *_scene;
+ bool _sceneDirty;
+ bool _consoleDirty;
+ bool _bordersDirty;
+
+ Common::StringArray _out;
+ Common::StringArray _lines;
+ uint _scrollPos;
+ int _consoleLineHeight;
+ uint _consoleNumLines;
+ bool _consoleFullRedraw;
+
+ Common::Rect _sceneArea;
+ bool _sceneIsActive;
+ bool _cursorIsArrow;
+
+ bool _inTextSelection;
+ int _selectionStartX;
+ int _selectionStartY;
+ int _selectionEndX;
+ int _selectionEndY;
+
+ Common::String _clipboard;
+ Common::String _undobuffer;
+
+ int _inputTextLineNum;
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/menu.cpp b/engines/wage/menu.cpp
new file mode 100644
index 0000000000..12ef8c2219
--- /dev/null
+++ b/engines/wage/menu.cpp
@@ -0,0 +1,571 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/system.h"
+#include "common/keyboard.h"
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/design.h"
+#include "wage/gui.h"
+#include "wage/menu.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+struct MenuSubItem {
+ Common::String text;
+ int action;
+ int style;
+ char shortcut;
+ bool enabled;
+ Common::Rect bbox;
+
+ MenuSubItem(const char *t, int a, int s = 0, char sh = 0, bool e = true) : text(t), action(a), style(s), shortcut(sh), enabled(e) {}
+};
+
+typedef Common::Array<MenuSubItem *> SubItemArray;
+
+struct MenuItem {
+ Common::String name;
+ SubItemArray subitems;
+ Common::Rect bbox;
+ Common::Rect subbbox;
+
+ MenuItem(const char *n) : name(n) {}
+};
+
+struct MenuData {
+ int menunum;
+ const char *title;
+ int action;
+ byte shortcut;
+ bool enabled;
+} static const menuSubItems[] = {
+ { kMenuFile, "New", kMenuActionNew, 0, false },
+ { kMenuFile, "Open...", kMenuActionOpen, 0, false },
+ { kMenuFile, "Close", kMenuActionClose, 0, true },
+ { kMenuFile, "Save", kMenuActionSave, 0, false },
+ { kMenuFile, "Save as...", kMenuActionSaveAs, 0, true },
+ { kMenuFile, "Revert", kMenuActionRevert, 0, false },
+ { kMenuFile, "Quit", kMenuActionQuit, 0, true },
+
+ { kMenuEdit, "Undo", kMenuActionUndo, 'Z', false },
+ { kMenuEdit, NULL, 0, 0, false },
+ { kMenuEdit, "Cut", kMenuActionCut, 'K', false },
+ { kMenuEdit, "Copy", kMenuActionCopy, 'C', false },
+ { kMenuEdit, "Paste", kMenuActionPaste, 'V', false },
+ { kMenuEdit, "Clear", kMenuActionClear, 'B', false },
+
+ { 0, NULL, 0, 0, false }
+};
+
+Menu::Menu(Gui *gui) : _gui(gui) {
+ assert(_gui->_engine);
+ assert(_gui->_engine->_world);
+
+ _font = getMenuFont();
+
+ MenuItem *about = new MenuItem(_gui->_builtInFonts ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple
+ _items.push_back(about);
+ _items[0]->subitems.push_back(new MenuSubItem(_gui->_engine->_world->getAboutMenuItemName(), kMenuActionAbout));
+
+ MenuItem *file = new MenuItem("File");
+ _items.push_back(file);
+
+ MenuItem *edit = new MenuItem("Edit");
+ _items.push_back(edit);
+
+ for (int i = 0; menuSubItems[i].menunum; i++) {
+ const MenuData *m = &menuSubItems[i];
+
+ _items[m->menunum]->subitems.push_back(new MenuSubItem(m->title, m->action, 0, m->shortcut, m->enabled));
+ }
+
+ _commands = new MenuItem(_gui->_engine->_world->_commandsMenuName.c_str());
+ _items.push_back(_commands);
+ regenCommandsMenu();
+
+ _weapons = NULL;
+
+ if (!_gui->_engine->_world->_weaponMenuDisabled) {
+ _weapons = new MenuItem(_gui->_engine->_world->_weaponsMenuName.c_str());
+ _items.push_back(_weapons);
+
+ regenWeaponsMenu();
+ }
+
+ // Calculate menu dimensions
+ int y = 1;
+ int x = 18;
+
+ for (uint i = 0; i < _items.size(); i++) {
+ int w = _font->getStringWidth(_items[i]->name);
+
+ if (_items[i]->bbox.bottom == 0) {
+ _items[i]->bbox.left = x - kMenuLeftMargin;
+ _items[i]->bbox.top = y;
+ _items[i]->bbox.right = x + w + kMenuSpacing - kMenuLeftMargin;
+ _items[i]->bbox.bottom = y + _font->getFontHeight() + (_gui->_builtInFonts ? 3 : 2);
+ }
+
+ calcMenuBounds(_items[i]);
+
+ x += w + kMenuSpacing;
+ }
+
+ _bbox.left = 0;
+ _bbox.top = 0;
+ _bbox.right = _gui->_screen.w - 1;
+ _bbox.bottom = kMenuHeight - 1;
+
+ _menuActivated = false;
+ _activeItem = -1;
+ _activeSubItem = -1;
+
+ _screenCopy.create(_gui->_screen.w, _gui->_screen.h, Graphics::PixelFormat::createFormatCLUT8());
+ _tempSurface.create(_gui->_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8());
+}
+
+Menu::~Menu() {
+ for (uint i = 0; i < _items.size(); i++) {
+ for (uint j = 0; j < _items[i]->subitems.size(); j++)
+ delete _items[i]->subitems[j];
+ delete _items[i];
+ }
+}
+
+void Menu::regenCommandsMenu() {
+ for (uint j = 0; j < _commands->subitems.size(); j++)
+ delete _commands->subitems[j];
+
+ _commands->subitems.clear();
+
+ createCommandsMenu(_commands);
+ calcMenuBounds(_commands);
+}
+
+void Menu::createCommandsMenu(MenuItem *menu) {
+ Common::String string(_gui->_engine->_world->_commandsMenu);
+
+ Common::String item;
+
+ for (uint i = 0; i < string.size(); i++) {
+ while(i < string.size() && string[i] != ';') // Read token
+ item += string[i++];
+
+ if (item == "(-") {
+ menu->subitems.push_back(new MenuSubItem(NULL, 0));
+ } else {
+ bool enabled = true;
+ int style = 0;
+ char shortcut = 0;
+ const char *shortPtr = strrchr(item.c_str(), '/');
+ if (shortPtr != NULL) {
+ if (strlen(shortPtr) >= 2) {
+ shortcut = shortPtr[1];
+ item.deleteChar(shortPtr - item.c_str());
+ item.deleteChar(shortPtr - item.c_str());
+ } else {
+ error("Unexpected shortcut: '%s', item '%s' in menu '%s'", shortPtr, item.c_str(), string.c_str());
+ }
+ }
+
+ while (item.size() >= 2 && item[item.size() - 2] == '<') {
+ char c = item.lastChar();
+ if (c == 'B') {
+ style |= kFontStyleBold;
+ } else if (c == 'I') {
+ style |= kFontStyleItalic;
+ } else if (c == 'U') {
+ style |= kFontStyleUnderline;
+ } else if (c == 'O') {
+ style |= kFontStyleOutline;
+ } else if (c == 'S') {
+ style |= kFontStyleShadow;
+ } else if (c == 'C') {
+ style |= kFontStyleCondensed;
+ } else if (c == 'E') {
+ style |= kFontStyleExtended;
+ }
+ item.deleteLastChar();
+ item.deleteLastChar();
+ }
+
+ Common::String tmpitem(item);
+ tmpitem.trim();
+ if (tmpitem[0] == '(') {
+ enabled = false;
+
+ for (uint j = 0; j < item.size(); j++)
+ if (item[j] == '(') {
+ item.deleteChar(j);
+ break;
+ }
+ }
+
+ menu->subitems.push_back(new MenuSubItem(item.c_str(), kMenuActionCommand, style, shortcut, enabled));
+ }
+
+ item.clear();
+ }
+}
+
+void Menu::regenWeaponsMenu() {
+ if (_gui->_engine->_world->_weaponMenuDisabled)
+ return;
+
+ for (uint j = 0; j < _weapons->subitems.size(); j++)
+ delete _weapons->subitems[j];
+
+ _weapons->subitems.clear();
+
+ createWeaponsMenu(_weapons);
+ calcMenuBounds(_weapons);
+}
+
+void Menu::createWeaponsMenu(MenuItem *menu) {
+ Chr *player = _gui->_engine->_world->_player;
+ ObjArray *weapons = player->getWeapons(true);
+
+ for (uint i = 0; i < weapons->size(); i++) {
+ Obj *obj = (*weapons)[i];
+ if (obj->_type == Obj::REGULAR_WEAPON ||
+ obj->_type == Obj::THROW_WEAPON ||
+ obj->_type == Obj::MAGICAL_OBJECT) {
+ Common::String command(obj->_operativeVerb);
+ command += " ";
+ command += obj->_name;
+
+ menu->subitems.push_back(new MenuSubItem(command.c_str(), kMenuActionCommand, 0, 0, true));
+ }
+ }
+ delete weapons;
+
+ if (menu->subitems.empty())
+ menu->subitems.push_back(new MenuSubItem("You have no weapons", 0, 0, 0, false));
+}
+
+const Graphics::Font *Menu::getMenuFont() {
+ return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont);
+}
+
+const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) {
+ static char res[20];
+ *res = 0;
+
+ if (item->shortcut != 0)
+ sprintf(res, "%s%c%c", prefix, (_gui->_builtInFonts ? '^' : '\x11'), item->shortcut);
+
+ return res;
+}
+
+int Menu::calculateMenuWidth(MenuItem *menu) {
+ int maxWidth = 0;
+ for (uint i = 0; i < menu->subitems.size(); i++) {
+ MenuSubItem *item = menu->subitems[i];
+ if (!item->text.empty()) {
+ Common::String text(item->text);
+ Common::String acceleratorText(getAcceleratorString(item, " "));
+ if (!acceleratorText.empty()) {
+ text += acceleratorText;
+ }
+
+ int width = _font->getStringWidth(text);
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ }
+ return maxWidth;
+}
+
+void Menu::calcMenuBounds(MenuItem *menu) {
+ // TODO: cache maxWidth
+ int maxWidth = calculateMenuWidth(menu);
+ int x1 = menu->bbox.left - 1;
+ int y1 = menu->bbox.bottom + 1;
+ int x2 = x1 + maxWidth + kMenuDropdownPadding * 2 - 4;
+ int y2 = y1 + menu->subitems.size() * kMenuDropdownItemHeight + 2;
+
+ menu->subbbox.left = x1;
+ menu->subbbox.top = y1;
+ menu->subbbox.right = x2;
+ menu->subbbox.bottom = y2;
+}
+
+void Menu::render() {
+ Common::Rect r(_bbox);
+
+ Design::drawFilledRoundRect(&_gui->_screen, r, kDesktopArc, kColorWhite, _gui->_patterns, kPatternSolid);
+ r.top = 7;
+ Design::drawFilledRect(&_gui->_screen, r, kColorWhite, _gui->_patterns, kPatternSolid);
+ r.top = kMenuHeight - 1;
+ Design::drawFilledRect(&_gui->_screen, r, kColorBlack, _gui->_patterns, kPatternSolid);
+
+ for (uint i = 0; i < _items.size(); i++) {
+ int color = kColorBlack;
+ MenuItem *it = _items[i];
+
+ if ((uint)_activeItem == i) {
+ Common::Rect hbox = it->bbox;
+
+ hbox.left -= 1;
+ hbox.right += 2;
+
+ Design::drawFilledRect(&_gui->_screen, hbox, kColorBlack, _gui->_patterns, kPatternSolid);
+ color = kColorWhite;
+
+ if (!it->subitems.empty())
+ renderSubmenu(it);
+ }
+
+ _font->drawString(&_gui->_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_gui->_builtInFonts ? 2 : 1), it->bbox.width(), color);
+ }
+
+ g_system->copyRectToScreen(_gui->_screen.getPixels(), _gui->_screen.pitch, 0, 0, _gui->_screen.w, kMenuHeight);
+}
+
+void Menu::renderSubmenu(MenuItem *menu) {
+ Common::Rect *r = &menu->subbbox;
+
+ if (r->width() == 0 || r->height() == 0)
+ return;
+
+ Design::drawFilledRect(&_gui->_screen, *r, kColorWhite, _gui->_patterns, kPatternSolid);
+ Design::drawRect(&_gui->_screen, *r, 1, kColorBlack, _gui->_patterns, kPatternSolid);
+ Design::drawVLine(&_gui->_screen, r->right + 1, r->top + 3, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid);
+ Design::drawHLine(&_gui->_screen, r->left + 3, r->right + 1, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid);
+
+ int x = r->left + kMenuDropdownPadding;
+ int y = r->top + 1;
+ for (uint i = 0; i < menu->subitems.size(); i++) {
+ Common::String text(menu->subitems[i]->text);
+ Common::String acceleratorText(getAcceleratorString(menu->subitems[i], ""));
+ int accelX = r->right - 25;
+
+ int color = kColorBlack;
+ if (i == (uint)_activeSubItem && !text.empty() && menu->subitems[i]->enabled) {
+ color = kColorWhite;
+ Common::Rect trect(r->left, y - (_gui->_builtInFonts ? 1 : 0), r->right, y + _font->getFontHeight());
+
+ Design::drawFilledRect(&_gui->_screen, trect, kColorBlack, _gui->_patterns, kPatternSolid);
+ }
+
+ if (!text.empty()) {
+ Graphics::Surface *s = &_gui->_screen;
+ int tx = x, ty = y;
+
+ if (!menu->subitems[i]->enabled) {
+ s = &_tempSurface;
+ tx = 0;
+ ty = 0;
+ accelX -= x;
+
+ _tempSurface.fillRect(Common::Rect(0, 0, _tempSurface.w, _tempSurface.h), kColorGreen);
+ }
+
+ _font->drawString(s, text, tx, ty, r->width(), color);
+
+ if (!acceleratorText.empty())
+ _font->drawString(s, acceleratorText, accelX, ty, r->width(), color);
+
+ if (!menu->subitems[i]->enabled) {
+ // I am lazy to extend drawString() with plotProc as a parameter, so
+ // fake it here
+ for (int ii = 0; ii < _tempSurface.h; ii++) {
+ const byte *src = (const byte *)_tempSurface.getBasePtr(0, ii);
+ byte *dst = (byte *)_gui->_screen.getBasePtr(x, y+ii);
+ byte pat = _gui->_patterns[kPatternCheckers2 - 1][ii % 8];
+ for (int j = 0; j < r->width(); j++) {
+ if (*src != kColorGreen && (pat & (1 << (7 - (x + j) % 8))))
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+ }
+ } else { // Delimiter
+ Design::drawHLine(&_gui->_screen, r->left + 1, r->right - 1, y + kMenuDropdownItemHeight / 2, 1, kColorBlack, _gui->_patterns, kPatternStripes);
+ }
+
+ y += kMenuDropdownItemHeight;
+ }
+
+ g_system->copyRectToScreen(_gui->_screen.getBasePtr(r->left, r->top), _gui->_screen.pitch, r->left, r->top, r->width() + 3, r->height() + 3);
+}
+
+bool Menu::mouseClick(int x, int y) {
+ if (_bbox.contains(x, y)) {
+ if (!_menuActivated)
+ _screenCopy.copyFrom(_gui->_screen);
+
+ for (uint i = 0; i < _items.size(); i++)
+ if (_items[i]->bbox.contains(x, y)) {
+ if ((uint)_activeItem == i)
+ return false;
+
+ if (_activeItem != -1) { // Restore background
+ Common::Rect r(_items[_activeItem]->subbbox);
+ r.right += 3;
+ r.bottom += 3;
+
+ _gui->_screen.copyRectToSurface(_screenCopy, r.left, r.top, r);
+ g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1);
+ }
+
+ _activeItem = i;
+ _activeSubItem = -1;
+ _menuActivated = true;
+
+ return true;
+ }
+ } else if (_menuActivated && _items[_activeItem]->subbbox.contains(x, y)) {
+ MenuItem *it = _items[_activeItem];
+ int numSubItem = (y - it->subbbox.top) / kMenuDropdownItemHeight;
+
+ if (numSubItem != _activeSubItem) {
+ _activeSubItem = numSubItem;
+
+ renderSubmenu(_items[_activeItem]);
+ }
+ } else if (_menuActivated && _activeItem != -1) {
+ _activeSubItem = -1;
+
+ renderSubmenu(_items[_activeItem]);
+ }
+
+ return false;
+}
+
+bool Menu::mouseMove(int x, int y) {
+ if (_menuActivated)
+ if (mouseClick(x, y))
+ return true;
+
+ return false;
+}
+
+bool Menu::mouseRelease(int x, int y) {
+ if (_menuActivated) {
+ _menuActivated = false;
+
+ if (_activeItem != -1 && _activeSubItem != -1 && _items[_activeItem]->subitems[_activeSubItem]->enabled)
+ executeCommand(_items[_activeItem]->subitems[_activeSubItem]);
+
+ _activeItem = -1;
+ _activeSubItem = -1;
+
+ return true;
+ }
+
+ return false;
+}
+
+void Menu::executeCommand(MenuSubItem *subitem) {
+ switch(subitem->action) {
+ case kMenuActionAbout:
+ case kMenuActionNew:
+ case kMenuActionOpen:
+ case kMenuActionClose:
+ case kMenuActionSave:
+ case kMenuActionSaveAs:
+ case kMenuActionRevert:
+ case kMenuActionQuit:
+
+ case kMenuActionUndo:
+ _gui->actionUndo();
+ break;
+ case kMenuActionCut:
+ _gui->actionCut();
+ break;
+ case kMenuActionCopy:
+ _gui->actionCopy();
+ break;
+ case kMenuActionPaste:
+ _gui->actionPaste();
+ break;
+ case kMenuActionClear:
+ _gui->actionClear();
+ break;
+
+ case kMenuActionCommand:
+ _gui->_engine->processTurn(&subitem->text, NULL);
+ break;
+
+ default:
+ warning("Unknown action: %d", subitem->action);
+
+ }
+}
+
+void Menu::processMenuShortCut(byte flags, uint16 ascii) {
+ ascii = tolower(ascii);
+
+ if (flags & (Common::KBD_CTRL | Common::KBD_META)) {
+ for (uint i = 0; i < _items.size(); i++)
+ for (uint j = 0; j < _items[i]->subitems.size(); j++)
+ if (_items[i]->subitems[j]->enabled && tolower(_items[i]->subitems[j]->shortcut) == ascii) {
+ executeCommand(_items[i]->subitems[j]);
+ break;
+ }
+ }
+}
+
+void Menu::enableCommand(int menunum, int action, bool state) {
+ for (uint i = 0; i < _items[menunum]->subitems.size(); i++)
+ if (_items[menunum]->subitems[i]->action == action)
+ _items[menunum]->subitems[i]->enabled = state;
+}
+
+void Menu::disableAllMenus() {
+ for (uint i = 1; i < _items.size(); i++) // Leave About menu on
+ for (uint j = 0; j < _items[i]->subitems.size(); j++)
+ _items[i]->subitems[j]->enabled = false;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/menu.h b/engines/wage/menu.h
new file mode 100644
index 0000000000..3550356bc6
--- /dev/null
+++ b/engines/wage/menu.h
@@ -0,0 +1,139 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_MENU_H
+#define WAGE_MENU_H
+
+namespace Wage {
+
+struct MenuItem;
+struct MenuSubItem;
+
+enum {
+ kFontStyleBold = 1,
+ kFontStyleItalic = 2,
+ kFontStyleUnderline = 4,
+ kFontStyleOutline = 8,
+ kFontStyleShadow = 16,
+ kFontStyleCondensed = 32,
+ kFontStyleExtended = 64
+};
+
+enum {
+ kMenuAbout = 0,
+ kMenuFile = 1,
+ kMenuEdit = 2,
+ kMenuCommands = 3,
+ kMenuWeapons = 4
+};
+
+enum {
+ kMenuActionAbout,
+ kMenuActionNew,
+ kMenuActionOpen,
+ kMenuActionClose,
+ kMenuActionSave,
+ kMenuActionSaveAs,
+ kMenuActionRevert,
+ kMenuActionQuit,
+
+ kMenuActionUndo,
+ kMenuActionCut,
+ kMenuActionCopy,
+ kMenuActionPaste,
+ kMenuActionClear,
+
+ kMenuActionCommand
+};
+
+class Menu {
+public:
+ Menu(Gui *gui);
+ ~Menu();
+
+ void render();
+ bool mouseClick(int x, int y);
+ bool mouseRelease(int x, int y);
+ bool mouseMove(int x, int y);
+
+ void regenCommandsMenu();
+ void regenWeaponsMenu();
+ void processMenuShortCut(byte flags, uint16 ascii);
+ void enableCommand(int menunum, int action, bool state);
+ void disableAllMenus();
+
+ bool _menuActivated;
+ Common::Rect _bbox;
+
+private:
+ Gui *_gui;
+ Graphics::Surface _screenCopy;
+ Graphics::Surface _tempSurface;
+
+private:
+ const Graphics::Font *getMenuFont();
+ const char *getAcceleratorString(MenuSubItem *item, const char *prefix);
+ int calculateMenuWidth(MenuItem *menu);
+ void calcMenuBounds(MenuItem *menu);
+ void renderSubmenu(MenuItem *menu);
+ void createCommandsMenu(MenuItem *menu);
+ void createWeaponsMenu(MenuItem *menu);
+ void executeCommand(MenuSubItem *subitem);
+
+ Common::Array<MenuItem *> _items;
+ MenuItem *_weapons;
+ MenuItem *_commands;
+
+ const Graphics::Font *_font;
+
+ int _activeItem;
+ int _activeSubItem;
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/module.mk b/engines/wage/module.mk
new file mode 100644
index 0000000000..21316bbf83
--- /dev/null
+++ b/engines/wage/module.mk
@@ -0,0 +1,29 @@
+MODULE := engines/wage
+
+MODULE_OBJS := \
+ combat.o \
+ debugger.o \
+ design.o \
+ detection.o \
+ dialog.o \
+ entities.o \
+ gui.o \
+ gui-console.o \
+ menu.o \
+ randomhat.o \
+ script.o \
+ sound.o \
+ util.o \
+ wage.o \
+ world.o
+
+MODULE_DIRS += \
+ engines/wage
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_WAGE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/wage/randomhat.cpp b/engines/wage/randomhat.cpp
new file mode 100644
index 0000000000..9371140398
--- /dev/null
+++ b/engines/wage/randomhat.cpp
@@ -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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/random.h"
+
+#include "common/hashmap.h"
+#include "wage/randomhat.h"
+
+namespace Wage {
+
+void RandomHat::addTokens(int type, int count) {
+ _tokens.setVal(type, _tokens.getVal(type, 0) + count);
+}
+
+int RandomHat::countTokens() {
+ int count = 0;
+ for (Common::HashMap<int, int>::const_iterator it = _tokens.begin(); it != _tokens.end(); ++it)
+ count += it->_value;
+
+ return count;
+}
+
+int RandomHat::drawToken() {
+ int total = countTokens();
+ if (total > 0) {
+ int random = _rnd->getRandomNumber(total - 1);
+ int count = 0;
+ for (Common::HashMap<int, int>::iterator it = _tokens.begin(); it != _tokens.end(); ++it) {
+ if (random >= count && random < count + it->_value) {
+ it->_value--;
+ return it->_key;
+ }
+ count += it->_value;
+ }
+ }
+ return kTokNone;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/randomhat.h b/engines/wage/randomhat.h
new file mode 100644
index 0000000000..254cd2ae8d
--- /dev/null
+++ b/engines/wage/randomhat.h
@@ -0,0 +1,77 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_RANDOMHAT_H
+#define WAGE_RANDOMHAT_H
+
+namespace Wage {
+
+enum {
+ kTokWeapons = -400,
+ kTokMagic = -300,
+ kTokRun = -200,
+ kTokOffer = -100,
+ kTokNone = -100000
+};
+
+class RandomHat {
+public:
+ RandomHat(Common::RandomSource *rnd) : _rnd(rnd) {}
+
+ void addTokens(int type, int count);
+ int drawToken();
+
+private:
+ Common::RandomSource *_rnd;
+ Common::HashMap<int, int> _tokens;
+
+ int countTokens();
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/script.cpp b/engines/wage/script.cpp
new file mode 100644
index 0000000000..294c08ed82
--- /dev/null
+++ b/engines/wage/script.cpp
@@ -0,0 +1,1175 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/script.h"
+#include "wage/world.h"
+
+#include "common/stream.h"
+
+namespace Wage {
+
+Common::String Script::Operand::toString() {
+ switch(_type) {
+ case NUMBER:
+ return Common::String::format("%d", _value.number);
+ case STRING:
+ case TEXT_INPUT:
+ return *_value.string;
+ case OBJ:
+ return _value.obj->toString();
+ case CHR:
+ return _value.chr->toString();
+ case SCENE:
+ return _value.scene->toString();
+ case CLICK_INPUT:
+ return _value.inputClick->toString();
+ default:
+ error("Unhandled operand type: _type");
+ }
+}
+
+Script::Script(Common::SeekableReadStream *data) : _data(data) {
+ _engine = NULL;
+ _world = NULL;
+
+ _loopCount = 0;
+ _inputText = NULL;
+ _inputClick = NULL;
+
+ _handled = false;
+
+ convertToText();
+}
+
+Script::~Script() {
+ for (uint i = 0; i < _scriptText.size(); i++) {
+ delete _scriptText[i];
+ }
+
+ delete _data;
+}
+
+void Script::print() {
+ for (uint i = 0; i < _scriptText.size(); i++) {
+ debug(4, "%d [%04x]: %s", i, _scriptText[i]->offset, _scriptText[i]->line.c_str());
+ }
+}
+
+void Script::printLine(int offset) {
+ for (uint i = 0; i < _scriptText.size(); i++)
+ if (_scriptText[i]->offset >= offset) {
+ debug(4, "%d [%04x]: %s", i, _scriptText[i]->offset, _scriptText[i]->line.c_str());
+ break;
+ }
+}
+
+bool Script::execute(World *world, int loopCount, Common::String *inputText, Designed *inputClick, WageEngine *engine) {
+ _world = world;
+ _loopCount = loopCount;
+ _inputText = inputText;
+ _inputClick = inputClick;
+ _engine = engine;
+ _handled = false;
+ Common::String input;
+
+ if (inputText)
+ input = *inputText;
+
+ _data->seek(12);
+ while (_data->pos() < _data->size()) {
+ printLine(_data->pos());
+
+ byte command = _data->readByte();
+
+ switch(command) {
+ case 0x80: // IF
+ processIf();
+ break;
+ case 0x87: // EXIT
+ debug(6, "exit at offset %d", _data->pos() - 1);
+
+ return true;
+ case 0x89: // MOVE
+ {
+ Scene *currentScene = _world->_player->_currentScene;
+ processMove();
+ if (_world->_player->_currentScene != currentScene)
+ return true;
+ break;
+ }
+ case 0x8B: // PRINT
+ {
+ Operand *op = readOperand();
+ // TODO check op type is string or number, or something good...
+ _handled = true;
+ _engine->appendText(op->toString().c_str());
+ delete op;
+ byte d = _data->readByte();
+ if (d != 0xFD)
+ warning("Operand 0x8B (PRINT) End Byte != 0xFD");
+ break;
+ }
+ case 0x8C: // SOUND
+ {
+ Operand *op = readOperand();
+ // TODO check op type is string.
+ _handled = true;
+ _engine->playSound(op->toString());
+ delete op;
+ byte d = _data->readByte();
+ if (d != 0xFD)
+ warning("Operand 0x8B (PRINT) End Byte != 0xFD");
+ break;
+ }
+ case 0x8E: // LET
+ processLet();
+ break;
+ case 0x95: // MENU
+ {
+ Operand *op = readStringOperand(); // allows empty menu
+ // TODO check op type is string.
+ _engine->setMenu(op->toString());
+ delete op;
+ byte d = _data->readByte();
+ if (d != 0xFD)
+ warning("Operand 0x8B (PRINT) End Byte != 0xFD");
+ }
+ case 0x88: // END
+ break;
+ default:
+ debug(0, "Unknown opcode: %d", _data->pos());
+ }
+ }
+
+ if (_world->_globalScript != this) {
+ debug(1, "Executing global script...");
+ bool globalHandled = _world->_globalScript->execute(_world, _loopCount, &input, _inputClick, _engine);
+ if (globalHandled)
+ _handled = true;
+ } else if (!input.empty()) {
+ if (input.contains("north")) {
+ _handled = _engine->handleMoveCommand(NORTH, "north");
+ } else if (input.contains("east")) {
+ _handled = _engine->handleMoveCommand(EAST, "east");
+ } else if (input.contains("south")) {
+ _handled = _engine->handleMoveCommand(SOUTH, "south");
+ } else if (input.contains("west")) {
+ _handled = _engine->handleMoveCommand(WEST, "west");
+ } else if (input.hasPrefix("take ")) {
+ _handled = _engine->handleTakeCommand(&input.c_str()[5]);
+ } else if (input.hasPrefix("get ")) {
+ _handled = _engine->handleTakeCommand(&input.c_str()[4]);
+ } else if (input.hasPrefix("pick up ")) {
+ _handled = _engine->handleTakeCommand(&input.c_str()[8]);
+ } else if (input.hasPrefix("drop ")) {
+ _handled = _engine->handleDropCommand(&input.c_str()[5]);
+ } else if (input.hasPrefix("aim ")) {
+ _handled = _engine->handleAimCommand(&input.c_str()[4]);
+ } else if (input.hasPrefix("wear ")) {
+ _handled = _engine->handleWearCommand(&input.c_str()[5]);
+ } else if (input.hasPrefix("put on ")) {
+ _handled = _engine->handleWearCommand(&input.c_str()[7]);
+ } else if (input.hasPrefix("offer ")) {
+ _handled = _engine->handleOfferCommand(&input.c_str()[6]);
+ } else if (input.contains("look")) {
+ _handled = _engine->handleLookCommand();
+ } else if (input.contains("inventory")) {
+ _handled = _engine->handleInventoryCommand();
+ } else if (input.contains("status")) {
+ _handled = _engine->handleStatusCommand();
+ } else if (input.contains("rest") || input.equals("wait")) {
+ _handled = _engine->handleRestCommand();
+ } else if (_engine->getOffer() != NULL && input.contains("accept")) {
+ _handled = _engine->handleAcceptCommand();
+ } else {
+ Chr *player = _world->_player;
+ ObjArray *weapons = player->getWeapons(true);
+ for (ObjArray::const_iterator weapon = weapons->begin(); weapon != weapons->end(); ++weapon) {
+ if (_engine->tryAttack(*weapon, input)) {
+ _handled = _engine->handleAttack(*weapon);
+ break;
+ }
+ }
+
+ delete weapons;
+ }
+ // TODO: weapons, offer, etc...
+ } else if (_inputClick->_classType == OBJ) {
+ Obj *obj = (Obj *)_inputClick;
+ if (obj->_type != Obj::IMMOBILE_OBJECT) {
+ _engine->takeObj(obj);
+ } else {
+ _engine->appendText(obj->_clickMessage.c_str());
+ }
+
+ _handled = true;
+ }
+
+ return _handled;
+}
+
+Script::Operand *Script::readOperand() {
+ byte operandType = _data->readByte();
+
+ debug(7, "%x: readOperand: 0x%x", _data->pos(), operandType);
+
+ Context *cont = &_world->_player->_context;
+ switch (operandType) {
+ case 0xA0: // TEXT$
+ return new Operand(_inputText, TEXT_INPUT);
+ case 0xA1:
+ return new Operand(_inputClick, CLICK_INPUT);
+ case 0xC0: // STORAGE@
+ return new Operand(_world->_storageScene, SCENE);
+ case 0xC1: // SCENE@
+ return new Operand(_world->_player->_currentScene, SCENE);
+ case 0xC2: // PLAYER@
+ return new Operand(_world->_player, CHR);
+ case 0xC3: // MONSTER@
+ return new Operand(_engine->getMonster(), CHR);
+ case 0xC4: // RANDOMSCN@
+ return new Operand(_world->_orderedScenes[_engine->_rnd->getRandomNumber(_world->_orderedScenes.size())], SCENE);
+ case 0xC5: // RANDOMCHR@
+ return new Operand(_world->_orderedChrs[_engine->_rnd->getRandomNumber(_world->_orderedChrs.size())], CHR);
+ case 0xC6: // RANDOMOBJ@
+ return new Operand(_world->_orderedObjs[_engine->_rnd->getRandomNumber(_world->_orderedObjs.size())], OBJ);
+ case 0xB0: // VISITS#
+ return new Operand(cont->_visits, NUMBER);
+ case 0xB1: // RANDOM# for Star Trek, but VISITS# for some other games?
+ return new Operand(1 + _engine->_rnd->getRandomNumber(100), NUMBER);
+ case 0xB5: // RANDOM# // A random number between 1 and 100.
+ return new Operand(1 + _engine->_rnd->getRandomNumber(100), NUMBER);
+ case 0xB2: // LOOP#
+ return new Operand(_loopCount, NUMBER);
+ case 0xB3: // VICTORY#
+ return new Operand(cont->_kills, NUMBER);
+ case 0xB4: // BADCOPY#
+ return new Operand(0, NUMBER); // \?\?\??
+ case 0xFF:
+ {
+ // user variable
+ int value = _data->readByte();
+
+ // TODO: Verify that we're using the right index.
+ return new Operand(cont->_userVariables[value - 1], NUMBER);
+ }
+ case 0xD0:
+ return new Operand(cont->_statVariables[PHYS_STR_BAS], NUMBER);
+ case 0xD1:
+ return new Operand(cont->_statVariables[PHYS_HIT_BAS], NUMBER);
+ case 0xD2:
+ return new Operand(cont->_statVariables[PHYS_ARM_BAS], NUMBER);
+ case 0xD3:
+ return new Operand(cont->_statVariables[PHYS_ACC_BAS], NUMBER);
+ case 0xD4:
+ return new Operand(cont->_statVariables[SPIR_STR_BAS], NUMBER);
+ case 0xD5:
+ return new Operand(cont->_statVariables[SPIR_HIT_BAS], NUMBER);
+ case 0xD6:
+ return new Operand(cont->_statVariables[SPIR_ARM_BAS], NUMBER);
+ case 0xD7:
+ return new Operand(cont->_statVariables[SPIR_ACC_BAS], NUMBER);
+ case 0xD8:
+ return new Operand(cont->_statVariables[PHYS_SPE_BAS], NUMBER);
+ case 0xE0:
+ return new Operand(cont->_statVariables[PHYS_STR_CUR], NUMBER);
+ case 0xE1:
+ return new Operand(cont->_statVariables[PHYS_HIT_CUR], NUMBER);
+ case 0xE2:
+ return new Operand(cont->_statVariables[PHYS_ARM_CUR], NUMBER);
+ case 0xE3:
+ return new Operand(cont->_statVariables[PHYS_ACC_CUR], NUMBER);
+ case 0xE4:
+ return new Operand(cont->_statVariables[SPIR_STR_CUR], NUMBER);
+ case 0xE5:
+ return new Operand(cont->_statVariables[SPIR_HIT_CUR], NUMBER);
+ case 0xE6:
+ return new Operand(cont->_statVariables[SPIR_ARM_CUR], NUMBER);
+ case 0xE7:
+ return new Operand(cont->_statVariables[SPIR_ACC_CUR], NUMBER);
+ case 0xE8:
+ return new Operand(cont->_statVariables[PHYS_SPE_CUR], NUMBER);
+ default:
+ if (operandType >= 0x20 && operandType < 0x80) {
+ _data->seek(-1, SEEK_CUR);
+ return readStringOperand();
+ } else {
+ debug("Dunno what %x is (index=%d)!\n", operandType, _data->pos()-1);
+ }
+ return NULL;
+ }
+}
+
+void Script::assign(byte operandType, int uservar, uint16 value) {
+ Context *cont = &_world->_player->_context;
+
+ switch (operandType) {
+ case 0xFF:
+ cont->_userVariables[uservar - 1] = value;
+ break;
+ case 0xD0:
+ cont->_statVariables[PHYS_STR_BAS] = value;
+ break;
+ case 0xD1:
+ cont->_statVariables[PHYS_HIT_BAS] = value;
+ break;
+ case 0xD2:
+ cont->_statVariables[PHYS_ARM_BAS] = value;
+ break;
+ case 0xD3:
+ cont->_statVariables[PHYS_ACC_BAS] = value;
+ break;
+ case 0xD4:
+ cont->_statVariables[SPIR_STR_BAS] = value;
+ break;
+ case 0xD5:
+ cont->_statVariables[SPIR_HIT_BAS] = value;
+ break;
+ case 0xD6:
+ cont->_statVariables[SPIR_ARM_BAS] = value;
+ break;
+ case 0xD7:
+ cont->_statVariables[SPIR_ACC_BAS] = value;
+ break;
+ case 0xD8:
+ cont->_statVariables[PHYS_SPE_BAS] = value;
+ break;
+ case 0xE0:
+ cont->_statVariables[PHYS_STR_CUR] = value;
+ break;
+ case 0xE1:
+ cont->_statVariables[PHYS_HIT_CUR] = value;
+ break;
+ case 0xE2:
+ cont->_statVariables[PHYS_ARM_CUR] = value;
+ break;
+ case 0xE3:
+ cont->_statVariables[PHYS_ACC_CUR] = value;
+ break;
+ case 0xE4:
+ cont->_statVariables[SPIR_STR_CUR] = value;
+ break;
+ case 0xE5:
+ cont->_statVariables[SPIR_HIT_CUR] = value;
+ break;
+ case 0xE6:
+ cont->_statVariables[SPIR_ARM_CUR] = value;
+ break;
+ case 0xE7:
+ cont->_statVariables[SPIR_ACC_CUR] = value;
+ break;
+ case 0xE8:
+ cont->_statVariables[PHYS_SPE_CUR] = value;
+ break;
+ default:
+ debug("No idea what I'm supposed to assign! (%x at %d)!\n", operandType, _data->pos()-1);
+ }
+}
+
+Script::Operand *Script::readStringOperand() {
+ Common::String *str;
+ bool allDigits = true;
+
+ str = new Common::String();
+
+ while (true) {
+ byte c = _data->readByte();
+ if (c >= 0x20 && c < 0x80)
+ *str += c;
+ else
+ break;
+ if (c < '0' || c > '9')
+ allDigits = false;
+ }
+ _data->seek(-1, SEEK_CUR);
+
+ if (allDigits && !str->empty()) {
+ int r = atol(str->c_str());
+ delete str;
+
+ return new Operand(r, NUMBER);
+ } else {
+ // TODO: This string could be a room name or something like that.
+ return new Operand(str, STRING);
+ }
+}
+
+const char *Script::readOperator() {
+ byte cmd = _data->readByte();
+
+ debug(7, "readOperator: 0x%x", cmd);
+ switch (cmd) {
+ case 0x81:
+ return "=";
+ case 0x82:
+ return "<";
+ case 0x83:
+ return ">";
+ case 0x8f:
+ return "+";
+ case 0x90:
+ return "-";
+ case 0x91:
+ return "*";
+ case 0x92:
+ return "/";
+ case 0x93:
+ return "==";
+ case 0x94:
+ return ">>";
+ case 0xfd:
+ return ";";
+ default:
+ warning("UNKNOWN OP %x", cmd);
+ }
+ return NULL;
+}
+
+void Script::processIf() {
+ int logicalOp = 0; // 0 => initial, 1 => and, 2 => or
+ bool result = true;
+ bool done = false;
+
+ do {
+ Operand *lhs = readOperand();
+ const char *op = readOperator();
+ Operand *rhs = readOperand();
+
+ bool condResult = eval(lhs, op, rhs);
+
+ delete lhs;
+ delete rhs;
+
+ if (logicalOp == 1) {
+ result = (result && condResult);
+ } else if (logicalOp == 2) {
+ result = (result || condResult);
+ } else { // logicalOp == 0
+ result = condResult;
+ }
+
+ byte logical = _data->readByte();
+
+ if (logical == 0x84) {
+ logicalOp = 1; // and
+ } else if (logical == 0x85) {
+ logicalOp = 2; // or
+ } else if (logical == 0xFE) {
+ done = true; // then
+ }
+ } while (!done);
+
+ if (result == false) {
+ skipBlock();
+ }
+}
+
+void Script::skipIf() {
+ do {
+ Operand *lhs = readOperand();
+ readOperator();
+ Operand *rhs = readOperand();
+
+ delete lhs;
+ delete rhs;
+ } while (_data->readByte() != 0xFE);
+}
+
+void Script::skipBlock() {
+ int nesting = 1;
+
+ while (true) {
+ byte op = _data->readByte();
+
+ if (_data->eos())
+ return;
+
+ if (op == 0x80) { // IF
+ nesting++;
+ skipIf();
+ } else if (op == 0x88 || op == 0x87) { // END or EXIT
+ nesting--;
+ if (nesting == 0) {
+ return;
+ }
+ } else switch (op) {
+ case 0x8B: // PRINT
+ case 0x8C: // SOUND
+ case 0x8E: // LET
+ case 0x95: // MENU
+ while (_data->readByte() != 0xFD)
+ ;
+ }
+ }
+}
+
+enum {
+ kCompEqNumNum,
+ kCompEqObjScene,
+ kCompEqChrScene,
+ kCompEqObjChr,
+ kCompEqChrChr,
+ kCompEqSceneScene,
+ kCompEqStringTextInput,
+ kCompEqTextInputString,
+ kCompEqNumberTextInput,
+ kCompEqTextInputNumber,
+ kCompLtNumNum,
+ kCompLtStringTextInput,
+ kCompLtTextInputString,
+ kCompLtObjChr,
+ kCompLtChrObj,
+ kCompLtObjScene,
+ kCompGtNumNum,
+ kCompGtStringString,
+ kCompGtChrScene,
+ kMoveObjChr,
+ kMoveObjScene,
+ kMoveChrScene
+};
+
+static const char *typeNames[] = {
+ "OBJ",
+ "CHR",
+ "SCENE",
+ "NUMBER",
+ "STRING",
+ "CLICK_INPUT",
+ "TEXT_INPUT"
+};
+
+static const char *operandTypeToStr(int type) {
+ if (type < 0 || type > 6)
+ return "UNKNOWN";
+
+ return typeNames[type];
+}
+
+struct Comparator {
+ char op;
+ OperandType o1;
+ OperandType o2;
+ int cmp;
+} static comparators[] = {
+ { '=', NUMBER, NUMBER, kCompEqNumNum },
+ { '=', OBJ, SCENE, kCompEqObjScene },
+ { '=', CHR, SCENE, kCompEqChrScene },
+ { '=', OBJ, CHR, kCompEqObjChr },
+ { '=', CHR, CHR, kCompEqChrChr },
+ { '=', SCENE, SCENE, kCompEqSceneScene },
+ { '=', STRING, TEXT_INPUT, kCompEqStringTextInput },
+ { '=', TEXT_INPUT, STRING, kCompEqTextInputString },
+ { '=', NUMBER, TEXT_INPUT, kCompEqNumberTextInput },
+ { '=', TEXT_INPUT, NUMBER, kCompEqTextInputNumber },
+
+ { '<', NUMBER, NUMBER, kCompLtNumNum },
+ { '<', STRING, TEXT_INPUT, kCompLtStringTextInput },
+ { '<', TEXT_INPUT, STRING, kCompLtTextInputString },
+ { '<', OBJ, CHR, kCompLtObjChr },
+ { '<', CHR, OBJ, kCompLtChrObj },
+ { '<', OBJ, SCENE, kCompLtObjScene },
+ { '<', CHR, CHR, kCompEqChrChr }, // Same logic as =
+ { '<', SCENE, SCENE, kCompEqSceneScene },
+
+ { '>', NUMBER, NUMBER, kCompGtNumNum },
+ { '>', TEXT_INPUT, STRING, kCompLtTextInputString }, // Same logic as <
+ //FIXME: this prevents the below cases from working due to exact
+ //matches taking precedence over conversions...
+ //{ '>', STRING, STRING, kCompGtStringString }, // Same logic as <
+ { '>', OBJ, CHR, kCompLtObjChr }, // Same logic as <
+ { '>', OBJ, SCENE, kCompLtObjScene }, // Same logic as <
+ { '>', CHR, SCENE, kCompGtChrScene },
+
+ { 'M', OBJ, CHR, kMoveObjChr },
+ { 'M', OBJ, SCENE, kMoveObjScene },
+ { 'M', CHR, SCENE, kMoveChrScene },
+ { 0, OBJ, OBJ, 0 }
+};
+
+bool Script::compare(Operand *o1, Operand *o2, int comparator) {
+ switch(comparator) {
+ case kCompEqNumNum:
+ return o1->_value.number == o2->_value.number;
+ case kCompEqObjScene:
+ for (ObjList::const_iterator it = o2->_value.scene->_objs.begin(); it != o2->_value.scene->_objs.end(); ++it)
+ if (*it == o1->_value.obj)
+ return true;
+ return false;
+ case kCompEqChrScene:
+ for (ChrList::const_iterator it = o2->_value.scene->_chrs.begin(); it != o2->_value.scene->_chrs.end(); ++it)
+ if (*it == o1->_value.chr)
+ return true;
+ return false;
+ case kCompEqObjChr:
+ for (ObjArray::const_iterator it = o2->_value.chr->_inventory.begin(); it != o2->_value.chr->_inventory.end(); ++it)
+ if (*it == o1->_value.obj)
+ return true;
+ return false;
+ case kCompEqChrChr:
+ return o1->_value.chr == o2->_value.chr;
+ case kCompEqSceneScene:
+ return o1->_value.scene == o2->_value.scene;
+ case kCompEqStringTextInput:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(*o1->_value.string);
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompEqTextInputString:
+ return compare(o2, o1, kCompEqStringTextInput);
+ case kCompEqNumberTextInput:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(o1->toString());
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompEqTextInputNumber:
+ if (_inputText == NULL) {
+ return false;
+ } else {
+ Common::String s1(*_inputText), s2(o2->toString());
+ s1.toLowercase();
+ s2.toLowercase();
+
+ return s1.contains(s2);
+ }
+ case kCompLtNumNum:
+ return o1->_value.number < o2->_value.number;
+ case kCompLtStringTextInput:
+ return !compare(o1, o2, kCompEqStringTextInput);
+ case kCompLtTextInputString:
+ return !compare(o2, o1, kCompEqStringTextInput);
+ case kCompLtObjChr:
+ return o1->_value.obj->_currentOwner != o2->_value.chr;
+ case kCompLtChrObj:
+ return compare(o2, o1, kCompLtObjChr);
+ case kCompLtObjScene:
+ return o1->_value.obj->_currentScene != o2->_value.scene;
+ case kCompGtNumNum:
+ return o1->_value.number > o2->_value.number;
+ case kCompGtStringString:
+ return o1->_value.string == o2->_value.string;
+ case kCompGtChrScene:
+ return (o1->_value.chr != NULL && o1->_value.chr->_currentScene != o2->_value.scene);
+ case kMoveObjChr:
+ if (o1->_value.obj->_currentOwner != o2->_value.chr) {
+ _world->move(o1->_value.obj, o2->_value.chr);
+ _handled = true; // TODO: Is this correct?
+ }
+ break;
+ case kMoveObjScene:
+ if (o1->_value.obj->_currentScene != o2->_value.scene) {
+ _world->move(o1->_value.obj, o2->_value.scene);
+ // Note: This shouldn't call setHandled() - see
+ // Sultan's Palace 'Food and Drink' scene.
+ }
+ break;
+ case kMoveChrScene:
+ _world->move(o1->_value.chr, o2->_value.scene);
+ _handled = true; // TODO: Is this correct?
+ break;
+ }
+
+ return false;
+}
+
+bool Script::evaluatePair(Operand *lhs, const char *op, Operand *rhs) {
+ debug(7, "HANDLING CASE: [lhs=%s/%s, op=%s rhs=%s/%s]",
+ operandTypeToStr(lhs->_type), lhs->toString().c_str(), op, operandTypeToStr(rhs->_type), rhs->toString().c_str());
+
+ for (int cmp = 0; comparators[cmp].op != 0; cmp++) {
+ if (comparators[cmp].op != op[0])
+ continue;
+
+ if (comparators[cmp].o1 == lhs->_type && comparators[cmp].o2 == rhs->_type)
+ return compare(lhs, rhs, comparators[cmp].cmp);
+ }
+
+ // Now, try partial matches.
+ Operand *c1, *c2;
+ for (int cmp = 0; comparators[cmp].op != 0; cmp++) {
+ if (comparators[cmp].op != op[0])
+ continue;
+
+ if (comparators[cmp].o1 == lhs->_type &&
+ (c2 = convertOperand(rhs, comparators[cmp].o2)) != NULL) {
+ bool res = compare(lhs, c2, comparators[cmp].cmp);
+ delete c2;
+ return res;
+ } else if (comparators[cmp].o2 == rhs->_type &&
+ (c1 = convertOperand(lhs, comparators[cmp].o1)) != NULL) {
+ bool res = compare(c1, rhs, comparators[cmp].cmp);
+ delete c1;
+ return res;
+ }
+ }
+
+ // Now, try double conversion.
+ for (int cmp = 0; comparators[cmp].op != 0; cmp++) {
+ if (comparators[cmp].op != op[0])
+ continue;
+
+ if (comparators[cmp].o1 == lhs->_type || comparators[cmp].o2 == rhs->_type)
+ continue;
+
+ if ((c1 = convertOperand(lhs, comparators[cmp].o1)) != NULL) {
+ if ((c2 = convertOperand(rhs, comparators[cmp].o2)) != NULL) {
+ bool res = compare(c1, c2, comparators[cmp].cmp);
+ delete c1;
+ delete c2;
+ return res;
+ }
+ delete c1;
+ }
+ }
+
+ warning("UNHANDLED CASE: [lhs=%s/%s, op=%s rhs=%s/%s]",
+ operandTypeToStr(lhs->_type), lhs->toString().c_str(), op, operandTypeToStr(rhs->_type), rhs->toString().c_str());
+
+ return false;
+}
+
+bool Script::eval(Operand *lhs, const char *op, Operand *rhs) {
+ bool result = false;
+
+ if (lhs->_type == CLICK_INPUT || rhs->_type == CLICK_INPUT) {
+ return evalClickCondition(lhs, op, rhs);
+ } else if (!strcmp(op, "==") || !strcmp(op, ">>")) {
+ // TODO: check if >> can be used for click inputs and if == can be used for other things
+ // exact string match
+ if (lhs->_type == TEXT_INPUT) {
+ if ((rhs->_type != STRING && rhs->_type != NUMBER) || _inputText == NULL) {
+ result = false;
+ } else {
+ result = _inputText->equalsIgnoreCase(rhs->toString());
+ }
+ } else if (rhs->_type == TEXT_INPUT) {
+ if ((lhs->_type != STRING && lhs->_type != NUMBER) || _inputText == NULL) {
+ result = false;
+ } else {
+ result = _inputText->equalsIgnoreCase(lhs->toString());
+ }
+ } else {
+ error("UNHANDLED CASE: [lhs=%s/%s, rhs=%s/%s]",
+ operandTypeToStr(lhs->_type), lhs->toString().c_str(), operandTypeToStr(rhs->_type), rhs->toString().c_str());
+ }
+ if (!strcmp(op, ">>")) {
+ result = !result;
+ }
+
+ return result;
+ } else {
+ return evaluatePair(lhs, op, rhs);
+ }
+
+ return false;
+}
+
+Script::Operand *Script::convertOperand(Operand *operand, int type) {
+ if (operand->_type == type)
+ error("Incorrect conversion to type %d", type);
+
+ if (type == SCENE) {
+ if (operand->_type == STRING || operand->_type == NUMBER) {
+ Common::String key(operand->toString());
+ key.toLowercase();
+ if (_world->_scenes.contains(key))
+ return new Operand(_world->_scenes[key], SCENE);
+ }
+ } else if (type == OBJ) {
+ if (operand->_type == STRING || operand->_type == NUMBER) {
+ Common::String key = operand->toString();
+ key.toLowercase();
+ if (_world->_objs.contains(key))
+ return new Operand(_world->_objs[key], OBJ);
+ } else if (operand->_type == CLICK_INPUT) {
+ if (_inputClick->_classType == OBJ)
+ return new Operand(_inputClick, OBJ);
+ }
+ } else if (type == CHR) {
+ if (operand->_type == STRING || operand->_type == NUMBER) {
+ Common::String key = operand->toString();
+ key.toLowercase();
+ if (_world->_chrs.contains(key))
+ return new Operand(_world->_chrs[key], CHR);
+ } else if (operand->_type == CLICK_INPUT) {
+ if (_inputClick->_classType == CHR)
+ return new Operand(_inputClick, CHR);
+ }
+ }
+
+ return NULL;
+}
+
+bool Script::evalClickEquality(Operand *lhs, Operand *rhs, bool partialMatch) {
+ bool result = false;
+ if (lhs->_value.obj == NULL || rhs->_value.obj == NULL) {
+ result = false;
+ } else if (lhs->_value.obj == rhs->_value.obj) {
+ result = true;
+ } else if (rhs->_type == STRING) {
+ Common::String str = rhs->toString();
+ str.toLowercase();
+
+ debug(9, "evalClickEquality(%s, %s, %d)", lhs->_value.designed->_name.c_str(), rhs->_value.designed->_name.c_str(), partialMatch);
+ debug(9, "l: %s r: %s)", operandTypeToStr(lhs->_type), operandTypeToStr(rhs->_type));
+ debug(9, "class: %d", lhs->_value.inputClick->_classType);
+
+ if (lhs->_value.inputClick->_classType == CHR || lhs->_value.inputClick->_classType == OBJ) {
+ Common::String name = lhs->_value.designed->_name;
+ name.toLowercase();
+
+ if (partialMatch)
+ result = name.contains(str);
+ else
+ result = name.equals(str);
+ }
+
+ debug(9, "result: %d", result);
+ }
+ return result;
+}
+
+bool Script::evalClickCondition(Operand *lhs, const char *op, Operand *rhs) {
+ // TODO: check if >> can be used for click inputs
+ if (strcmp(op, "==") && strcmp(op, "=") && strcmp(op, "<") && strcmp(op, ">")) {
+ error("Unknown operation '%s' for Script::evalClickCondition", op);
+ }
+
+ bool partialMatch = strcmp(op, "==");
+ bool result;
+ if (lhs->_type == CLICK_INPUT) {
+ result = evalClickEquality(lhs, rhs, partialMatch);
+ } else {
+ result = evalClickEquality(rhs, lhs, partialMatch);
+ }
+ if (!strcmp(op, "<") || !strcmp(op, ">")) {
+ // CLICK$<FOO only matches if there was a click
+ if (_inputClick == NULL) {
+ result = false;
+ } else {
+ result = !result;
+ }
+ }
+ return result;
+}
+
+void Script::processMove() {
+ Operand *what = readOperand();
+ byte skip = _data->readByte();
+ if (skip != 0x8a)
+ error("Incorrect operator for MOVE: %02x", skip);
+
+ Operand *to = readOperand();
+
+ skip = _data->readByte();
+ if (skip != 0xfd)
+ error("No end for MOVE: %02x", skip);
+
+ evaluatePair(what, "M", to);
+
+ delete what;
+ delete to;
+}
+
+void Script::processLet() {
+ const char *lastOp = NULL;
+ int16 result = 0;
+ int operandType = _data->readByte();
+ int uservar = 0;
+
+ if (operandType == 0xff) {
+ uservar = _data->readByte();
+ }
+
+ byte eq = _data->readByte(); // skip "=" operator
+
+ debug(7, "processLet: 0x%x, uservar: 0x%x, eq: 0x%x", operandType, uservar, eq);
+
+ do {
+ Operand *operand = readOperand();
+ // TODO assert that value is NUMBER
+ int16 value = operand->_value.number;
+ delete operand;
+ if (lastOp != NULL) {
+ if (lastOp[0] == '+')
+ result += value;
+ else if (lastOp[0] == '-')
+ result -= value;
+ else if (lastOp[0] == '/')
+ result = (int16)(value == 0 ? 0 : result / value);
+ else if (lastOp[0] == '*')
+ result *= value;
+ } else {
+ result = value;
+ }
+ lastOp = readOperator();
+
+ if (lastOp[0] == ';')
+ break;
+ } while (true);
+ //System.out.println("processLet " + buildStringFromOffset(oldIndex - 1, index - oldIndex + 1) + "}");
+
+ assign(operandType, uservar, result);
+}
+
+enum {
+ BLOCK_START,
+ BLOCK_END,
+ STATEMENT,
+ OPERATOR,
+ OPCODE
+};
+
+struct Mapping {
+ const char *cmd;
+ int type;
+} static const mapping[] = {
+ { "IF{", STATEMENT }, // 0x80
+ { "=", OPERATOR },
+ { "<", OPERATOR },
+ { ">", OPERATOR },
+ { "}AND{", OPCODE },
+ { "}OR{", OPCODE },
+ { "\?\?\?(0x86)", OPCODE },
+ { "EXIT\n", BLOCK_END },
+ { "END\n", BLOCK_END }, // 0x88
+ { "MOVE{", STATEMENT },
+ { "}TO{", OPCODE },
+ { "PRINT{", STATEMENT },
+ { "SOUND{", STATEMENT },
+ { "\?\?\?(0x8d)", OPCODE },
+ { "LET{", STATEMENT },
+ { "+", OPERATOR },
+ { "-", OPERATOR }, // 0x90
+ { "*", OPERATOR },
+ { "/", OPERATOR },
+ { "==", OPERATOR },
+ { ">>", OPERATOR },
+ { "MENU{", STATEMENT },
+ { "\?\?\?(0x96)", OPCODE },
+ { "\?\?\?(0x97)", OPCODE },
+ { "\?\?\?(0x98)", OPCODE }, // 0x98
+ { "\?\?\?(0x99)", OPCODE },
+ { "\?\?\?(0x9a)", OPCODE },
+ { "\?\?\?(0x9b)", OPCODE },
+ { "\?\?\?(0x9c)", OPCODE },
+ { "\?\?\?(0x9d)", OPCODE },
+ { "\?\?\?(0x9e)", OPCODE },
+ { "\?\?\?(0x9f)", OPCODE },
+ { "TEXT$", OPCODE }, // 0xa0
+ { "CLICK$", OPCODE },
+ { "\?\?\?(0xa2)", OPCODE },
+ { "\?\?\?(0xa3)", OPCODE },
+ { "\?\?\?(0xa4)", OPCODE },
+ { "\?\?\?(0xa5)", OPCODE },
+ { "\?\?\?(0xa6)", OPCODE },
+ { "\?\?\?(0xa7)", OPCODE },
+ { "\?\?\?(0xa8)", OPCODE }, // 0xa8
+ { "\?\?\?(0xa9)", OPCODE },
+ { "\?\?\?(0xaa)", OPCODE },
+ { "\?\?\?(0xab)", OPCODE },
+ { "\?\?\?(0xac)", OPCODE },
+ { "\?\?\?(0xad)", OPCODE },
+ { "\?\?\?(0xae)", OPCODE },
+ { "\?\?\?(0xaf)", OPCODE },
+ { "VISITS#", OPCODE }, // 0xb0 // The number of scenes the player has visited, including repeated visits.
+ { "RANDOM#", OPCODE }, // RANDOM# for Star Trek, but VISITS# for some other games?
+ { "LOOP#", OPCODE }, // The number of commands the player has given in the current scene.
+ { "VICTORY#", OPCODE }, // The number of characters killed.
+ { "BADCOPY#", OPCODE },
+ { "RANDOM#", OPCODE }, // A random number between 1 and 100.
+ { "\?\?\?(0xb6)", OPCODE },
+ { "\?\?\?(0xb7)", OPCODE },
+ { "\?\?\?(0xb8)", OPCODE }, // 0xb8
+ { "\?\?\?(0xb9)", OPCODE },
+ { "\?\?\?(0xba)", OPCODE },
+ { "\?\?\?(0xbb)", OPCODE },
+ { "\?\?\?(0xbc)", OPCODE },
+ { "\?\?\?(0xbd)", OPCODE },
+ { "\?\?\?(0xbe)", OPCODE },
+ { "\?\?\?(0xbf)", OPCODE },
+ { "STORAGE@", OPCODE }, // 0xc0
+ { "SCENE@", OPCODE },
+ { "PLAYER@", OPCODE },
+ { "MONSTER@", OPCODE },
+ { "RANDOMSCN@", OPCODE },
+ { "RANDOMCHR@", OPCODE },
+ { "RANDOMOBJ@", OPCODE },
+ { "\?\?\?(0xc7)", OPCODE },
+ { "\?\?\?(0xc8)", OPCODE }, // 0xc8
+ { "\?\?\?(0xc9)", OPCODE },
+ { "\?\?\?(0xca)", OPCODE },
+ { "\?\?\?(0xcb)", OPCODE },
+ { "\?\?\?(0xcc)", OPCODE },
+ { "\?\?\?(0xcd)", OPCODE },
+ { "\?\?\?(0xce)", OPCODE },
+ { "\?\?\?(0xcf)", OPCODE },
+ { "PHYS.STR.BAS#", OPCODE }, // 0xd0
+ { "PHYS.HIT.BAS#", OPCODE },
+ { "PHYS.ARM.BAS#", OPCODE },
+ { "PHYS.ACC.BAS#", OPCODE },
+ { "SPIR.STR.BAS#", OPCODE },
+ { "SPIR.HIT.BAS#", OPCODE },
+ { "SPIR.ARM.BAS#", OPCODE },
+ { "SPIR.ACC.BAS#", OPCODE },
+ { "PHYS.SPE.BAS#", OPCODE }, // 0xd8
+ { "\?\?\?(0xd9)", OPCODE },
+ { "\?\?\?(0xda)", OPCODE },
+ { "\?\?\?(0xdb)", OPCODE },
+ { "\?\?\?(0xdc)", OPCODE },
+ { "\?\?\?(0xdd)", OPCODE },
+ { "\?\?\?(0xde)", OPCODE },
+ { "\?\?\?(0xdf)", OPCODE },
+ { "PHYS.STR.CUR#", OPCODE }, // 0xe0
+ { "PHYS.HIT.CUR#", OPCODE },
+ { "PHYS.ARM.CUR#", OPCODE },
+ { "PHYS.ACC.CUR#", OPCODE },
+ { "SPIR.STR.CUR#", OPCODE },
+ { "SPIR.HIT.CUR#", OPCODE },
+ { "SPIR.ARM.CUR#", OPCODE },
+ { "SPIR.ACC.CUR#", OPCODE },
+ { "PHYS.SPE.CUR#", OPCODE }, // 0xe8
+ { "\?\?\?(0xe9)", OPCODE },
+ { "\?\?\?(0xea)", OPCODE },
+ { "\?\?\?(0xeb)", OPCODE },
+ { "\?\?\?(0xec)", OPCODE },
+ { "\?\?\?(0xed)", OPCODE },
+ { "\?\?\?(0xee)", OPCODE },
+ { "\?\?\?(0xef)", OPCODE },
+ { "\?\?\?(0xf0)", OPCODE },
+ { "\?\?\?(0xf1)", OPCODE },
+ { "\?\?\?(0xf2)", OPCODE },
+ { "\?\?\?(0xf3)", OPCODE },
+ { "\?\?\?(0xf4)", OPCODE },
+ { "\?\?\?(0xf5)", OPCODE },
+ { "\?\?\?(0xf6)", OPCODE },
+ { "\?\?\?(0xf7)", OPCODE },
+ { "\?\?\?(0xf8)", OPCODE }, // 0xa8
+ { "\?\?\?(0xf9)", OPCODE },
+ { "\?\?\?(0xfa)", OPCODE },
+ { "\?\?\?(0xfb)", OPCODE },
+ { "\?\?\?(0xfc)", OPCODE },
+ { "}\n", OPCODE },
+ { "}THEN\n", BLOCK_START },
+ { "\?\?\?(0xff)", OPCODE } // Uservar
+};
+
+void Script::convertToText() {
+ _data->seek(12);
+
+ int indentLevel = 0;
+ ScriptText *scr = new ScriptText;
+ scr->offset = _data->pos();
+
+ while(true) {
+ int c = _data->readByte();
+
+ if (_data->eos())
+ break;
+
+ if (c < 0x80) {
+ if (c < 0x20)
+ error("convertToText: Unknown code 0x%02x at %d", c, _data->pos());
+
+ do {
+ scr->line += c;
+ c = _data->readByte();
+ } while (c < 0x80);
+
+ _data->seek(-1, SEEK_CUR);
+ } else if (c == 0xff) {
+ int value = _data->readByte();
+ value -= 1;
+ scr->line += (char)('A' + (value / 9));
+ scr->line += (char)('0' + (value % 9) + 1);
+ scr->line += '#';
+ } else {
+ const char *cmd = mapping[c - 0x80].cmd;
+ int type = mapping[c - 0x80].type;
+
+ if (type == STATEMENT) {
+ for (int i = 0; i < indentLevel; i++)
+ scr->line += ' ';
+ } else if (type == BLOCK_START) {
+ indentLevel += 2;
+ } else if (type == BLOCK_END) {
+ indentLevel -= 2;
+ for (int i = 0; i < indentLevel; i++)
+ scr->line += ' ';
+ }
+
+ scr->line += cmd;
+
+ if (strchr(cmd, '\n')) {
+ scr->line.deleteLastChar();
+
+ _scriptText.push_back(scr);
+
+ scr = new ScriptText;
+ scr->offset = _data->pos();
+ }
+ }
+ }
+
+ if (!scr->line.empty())
+ _scriptText.push_back(scr);
+ else
+ delete scr;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/script.h b/engines/wage/script.h
new file mode 100644
index 0000000000..de9476228c
--- /dev/null
+++ b/engines/wage/script.h
@@ -0,0 +1,161 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_SCRIPT_H
+#define WAGE_SCRIPT_H
+
+namespace Wage {
+
+class Script {
+public:
+ Script(Common::SeekableReadStream *data);
+ ~Script();
+
+private:
+ Common::SeekableReadStream *_data;
+
+ WageEngine *_engine;
+ World *_world;
+ int _loopCount;
+ Common::String *_inputText;
+ Designed *_inputClick;
+ bool _handled;
+
+ class Operand {
+ public:
+ union {
+ Obj *obj;
+ Chr *chr;
+ Designed *designed;
+ Scene *scene;
+ int16 number;
+ Common::String *string;
+ Designed *inputClick;
+ } _value;
+ OperandType _type;
+
+ Operand(Obj *value, OperandType type) {
+ _value.obj = value;
+ assert(type == OBJ);
+ _type = type;
+ }
+
+ Operand(Chr *value, OperandType type) {
+ _value.chr = value;
+ assert(type == CHR);
+ _type = type;
+ }
+
+ Operand(Scene *value, OperandType type) {
+ _value.scene = value;
+ assert(type == SCENE);
+ _type = type;
+ }
+
+ Operand(int value, OperandType type) {
+ _value.number = value;
+ assert(type == NUMBER);
+ _type = type;
+ }
+
+ Operand(Common::String *value, OperandType type) {
+ _value.string = value;
+ assert(type == STRING || type == TEXT_INPUT);
+ _type = type;
+ }
+
+ Operand(Designed *value, OperandType type) {
+ _value.inputClick = value;
+ assert(type == CLICK_INPUT);
+ _type = type;
+ }
+
+ ~Operand() {
+ if (_type == STRING)
+ delete _value.string;
+ }
+
+ Common::String toString();
+ };
+
+ struct ScriptText {
+ int offset;
+ Common::String line;
+ };
+
+public:
+ void print();
+ void printLine(int offset);
+ bool execute(World *world, int loopCount, Common::String *inputText, Designed *inputClick, WageEngine *engine);
+
+private:
+ Operand *readOperand();
+ Operand *readStringOperand();
+ const char *readOperator();
+ void processIf();
+ void skipBlock();
+ void skipIf();
+ bool compare(Operand *o1, Operand *o2, int comparator);
+ bool eval(Operand *lhs, const char *op, Operand *rhs);
+ bool evaluatePair(Operand *lhs, const char *op, Operand *rhs);
+ Operand *convertOperand(Operand *operand, int type);
+ bool evalClickCondition(Operand *lhs, const char *op, Operand *rhs);
+ bool evalClickEquality(Operand *lhs, Operand *rhs, bool partialMatch);
+ void processMove();
+ void processLet();
+
+ void assign(byte operandType, int uservar, uint16 value);
+
+ void convertToText();
+
+public:
+ Common::Array<ScriptText *> _scriptText;
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/sound.cpp b/engines/wage/sound.cpp
new file mode 100644
index 0000000000..bcb274cab9
--- /dev/null
+++ b/engines/wage/sound.cpp
@@ -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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/stream.h"
+
+#include "wage/wage.h"
+#include "wage/sound.h"
+
+namespace Wage {
+
+static const int8 deltas[] = { 0,-49,-36,-25,-16,-9,-4,-1,0,1,4,9,16,25,36,49 };
+
+Sound::Sound(Common::String name, Common::SeekableReadStream *data) : _name(name) {
+ int size = data->size() - 20;
+ _data = (byte *)calloc(2 * size, 1);
+
+ data->skip(20); // Skip header
+
+ byte value = 0x80;
+ for (int i = 0; i < size; i++) {
+ byte d = data->readByte();
+ value += deltas[d & 0xf];
+ _data[i * 2] = value;
+ value += deltas[(d >> 4) & 0xf];
+ _data[i * 2 + 1] = value;
+ }
+}
+
+Sound::~Sound() {
+ free(_data);
+}
+
+void WageEngine::playSound(Common::String soundName) {
+ warning("STUB: WageEngine::playSound(%s)", soundName.c_str());
+}
+
+void WageEngine::updateSoundTimerForScene(Scene *scene, bool firstTime) {
+ //warning("STUB: WageEngine::updateSoundTimerForScene()");
+}
+
+
+} // End of namespace Wage
diff --git a/engines/wage/sound.h b/engines/wage/sound.h
new file mode 100644
index 0000000000..eccfe33170
--- /dev/null
+++ b/engines/wage/sound.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_SOUND_H
+#define WAGE_SOUND_H
+
+namespace Wage {
+
+class Sound {
+public:
+ Sound(Common::String name, Common::SeekableReadStream *data);
+ ~Sound();
+
+ Common::String _name;
+ byte *_data;
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/util.cpp b/engines/wage/util.cpp
new file mode 100644
index 0000000000..f31a83ca04
--- /dev/null
+++ b/engines/wage/util.cpp
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/stream.h"
+
+#include "wage/wage.h"
+
+namespace Wage {
+
+Common::String readPascalString(Common::SeekableReadStream *in) {
+ Common::String s;
+ char *buf;
+ int len;
+ int i;
+
+ len = in->readByte();
+ buf = (char *)malloc(len + 1);
+ for (i = 0; i < len; i++) {
+ buf[i] = in->readByte();
+ if (buf[i] == 0x0d)
+ buf[i] = '\n';
+ }
+
+ buf[i] = 0;
+
+ s = buf;
+ free(buf);
+
+ return s;
+}
+
+Common::Rect *readRect(Common::SeekableReadStream *in) {
+ int x1, y1, x2, y2;
+
+ y1 = in->readUint16BE();
+ x1 = in->readUint16BE();
+ y2 = in->readUint16BE() + 4;
+ x2 = in->readUint16BE() + 4;
+
+ debug(9, "readRect: %d, %d, %d, %d", x1, y1, x2, y2);
+
+ return new Common::Rect(x1, y1, x2, y2);
+}
+
+const char *getIndefiniteArticle(const Common::String &word) {
+ switch (word[0]) {
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'i': case 'I':
+ case 'o': case 'O':
+ case 'u': case 'U':
+ return "an ";
+ }
+ return "a ";
+}
+
+enum {
+ GENDER_MALE = 0,
+ GENDER_FEMALE = 1,
+ GENDER_NEUTRAL = 2
+};
+
+const char *prependGenderSpecificPronoun(int gender) {
+ if (gender == GENDER_MALE)
+ return "his ";
+ else if (gender == GENDER_FEMALE)
+ return "her ";
+ else
+ return "its ";
+}
+
+const char *getGenderSpecificPronoun(int gender, bool capitalize) {
+ if (gender == GENDER_MALE)
+ return capitalize ? "He" : "he";
+ else if (gender == GENDER_FEMALE)
+ return capitalize ? "She" : "she";
+ else
+ return capitalize ? "It" : "it";
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
new file mode 100644
index 0000000000..e0299c8da2
--- /dev/null
+++ b/engines/wage/wage.cpp
@@ -0,0 +1,515 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/system.h"
+
+#include "engines/engine.h"
+#include "engines/util.h"
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/gui.h"
+#include "wage/dialog.h"
+#include "wage/script.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+WageEngine::WageEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc) {
+ _rnd = new Common::RandomSource("wage");
+
+ _aim = -1;
+ _opponentAim = -1;
+ _temporarilyHidden = false;
+ _isGameOver = false;
+ _monster = NULL;
+ _running = NULL;
+ _lastScene = NULL;
+
+ _loopCount = 0;
+ _turn = 0;
+
+ _commandWasQuick = false;
+
+ _shouldQuit = false;
+
+ _gui = NULL;
+ _world = NULL;
+ _console = NULL;
+ _offer = NULL;
+
+ _resManager = NULL;
+
+ debug("WageEngine::WageEngine()");
+}
+
+WageEngine::~WageEngine() {
+ debug("WageEngine::~WageEngine()");
+
+ DebugMan.clearAllDebugChannels();
+ delete _world;
+ delete _resManager;
+ delete _gui;
+ delete _rnd;
+ delete _console;
+}
+
+Common::Error WageEngine::run() {
+ debug("WageEngine::init");
+
+ initGraphics(512, 342, true);
+
+ // Create debugger console. It requires GFX to be initialized
+ _console = new Console(this);
+
+ _debugger = new Debugger(this);
+
+ // Your main event loop should be (invoked from) here.
+ _resManager = new Common::MacResManager();
+ if (!_resManager->open(getGameFile()))
+ error("Could not open %s as a resource fork", getGameFile());
+
+ _world = new World(this);
+
+ if (!_world->loadWorld(_resManager))
+ return Common::kNoGameDataFoundError;
+
+ _gui = new Gui(this);
+
+ _temporarilyHidden = true;
+ performInitialSetup();
+ Common::String input("look");
+ processTurn(&input, NULL);
+ _temporarilyHidden = false;
+
+ _shouldQuit = false;
+
+ while (!_shouldQuit) {
+ _debugger->onFrame();
+
+ processEvents();
+
+ _gui->draw();
+ g_system->updateScreen();
+ g_system->delayMillis(50);
+ }
+
+ return Common::kNoError;
+}
+
+void WageEngine::processEvents() {
+ Common::Event event;
+
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ if (saveDialog())
+ _shouldQuit = true;
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ _gui->mouseMove(event.mouse.x, event.mouse.y);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ _gui->mouseDown(event.mouse.x, event.mouse.y);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ {
+ Designed *obj = _gui->mouseUp(event.mouse.x, event.mouse.y);
+ if (obj != NULL)
+ processTurn(NULL, obj);
+ }
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ if (!_inputText.empty()) {
+ _inputText.deleteLastChar();
+ _gui->drawInput();
+ }
+ break;
+
+ case Common::KEYCODE_RETURN:
+ if (_inputText.empty())
+ break;
+
+ processTurn(&_inputText, NULL);
+ _gui->disableUndo();
+ break;
+
+ default:
+ if (event.kbd.ascii == '~') {
+ _debugger->attach();
+ break;
+ }
+
+ if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) {
+ if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
+ _gui->processMenuShortCut(event.kbd.flags, event.kbd.ascii);
+ }
+ break;
+ }
+
+ if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {
+ _inputText += (char)event.kbd.ascii;
+ _gui->drawInput();
+ }
+
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void WageEngine::setMenu(Common::String menu) {
+ _world->_commandsMenu = menu;
+
+ _gui->regenCommandsMenu();
+}
+
+void WageEngine::appendText(const char *str) {
+ _gui->appendText(str);
+
+ _inputText.clear();
+}
+
+void WageEngine::gameOver() {
+ DialogButtonArray buttons;
+
+ buttons.push_back(new DialogButton("OK", 66, 67, 68, 28));
+
+ Dialog gameOverDialog(_gui, 199, _world->_gameOverMessage->c_str(), &buttons, 0);
+
+ gameOverDialog.run();
+
+ doClose();
+
+ _gui->disableAllMenus();
+ _gui->enableNewGameMenus();
+ _gui->_menuDirty = true;
+}
+
+bool WageEngine::saveDialog() {
+ DialogButtonArray buttons;
+
+ buttons.push_back(new DialogButton("No", 19, 67, 68, 28));
+ buttons.push_back(new DialogButton("Yes", 112, 67, 68, 28));
+ buttons.push_back(new DialogButton("Cancel", 205, 67, 68, 28));
+
+ Dialog save(_gui, 291, "Save changes before closing?", &buttons, 1);
+
+ int button = save.run();
+
+ if (button == 2) // Cancel
+ return false;
+
+ if (button == 1)
+ saveGame();
+
+ doClose();
+
+ return true;
+}
+
+void WageEngine::saveGame() {
+ warning("STUB: saveGame()");
+}
+
+void WageEngine::performInitialSetup() {
+ debug(5, "Resetting Objs: %d", _world->_orderedObjs.size());
+ for (uint i = 0; i < _world->_orderedObjs.size() - 1; i++)
+ _world->move(_world->_orderedObjs[i], _world->_storageScene, true);
+
+ _world->move(_world->_orderedObjs[_world->_orderedObjs.size() - 1], _world->_storageScene);
+
+ debug(5, "Resetting Chrs: %d", _world->_orderedChrs.size());
+ for (uint i = 0; i < _world->_orderedChrs.size() - 1; i++)
+ _world->move(_world->_orderedChrs[i], _world->_storageScene, true);
+
+ _world->move(_world->_orderedChrs[_world->_orderedChrs.size() - 1], _world->_storageScene);
+
+ debug(5, "Resetting Owners: %d", _world->_orderedObjs.size());
+ for (uint i = 0; i < _world->_orderedObjs.size(); i++) {
+ Obj *obj = _world->_orderedObjs[i];
+ if (!obj->_sceneOrOwner.equalsIgnoreCase(STORAGESCENE)) {
+ Common::String location = obj->_sceneOrOwner;
+ location.toLowercase();
+ if (_world->_scenes.contains(location)) {
+ _world->move(obj, _world->_scenes[location]);
+ } else {
+ if (!_world->_chrs.contains(location)) {
+ // Note: PLAYER@ is not a valid target here.
+ warning("Couldn't move %s to %s", obj->_name.c_str(), obj->_sceneOrOwner.c_str());
+ } else {
+ // TODO: Add check for max items.
+ _world->move(obj, _world->_chrs[location]);
+ }
+ }
+ }
+ }
+
+ bool playerPlaced = false;
+ for (uint i = 0; i < _world->_orderedChrs.size(); i++) {
+ Chr *chr = _world->_orderedChrs[i];
+ if (!chr->_initialScene.equalsIgnoreCase(STORAGESCENE)) {
+ Common::String key = chr->_initialScene;
+ key.toLowercase();
+ if (_world->_scenes.contains(key) && _world->_scenes[key] != NULL) {
+ _world->move(chr, _world->_scenes[key]);
+
+ if (chr->_playerCharacter)
+ debug(0, "Initial scene: %s", key.c_str());
+ } else {
+ _world->move(chr, _world->getRandomScene());
+ }
+ if (chr->_playerCharacter) {
+ playerPlaced = true;
+ }
+ }
+ chr->wearObjs();
+ }
+ if (!playerPlaced) {
+ _world->move(_world->_player, _world->getRandomScene());
+ }
+}
+
+void WageEngine::doClose() {
+ warning("STUB: doClose()");
+}
+
+Scene *WageEngine::getSceneByName(Common::String &location) {
+ Scene *scene;
+ if (location.equals("random@")) {
+ scene = _world->getRandomScene();
+ } else {
+ scene = _world->_scenes[location];
+ }
+ return scene;
+}
+
+void WageEngine::onMove(Designed *what, Designed *from, Designed *to) {
+ Chr *player = _world->_player;
+ Scene *currentScene = player->_currentScene;
+ if (currentScene == _world->_storageScene && !_temporarilyHidden) {
+ if (!_isGameOver) {
+ _isGameOver = true;
+ gameOver();
+ }
+ return;
+ }
+
+ if (from == currentScene || to == currentScene ||
+ (what->_classType == CHR && ((Chr *)what)->_currentScene == currentScene) ||
+ (what->_classType == OBJ && ((Obj *)what)->_currentScene == currentScene))
+ _gui->setSceneDirty();
+
+ if ((from == player || to == player) && !_temporarilyHidden)
+ _gui->regenWeaponsMenu();
+
+ if (what != player && what->_classType == CHR) {
+ Chr *chr = (Chr *)what;
+ if (to == _world->_storageScene) {
+ int returnTo = chr->_returnTo;
+ if (returnTo != Chr::RETURN_TO_STORAGE) {
+ Common::String returnToSceneName;
+ if (returnTo == Chr::RETURN_TO_INITIAL_SCENE) {
+ returnToSceneName = chr->_initialScene;
+ returnToSceneName.toLowercase();
+ } else {
+ returnToSceneName = "random@";
+ }
+ Scene *scene = getSceneByName(returnToSceneName);
+ if (scene != NULL && scene != _world->_storageScene) {
+ _world->move(chr, scene);
+ // To avoid sleeping twice, return if the above move command would cause a sleep.
+ if (scene == currentScene)
+ return;
+ }
+ }
+ } else if (to == player->_currentScene) {
+ if (getMonster() == NULL) {
+ _monster = chr;
+ encounter(player, chr);
+ }
+ }
+ }
+ if (!_temporarilyHidden) {
+ if (to == currentScene || from == currentScene) {
+ redrawScene();
+ g_system->delayMillis(100);
+ }
+ }
+}
+
+void WageEngine::redrawScene() {
+ Scene *currentScene = _world->_player->_currentScene;
+
+ if (currentScene != NULL) {
+ bool firstTime = (_lastScene != currentScene);
+
+ updateSoundTimerForScene(currentScene, firstTime);
+ }
+}
+
+void WageEngine::processTurnInternal(Common::String *textInput, Designed *clickInput) {
+ Scene *playerScene = _world->_player->_currentScene;
+ if (playerScene == _world->_storageScene)
+ return;
+
+ bool shouldEncounter = false;
+
+ if (playerScene != _lastScene) {
+ _loopCount = 0;
+ _lastScene = playerScene;
+ _monster = NULL;
+ _running = NULL;
+ _offer = NULL;
+
+ for (ChrList::const_iterator it = playerScene->_chrs.begin(); it != playerScene->_chrs.end(); ++it) {
+ if (!(*it)->_playerCharacter) {
+ _monster = *it;
+ shouldEncounter = true;
+ break;
+ }
+ }
+ }
+
+ bool monsterWasNull = (_monster == NULL);
+ Script *script = playerScene->_script != NULL ? playerScene->_script : _world->_globalScript;
+ bool handled = script->execute(_world, _loopCount++, textInput, clickInput, this);
+
+ playerScene = _world->_player->_currentScene;
+
+ if (playerScene == _world->_storageScene)
+ return;
+
+ if (playerScene != _lastScene) {
+ _temporarilyHidden = true;
+ _gui->clearOutput();
+ regen();
+ Common::String input("look");
+ processTurnInternal(&input, NULL);
+ redrawScene();
+ _temporarilyHidden = false;
+ } else if (_loopCount == 1) {
+ redrawScene();
+ if (shouldEncounter && getMonster() != NULL) {
+ encounter(_world->_player, _monster);
+ }
+ } else if (textInput != NULL && !handled) {
+ if (monsterWasNull && getMonster() != NULL)
+ return;
+
+ const char *rant = _rnd->getRandomNumber(1) ? "What?" : "Huh?";
+
+ appendText(rant);
+ _commandWasQuick = true;
+ }
+}
+
+void WageEngine::processTurn(Common::String *textInput, Designed *clickInput) {
+ _commandWasQuick = false;
+ Scene *prevScene = _world->_player->_currentScene;
+ Chr *prevMonster = getMonster();
+ Common::String input;
+
+ if (textInput)
+ input = *textInput;
+
+ input.toLowercase();
+ if (input.equals("e"))
+ input = "east";
+ else if (input.equals("w"))
+ input = "west";
+ else if (input.equals("n"))
+ input = "north";
+ else if (input.equals("s"))
+ input = "south";
+
+ processTurnInternal(&input, clickInput);
+ Scene *playerScene = _world->_player->_currentScene;
+
+ if (prevScene != playerScene && playerScene != _world->_storageScene) {
+ if (prevMonster != NULL) {
+ bool followed = false;
+ if (getMonster() == NULL) {
+ // TODO: adjacent scenes doesn't contain up/down etc... verify that monsters can't follow these...
+ if (_world->scenesAreConnected(playerScene, prevMonster->_currentScene)) {
+ int chance = _rnd->getRandomNumber(255);
+ followed = (chance < prevMonster->_followsOpponent);
+ }
+ }
+
+ char buf[512];
+
+ if (followed) {
+ snprintf(buf, 512, "%s%s follows you.", prevMonster->getDefiniteArticle(true), prevMonster->_name.c_str());
+ appendText(buf);
+
+ _world->move(prevMonster, playerScene);
+ } else {
+ snprintf(buf, 512, "You escape %s%s.", prevMonster->getDefiniteArticle(false), prevMonster->_name.c_str());
+ appendText(buf);
+ }
+ }
+ }
+ if (!_commandWasQuick && getMonster() != NULL) {
+ performCombatAction(getMonster(), _world->_player);
+ }
+
+ _inputText.clear();
+ _gui->appendText("");
+}
+
+
+} // End of namespace Wage
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
new file mode 100644
index 0000000000..8ca306aea3
--- /dev/null
+++ b/engines/wage/wage.h
@@ -0,0 +1,239 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_WAGE_H
+#define WAGE_WAGE_H
+
+#include "engines/engine.h"
+#include "common/debug.h"
+#include "common/endian.h"
+#include "common/rect.h"
+#include "common/macresman.h"
+#include "common/random.h"
+
+#include "wage/debugger.h"
+
+struct ADGameDescription;
+
+namespace Wage {
+
+class Console;
+class Chr;
+class Designed;
+class Dialog;
+class Gui;
+class Obj;
+class Scene;
+class World;
+
+typedef Common::Array<Obj *> ObjArray;
+typedef Common::Array<Chr *> ChrArray;
+typedef Common::List<Obj *> ObjList;
+typedef Common::List<Chr *> ChrList;
+
+enum OperandType {
+ OBJ = 0,
+ CHR = 1,
+ SCENE = 2,
+ NUMBER = 3,
+ STRING = 4,
+ CLICK_INPUT = 5,
+ TEXT_INPUT = 6,
+ UNKNOWN = 100
+};
+
+enum Directions {
+ NORTH = 0,
+ SOUTH = 1,
+ EAST = 2,
+ WEST = 3
+};
+
+// our engine debug levels
+enum {
+ kWageDebugExample = 1 << 0,
+ kWageDebugExample2 = 1 << 1
+ // next new level must be 1 << 2 (4)
+ // the current limitation is 32 debug levels (1 << 31 is the last one)
+};
+
+enum {
+ kColorBlack = 0,
+ kColorGray = 1,
+ kColorWhite = 2,
+ kColorGreen = 3
+};
+
+Common::String readPascalString(Common::SeekableReadStream *in);
+Common::Rect *readRect(Common::SeekableReadStream *in);
+const char *getIndefiniteArticle(const Common::String &word);
+const char *prependGenderSpecificPronoun(int gender);
+const char *getGenderSpecificPronoun(int gender, bool capitalize);
+
+
+typedef Common::Array<byte *> Patterns;
+
+class WageEngine : public Engine {
+ friend class Dialog;
+public:
+ WageEngine(OSystem *syst, const ADGameDescription *gameDesc);
+ ~WageEngine();
+
+ virtual bool hasFeature(EngineFeature f) const;
+
+ virtual Common::Error run();
+
+ bool canLoadGameStateCurrently();
+ bool canSaveGameStateCurrently();
+
+ const char *getGameFile() const;
+ void processTurn(Common::String *textInput, Designed *clickInput);
+ void regen();
+
+private:
+ bool loadWorld(Common::MacResManager *resMan);
+ void performInitialSetup();
+ void wearObjs(Chr *chr);
+ void processTurnInternal(Common::String *textInput, Designed *clickInput);
+ void performCombatAction(Chr *npc, Chr *player);
+ int getValidMoveDirections(Chr *npc);
+ void performAttack(Chr *attacker, Chr *victim, Obj *weapon);
+ void performMagic(Chr *attacker, Chr *victim, Obj *magicalObject);
+ void performMove(Chr *chr, int validMoves);
+ void performOffer(Chr *attacker, Chr *victim);
+ void performTake(Chr *npc, Obj *obj);
+ void decrementUses(Obj *obj);
+ bool attackHit(Chr *attacker, Chr *victim, Obj *weapon, int targetIndex);
+ void performHealingMagic(Chr *chr, Obj *magicalObject);
+
+ void doClose();
+ void updateSoundTimerForScene(Scene *scene, bool firstTime);
+
+public:
+ void takeObj(Obj *obj);
+
+ bool handleMoveCommand(Directions dir, const char *dirName);
+ bool handleLookCommand();
+ Common::String *getGroundItemsList(Scene *scene);
+ void appendObjNames(Common::String &str, const ObjArray &objs);
+ bool handleInventoryCommand();
+ bool handleStatusCommand();
+ bool handleRestCommand();
+ bool handleAcceptCommand();
+
+ bool handleTakeCommand(const char *target);
+ bool handleDropCommand(const char *target);
+ bool handleAimCommand(const char *target);
+ bool handleWearCommand(const char *target);
+ bool handleOfferCommand(const char *target);
+
+ void wearObj(Obj *o, int pos);
+
+ bool tryAttack(const Obj *weapon, const Common::String &input);
+ bool handleAttack(Obj *weapon);
+
+ void printPlayerCondition(Chr *player);
+ const char *getPercentMessage(double percent);
+
+public:
+ Common::RandomSource *_rnd;
+
+ Debugger *_debugger;
+
+ Gui *_gui;
+ World *_world;
+
+ Scene *_lastScene;
+ int _loopCount;
+ int _turn;
+ Chr *_monster;
+ Chr *_running;
+ Obj *_offer;
+ int _aim;
+ int _opponentAim;
+ bool _temporarilyHidden;
+ bool _isGameOver;
+ bool _commandWasQuick;
+
+ Common::String _inputText;
+
+ void playSound(Common::String soundName);
+ void setMenu(Common::String soundName);
+ void appendText(const char *str);
+ void gameOver();
+ bool saveDialog();
+ Obj *getOffer();
+ Chr *getMonster();
+ void processEvents();
+ Scene *getSceneByName(Common::String &location);
+ void onMove(Designed *what, Designed *from, Designed *to);
+ void encounter(Chr *player, Chr *chr);
+ void redrawScene();
+ void saveGame();
+
+ virtual GUI::Debugger *getDebugger() { return _debugger; }
+
+private:
+ Console *_console;
+
+ const ADGameDescription *_gameDescription;
+
+ Common::MacResManager *_resManager;
+
+ bool _shouldQuit;
+};
+
+// Example console class
+class Console : public GUI::Debugger {
+public:
+ Console(WageEngine *vm) {}
+ virtual ~Console(void) {}
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp
new file mode 100644
index 0000000000..40b1555e35
--- /dev/null
+++ b/engines/wage/world.cpp
@@ -0,0 +1,523 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common/file.h"
+
+#include "wage/wage.h"
+#include "wage/entities.h"
+#include "wage/script.h"
+#include "wage/sound.h"
+#include "wage/world.h"
+
+namespace Wage {
+
+World::World(WageEngine *engine) {
+ _storageScene = new Scene;
+ _storageScene->_name = STORAGESCENE;
+
+ _orderedScenes.push_back(_storageScene);
+ _scenes[STORAGESCENE] = _storageScene;
+
+ _gameOverMessage = nullptr;
+ _saveBeforeQuitMessage = nullptr;
+ _saveBeforeCloseMessage = nullptr;
+ _revertMessage = nullptr;
+
+ _globalScript = nullptr;
+ _player = nullptr;
+
+ _weaponMenuDisabled = true;
+
+ _engine = engine;
+}
+
+World::~World() {
+ for (uint i = 0; i < _orderedObjs.size(); i++)
+ delete _orderedObjs[i];
+
+ for (uint i = 0; i < _orderedChrs.size(); i++)
+ delete _orderedChrs[i];
+
+ for (uint i = 0; i < _orderedSounds.size(); i++)
+ delete _orderedSounds[i];
+
+ for (uint i = 0; i < _orderedScenes.size(); i++)
+ delete _orderedScenes[i];
+
+ for (uint i = 0; i < _patterns.size(); i++)
+ free(_patterns[i]);
+
+ delete _globalScript;
+
+ delete _gameOverMessage;
+ delete _saveBeforeQuitMessage;
+ delete _saveBeforeCloseMessage;
+ delete _revertMessage;
+
+}
+
+bool World::loadWorld(Common::MacResManager *resMan) {
+ Common::MacResIDArray resArray;
+ Common::SeekableReadStream *res;
+ Common::MacResIDArray::const_iterator iter;
+
+ if ((resArray = resMan->getResIDArray(MKTAG('G','C','O','D'))).size() == 0)
+ return false;
+
+ // Load global script
+ res = resMan->getResource(MKTAG('G','C','O','D'), resArray[0]);
+ _globalScript = new Script(res);
+
+ // TODO: read creator
+
+ // Load main configuration
+ if ((resArray = resMan->getResIDArray(MKTAG('V','E','R','S'))).size() == 0)
+ return false;
+
+ _name = resMan->getBaseFileName();
+
+ if (resArray.size() > 1)
+ warning("Too many VERS resources");
+
+ if (!resArray.empty()) {
+ debug(3, "Loading version info");
+
+ res = resMan->getResource(MKTAG('V','E','R','S'), resArray[0]);
+
+ res->skip(10);
+ byte b = res->readByte();
+ _weaponMenuDisabled = (b != 0);
+ if (b != 0 && b != 1)
+ error("Unexpected value for weapons menu");
+
+ res->skip(3);
+ _aboutMessage = readPascalString(res);
+
+ if (!scumm_stricmp(resMan->getBaseFileName().c_str(), "Scepters"))
+ res->skip(1); // ????
+
+ _soundLibrary1 = readPascalString(res);
+ _soundLibrary2 = readPascalString(res);
+
+ delete res;
+ }
+
+ Common::String *message;
+ if ((message = loadStringFromDITL(resMan, 2910, 1)) != NULL) {
+ message->trim();
+ debug(2, "_gameOverMessage: %s", message->c_str());
+ _gameOverMessage = message;
+ }
+ if ((message = loadStringFromDITL(resMan, 2480, 3)) != NULL) {
+ message->trim();
+ debug(2, "_saveBeforeQuitMessage: %s", message->c_str());
+ _saveBeforeQuitMessage = message;
+ }
+ if ((message = loadStringFromDITL(resMan, 2490, 3)) != NULL) {
+ message->trim();
+ debug(2, "_saveBeforeCloseMessage: %s", message->c_str());
+ _saveBeforeCloseMessage = message;
+ }
+ if ((message = loadStringFromDITL(resMan, 2940, 2)) != NULL) {
+ message->trim();
+ debug(2, "_revertMessage: %s", message->c_str());
+ _revertMessage = message;
+ }
+
+ // Load scenes
+ resArray = resMan->getResIDArray(MKTAG('A','S','C','N'));
+ debug(3, "Loading %d scenes", resArray.size());
+
+ for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
+ res = resMan->getResource(MKTAG('A','S','C','N'), *iter);
+ Scene *scene = new Scene(resMan->getResName(MKTAG('A','S','C','N'), *iter), res);
+
+ res = resMan->getResource(MKTAG('A','C','O','D'), *iter);
+ if (res != NULL)
+ scene->_script = new Script(res);
+
+ res = resMan->getResource(MKTAG('A','T','X','T'), *iter);
+ if (res != NULL) {
+ scene->_textBounds = readRect(res);
+ scene->_fontType = res->readUint16BE();
+ scene->_fontSize = res->readUint16BE();
+
+ Common::String text;
+ while (res->pos() < res->size()) {
+ char c = res->readByte();
+ if (c == 0x0d)
+ c = '\n';
+ text += c;
+ }
+ scene->_text = text;
+
+ delete res;
+ }
+ addScene(scene);
+ }
+
+ // Load Objects
+ resArray = resMan->getResIDArray(MKTAG('A','O','B','J'));
+ debug(3, "Loading %d objects", resArray.size());
+
+ for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
+ res = resMan->getResource(MKTAG('A','O','B','J'), *iter);
+ addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res));
+ }
+
+ // Load Characters
+ resArray = resMan->getResIDArray(MKTAG('A','C','H','R'));
+ debug(3, "Loading %d characters", resArray.size());
+
+ for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
+ res = resMan->getResource(MKTAG('A','C','H','R'), *iter);
+ Chr *chr = new Chr(resMan->getResName(MKTAG('A','C','H','R'), *iter), res);
+
+ addChr(chr);
+ // TODO: What if there's more than one player character?
+ if (chr->_playerCharacter)
+ _player = chr;
+ }
+
+ // Load Sounds
+ resArray = resMan->getResIDArray(MKTAG('A','S','N','D'));
+ debug(3, "Loading %d sounds", resArray.size());
+
+ for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
+ res = resMan->getResource(MKTAG('A','S','N','D'), *iter);
+ addSound(new Sound(resMan->getResName(MKTAG('A','S','N','D'), *iter), res));
+ }
+
+ if (!_soundLibrary1.empty()) {
+ loadExternalSounds(_soundLibrary1);
+ }
+ if (!_soundLibrary2.empty()) {
+ loadExternalSounds(_soundLibrary2);
+ }
+
+ // Load Patterns
+ res = resMan->getResource(MKTAG('P','A','T','#'), 900);
+ if (res != NULL) {
+ int count = res->readUint16BE();
+ debug(3, "Loading %d patterns", count);
+
+ for (int i = 0; i < count; i++) {
+ byte *pattern = (byte *)malloc(8);
+
+ res->read(pattern, 8);
+ _patterns.push_back(pattern);
+ }
+
+ delete res;
+ } else {
+ /* Enchanted Scepters did not use the PAT# resource for the textures. */
+ res = resMan->getResource(MKTAG('C','O','D','E'), 1);
+ if (res != NULL) {
+ res->skip(0x55ac);
+ for (int i = 0; i < 29; i++) {
+ byte *pattern = (byte *)malloc(8);
+
+ res->read(pattern, 8);
+ _patterns.push_back(pattern);
+ }
+ }
+ delete res;
+ }
+
+ res = resMan->getResource(MKTAG('M','E','N','U'), 2001);
+ if (res != NULL) {
+ Common::StringArray *menu = readMenu(res);
+ _aboutMenuItemName.clear();
+ Common::String string = menu->operator[](1);
+
+ for (uint i = 0; i < string.size() && string[i] != ';'; i++) // Read token
+ _aboutMenuItemName += string[i];
+
+ delete menu;
+ delete res;
+ }
+ res = resMan->getResource(MKTAG('M','E','N','U'), 2004);
+ if (res != NULL) {
+ Common::StringArray *menu = readMenu(res);
+ _commandsMenuName = menu->operator[](0);
+ _commandsMenu = menu->operator[](1);
+ delete menu;
+ delete res;
+ }
+ res = resMan->getResource(MKTAG('M','E','N','U'), 2005);
+ if (res != NULL) {
+ Common::StringArray *menu = readMenu(res);
+ _weaponsMenuName = menu->operator[](0);
+ delete menu;
+ delete res;
+ }
+ // TODO: Read Apple menu and get the name of that menu item..
+
+ // store global info in state object for use with save/load actions
+ //world.setCurrentState(initialState); // pass off the state object to the world
+
+ return true;
+}
+
+void World::addSound(Sound *sound) {
+ Common::String s = sound->_name;
+ s.toLowercase();
+ _sounds[s] = sound;
+ _orderedSounds.push_back(sound);
+}
+
+Common::StringArray *World::readMenu(Common::SeekableReadStream *res) {
+ res->skip(10);
+ int enableFlags = res->readUint32BE();
+ Common::String menuName = readPascalString(res);
+ Common::String menuItem = readPascalString(res);
+ int menuItemNumber = 1;
+ Common::String menu;
+ byte itemData[4];
+
+ while (!menuItem.empty()) {
+ if (!menu.empty()) {
+ menu += ';';
+ }
+ if ((enableFlags & (1 << menuItemNumber)) == 0) {
+ menu += '(';
+ }
+ menu += menuItem;
+ res->read(itemData, 4);
+ static const char styles[] = {'B', 'I', 'U', 'O', 'S', 'C', 'E', 0};
+ for (int i = 0; styles[i] != 0; i++) {
+ if ((itemData[3] & (1 << i)) != 0) {
+ menu += '<';
+ menu += styles[i];
+ }
+ }
+ if (itemData[1] != 0) {
+ menu += '/';
+ menu += (char)itemData[1];
+ }
+ menuItem = readPascalString(res);
+ menuItemNumber++;
+ }
+
+ Common::StringArray *result = new Common::StringArray;
+ result->push_back(menuName);
+ result->push_back(menu);
+
+ debug(4, "menuName: %s", menuName.c_str());
+ debug(4, "menu: %s", menu.c_str());
+
+ return result;
+}
+
+void World::loadExternalSounds(Common::String fname) {
+ Common::File in;
+
+ in.open(fname);
+ if (!in.isOpen()) {
+ warning("Cannot load sound file <%s>", fname.c_str());
+ return;
+ }
+ in.close();
+
+ Common::MacResManager resMan;
+ resMan.open(fname);
+
+ Common::MacResIDArray resArray;
+ Common::SeekableReadStream *res;
+ Common::MacResIDArray::const_iterator iter;
+
+ resArray = resMan.getResIDArray(MKTAG('A','S','N','D'));
+ for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
+ res = resMan.getResource(MKTAG('A','S','N','D'), *iter);
+ addSound(new Sound(resMan.getResName(MKTAG('A','S','N','D'), *iter), res));
+ }
+}
+
+Common::String *World::loadStringFromDITL(Common::MacResManager *resMan, int resourceId, int itemIndex) {
+ Common::SeekableReadStream *res = resMan->getResource(MKTAG('D','I','T','L'), resourceId);
+ if (res) {
+ int itemCount = res->readSint16BE();
+ for (int i = 0; i <= itemCount; i++) {
+ // int placeholder; short rect[4]; byte flags; pstring str;
+ res->skip(13);
+ Common::String message = readPascalString(res);
+ if (i == itemIndex) {
+ Common::String *msg = new Common::String(message);
+ delete res;
+ return msg;
+ }
+ }
+
+ delete res;
+ }
+
+ return NULL;
+}
+
+static bool invComparator(const Obj *l, const Obj *r) {
+ return l->_index < r->_index;
+}
+
+void World::move(Obj *obj, Chr *chr) {
+ if (obj == NULL)
+ return;
+
+ Designed *from = obj->removeFromCharOrScene();
+ obj->_currentOwner = chr;
+ chr->_inventory.push_back(obj);
+
+ Common::sort(chr->_inventory.begin(), chr->_inventory.end(), invComparator);
+
+ _engine->onMove(obj, from, chr);
+}
+
+static bool objComparator(const Obj *o1, const Obj *o2) {
+ bool o1Immobile = (o1->_type == Obj::IMMOBILE_OBJECT);
+ bool o2Immobile = (o2->_type == Obj::IMMOBILE_OBJECT);
+ if (o1Immobile == o2Immobile) {
+ return o1->_index - o2->_index;
+ }
+ return o1Immobile;
+}
+
+void World::move(Obj *obj, Scene *scene, bool skipSort) {
+ if (obj == NULL)
+ return;
+
+ Designed *from = obj->removeFromCharOrScene();
+ obj->_currentScene = scene;
+ scene->_objs.push_back(obj);
+
+ if (!skipSort)
+ Common::sort(scene->_objs.begin(), scene->_objs.end(), objComparator);
+
+ _engine->onMove(obj, from, scene);
+}
+
+static bool chrComparator(const Chr *l, const Chr *r) {
+ return l->_index < r->_index;
+}
+
+void World::move(Chr *chr, Scene *scene, bool skipSort) {
+ if (chr == NULL)
+ return;
+ Scene *from = chr->_currentScene;
+ if (from == scene)
+ return;
+ if (from != NULL)
+ from->_chrs.remove(chr);
+ scene->_chrs.push_back(chr);
+
+ if (!skipSort)
+ Common::sort(scene->_chrs.begin(), scene->_chrs.end(), chrComparator);
+
+ if (scene == _storageScene) {
+ chr->resetState();
+ } else if (chr->_playerCharacter) {
+ scene->_visited = true;
+ _player->_context._visits++;
+ }
+ chr->_currentScene = scene;
+
+ _engine->onMove(chr, from, scene);
+}
+
+Scene *World::getRandomScene() {
+ // Not including storage:
+ return _orderedScenes[1 + _engine->_rnd->getRandomNumber(_orderedScenes.size() - 2)];
+}
+
+Scene *World::getSceneAt(int x, int y) {
+ for (uint i = 0; i < _orderedScenes.size(); i++) {
+ Scene *scene = _orderedScenes[i];
+
+ if (scene != _storageScene && scene->_worldX == x && scene->_worldY == y) {
+ return scene;
+ }
+ }
+ return NULL;
+}
+
+static const int directionsX[] = { 0, 0, 1, -1 };
+static const int directionsY[] = { -1, 1, 0, 0 };
+
+bool World::scenesAreConnected(Scene *scene1, Scene *scene2) {
+ if (!scene1 || !scene2)
+ return false;
+
+ int x = scene2->_worldX;
+ int y = scene2->_worldY;
+
+ for (int dir = 0; dir < 4; dir++)
+ if (!scene2->_blocked[dir])
+ if (getSceneAt(x + directionsX[dir], y + directionsY[dir]) == scene1)
+ return true;
+
+ return false;
+}
+
+const char *World::getAboutMenuItemName() {
+ static char menu[256];
+
+ *menu = '\0';
+
+ if (_aboutMenuItemName.empty()) {
+ sprintf(menu, "About %s...", _name.c_str());
+ } else { // Replace '@' with name
+ const char *str = _aboutMenuItemName.c_str();
+ const char *pos = strchr(str, '@');
+ if (pos) {
+ strncat(menu, str, (pos - str));
+ strncat(menu, _name.c_str(), 255);
+ strncat(menu, pos + 1, 255);
+ }
+ }
+
+ return menu;
+}
+
+} // End of namespace Wage
diff --git a/engines/wage/world.h b/engines/wage/world.h
new file mode 100644
index 0000000000..e9041139df
--- /dev/null
+++ b/engines/wage/world.h
@@ -0,0 +1,138 @@
+/* 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.
+ *
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef WAGE_WORLD_H
+#define WAGE_WORLD_H
+
+namespace Wage {
+
+#define STORAGESCENE "STORAGE@"
+
+class Sound;
+
+class World {
+public:
+ World(WageEngine *engine);
+ ~World();
+
+ bool loadWorld(Common::MacResManager *resMan);
+ void loadExternalSounds(Common::String fname);
+ Common::String *loadStringFromDITL(Common::MacResManager *resMan, int resourceId, int itemIndex);
+ void move(Obj *obj, Chr *chr);
+ void move(Obj *obj, Scene *scene, bool skipSort = false);
+ void move(Chr *chr, Scene *scene, bool skipSort = false);
+ Scene *getRandomScene();
+ Scene *getSceneAt(int x, int y);
+ bool scenesAreConnected(Scene *scene1, Scene *scene2);
+ const char *getAboutMenuItemName();
+
+ WageEngine *_engine;
+
+ Common::String _name;
+ Common::String _aboutMessage;
+ Common::String _soundLibrary1;
+ Common::String _soundLibrary2;
+
+ bool _weaponMenuDisabled;
+ Script *_globalScript;
+ Common::HashMap<Common::String, Scene *> _scenes;
+ Common::HashMap<Common::String, Obj *> _objs;
+ Common::HashMap<Common::String, Chr *> _chrs;
+ Common::HashMap<Common::String, Sound *> _sounds;
+ Common::Array<Scene *> _orderedScenes;
+ ObjArray _orderedObjs;
+ ChrArray _orderedChrs;
+ Common::Array<Sound *> _orderedSounds;
+ Patterns _patterns;
+ Scene *_storageScene;
+ Chr *_player;
+ //List<MoveListener> moveListeners;
+
+ Common::String *_gameOverMessage;
+ Common::String *_saveBeforeQuitMessage;
+ Common::String *_saveBeforeCloseMessage;
+ Common::String *_revertMessage;
+
+ Common::String _aboutMenuItemName;
+ Common::String _commandsMenuName;
+ Common::String _commandsMenu;
+ Common::String _weaponsMenuName;
+
+ void addScene(Scene *room) {
+ if (!room->_name.empty()) {
+ Common::String s = room->_name;
+ s.toLowercase();
+ _scenes[s] = room;
+ }
+ _orderedScenes.push_back(room);
+ }
+
+ void addObj(Obj *obj) {
+ Common::String s = obj->_name;
+ s.toLowercase();
+ _objs[s] = obj;
+ obj->_index = _orderedObjs.size();
+ _orderedObjs.push_back(obj);
+ }
+
+ void addChr(Chr *chr) {
+ Common::String s = chr->_name;
+ s.toLowercase();
+ _chrs[s] = chr;
+ chr->_index = _orderedChrs.size();
+ _orderedChrs.push_back(chr);
+ }
+
+ void addSound(Sound *sound);
+
+private:
+ Common::StringArray *readMenu(Common::SeekableReadStream *res);
+};
+
+} // End of namespace Wage
+
+#endif
diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp
index 9d5a35464a..4661d3bca0 100644
--- a/engines/wintermute/ad/ad_actor.cpp
+++ b/engines/wintermute/ad/ad_actor.cpp
@@ -958,13 +958,13 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
stack->correctParams(1);
ScValue *val = stack->pop();
if (!val->isNative()) {
- script->runtimeError("actor.%s method accepts an entity refrence only", name);
+ script->runtimeError("actor.%s method accepts an entity reference only", name);
stack->pushNULL();
return STATUS_OK;
}
AdObject *obj = (AdObject *)val->getNative();
if (!obj || obj->getType() != OBJECT_ENTITY) {
- script->runtimeError("actor.%s method accepts an entity refrence only", name);
+ script->runtimeError("actor.%s method accepts an entity reference only", name);
stack->pushNULL();
return STATUS_OK;
}
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index 0f4a6b0775..cbf5d92d00 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -74,7 +74,7 @@ public:
static const Timer *getTimer();
static const Timer *getLiveTimer();
static void LOG(bool res, const char *fmt, ...);
- const char *getGameTargetName() const { return _targetName.c_str(); }
+ Common::String getGameTargetName() const { return _targetName; }
Common::String getGameId() const { return _gameId; }
Common::Language getLanguage() const { return _language; }
WMETargetExecutable getTargetExecutable() const {
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index bb5e0c4091..39462f7a15 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -56,7 +56,7 @@ namespace Wintermute {
#define SAVE_MAGIC_3 0x12564154
//////////////////////////////////////////////////////////////////////////
-BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool deleteSingleton) {
+BasePersistenceManager::BasePersistenceManager(const Common::String &savePrefix, bool deleteSingleton) {
_saving = false;
_offset = 0;
_saveStream = nullptr;
@@ -91,7 +91,7 @@ BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool dele
_thumbnailDataSize = 0;
_thumbnailData = nullptr;
- if (savePrefix) {
+ if (savePrefix != "") {
_savePrefix = savePrefix;
} else if (_gameRef) {
_savePrefix = _gameRef->getGameTargetName();
@@ -215,8 +215,8 @@ bool BasePersistenceManager::getSaveExists(int slot) {
}
//////////////////////////////////////////////////////////////////////////
-bool BasePersistenceManager::initSave(const char *desc) {
- if (!desc) {
+bool BasePersistenceManager::initSave(const Common::String &desc) {
+ if (desc == "") {
return STATUS_FAILED;
}
@@ -297,11 +297,11 @@ bool BasePersistenceManager::initSave(const char *desc) {
uint32 dataOffset = _offset +
sizeof(uint32) + // data offset
- sizeof(uint32) + strlen(desc) + 1 + // description
+ sizeof(uint32) + strlen(desc.c_str()) + 1 + // description
sizeof(uint32); // timestamp
putDWORD(dataOffset);
- putString(desc);
+ putString(desc.c_str());
g_system->getTimeAndDate(_savedTimestamp);
putTimeDate(_savedTimestamp);
diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h
index 373d1580de..760b45c907 100644
--- a/engines/wintermute/base/base_persistence_manager.h
+++ b/engines/wintermute/base/base_persistence_manager.h
@@ -63,7 +63,7 @@ public:
uint32 getMaxUsedSlot();
bool getSaveExists(int slot);
bool initLoad(const Common::String &filename);
- bool initSave(const char *desc);
+ bool initSave(const Common::String &desc);
bool getBytes(byte *buffer, uint32 size);
bool putBytes(byte *buffer, uint32 size);
uint32 _offset;
@@ -86,7 +86,7 @@ public:
bool transferCharPtr(const char *name, char **val);
bool transferString(const char *name, Common::String *val);
bool transferVector2(const char *name, Vector2 *val);
- BasePersistenceManager(const char *savePrefix = nullptr, bool deleteSingleton = false);
+ BasePersistenceManager(const Common::String &savePrefix = "", bool deleteSingleton = false);
virtual ~BasePersistenceManager();
bool checkVersion(byte verMajor, byte verMinor, byte verBuild);
diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp
index 4388942064..6d0c48ff17 100644
--- a/engines/wintermute/base/base_sub_frame.cpp
+++ b/engines/wintermute/base/base_sub_frame.cpp
@@ -268,7 +268,7 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl
Common::Point origin(x, y);
Common::Point newOrigin;
Rect32 oldRect1 = getRect();
- Common::Rect oldRect(oldRect1.top, oldRect1.left, oldRect1.bottom, oldRect1.right);
+ Common::Rect oldRect(oldRect1.left, oldRect1.top, oldRect1.right, oldRect1.bottom);
Common::Point newHotspot;
Graphics::TransformStruct transform = Graphics::TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0);
Rect32 newRect = Graphics::TransformTools::newRect(oldRect, transform, &newHotspot);
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
index 82a9e24dfb..d0c51616f4 100644
--- a/engines/wintermute/base/file/base_disk_file.cpp
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -113,13 +113,28 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
Common::String fixedFilename = filename;
correctSlashes(fixedFilename);
- // Absolute path: TODO: Add specific fallbacks here.
+ // HACK: There are a few games around which mistakenly refer to absolute paths in the scripts.
+ // The original interpreter on Windows usually simply ignores them when it can't find them.
+ // We try to turn the known ones into relative paths.
if (fixedFilename.contains(':')) {
- if (fixedFilename.hasPrefix("c:/windows/fonts/")) { // East Side Story refers to "c:\windows\fonts\framd.ttf"
- fixedFilename = filename.c_str() + 14;
- } else if (fixedFilename.hasPrefix("c:/carol6/svn/data/")) { // Carol Reed 6: Black Circle refers to "c:\carol6\svn\data\sprites\system\help.png"
- fixedFilename = fixedFilename.c_str() + 19;
- } else {
+ const char* const knownPrefixes[] = { // Known absolute paths
+ "c:/windows/fonts/", // East Side Story refers to "c:\windows\fonts\framd.ttf"
+ "c:/carol6/svn/data/", // Carol Reed 6: Black Circle refers to "c:\carol6\svn\data\sprites\system\help.png"
+ "f:/dokument/spel 5/demo/data/" // Carol Reed 5 (non-demo) refers to "f:\dokument\spel 5\demo\data\scenes\credits\op_cred_00\op_cred_00.jpg"
+ };
+
+ bool matched = false;
+
+ for (uint i = 0; i < ARRAYSIZE(knownPrefixes); i++) {
+ if (fixedFilename.hasPrefix(knownPrefixes[i])) {
+ fixedFilename = fixedFilename.c_str() + strlen(knownPrefixes[i]);
+ matched = true;
+ }
+ }
+
+ if (!matched) {
+ // fixedFilename is unchanged and thus still broken, none of the above workarounds worked.
+ // We can only bail out
error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str());
}
}
diff --git a/engines/wintermute/configure.engine b/engines/wintermute/configure.engine
index bdaf49de3f..55385776de 100644
--- a/engines/wintermute/configure.engine
+++ b/engines/wintermute/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 wintermute "Wintermute" yes "" "" "jpeg png zlib vorbis 16bit"
+add_engine wintermute "Wintermute" yes "" "" "jpeg png zlib vorbis 16bit highres"
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index aca682ae99..f77eb5c64d 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -75,8 +75,8 @@ static const char *directoryGlobs[] = {
class WintermuteMetaEngine : public AdvancedMetaEngine {
public:
WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(WMEGameDescription), Wintermute::wintermuteGames, gameGuiOptions) {
- _singleid = "wintermute";
- _guioptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS);
+ _singleId = "wintermute";
+ _guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS);
_maxScanDepth = 2;
_directoryGlobs = directoryGlobs;
}
@@ -94,8 +94,8 @@ public:
s_fallbackDesc.language = Common::UNK_LANG;
s_fallbackDesc.flags = ADGF_UNSTABLE;
s_fallbackDesc.platform = Common::kPlatformWindows; // default to Windows
- s_fallbackDesc.gameid = "wintermute";
- s_fallbackDesc.guioptions = GUIO0();
+ s_fallbackDesc.gameId = "wintermute";
+ s_fallbackDesc.guiOptions = GUIO0();
if (allFiles.contains("data.dcp")) {
Common::String name, caption;
@@ -109,7 +109,7 @@ public:
// Prefix to avoid collisions with actually known games
name = "wmeunk-" + name;
Common::strlcpy(s_fallbackGameIdBuf, name.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
- s_fallbackDesc.gameid = s_fallbackGameIdBuf;
+ s_fallbackDesc.gameId = s_fallbackGameIdBuf;
if (caption != name) {
caption += " (unknown version) ";
char *offset = s_fallbackGameIdBuf + name.size() + 1;
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 25a01766e4..ca30204462 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -181,10 +181,13 @@ static const WMEGameDescription gameDescriptions[] = {
WME_ENTRY1s("data.dcp", "b3f8b09bb4b05ee3e9d14697525257f9", 59296246), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Carol Reed 4 - East Side Story
WME_WINENTRY("carolreed4", "",
- WME_ENTRY1s("data.dcp", "b26377797f060afc2d440d820100c1ce", 529320536), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
+ WME_ENTRY1s("data.dcp", "b26377797f060afc2d440d820100c1ce", 529320536), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Carol Reed 5 - The Colour of Murder
WME_WINENTRY("carolreed5", "",
WME_ENTRY1s("data.dcp", "3fcfca44209545d0e26774156427b494", 603660415), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ // Carol Reed 5 - The Colour of Murder (1.0 Demo)
+ WME_WINENTRY("carolreed5", "Demo",
+ WME_ENTRY1s("data.dcp", "27b3efc018ade5ee8f4adf08b4e3c0dd", 92019500), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
// Carol Reed 6 - Black Circle
WME_WINENTRY("carolreed6", "",
WME_ENTRY1s("data.dcp", "0e4c532beecf23d85012168753f41189", 456258147), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index e35bb60c3d..955f2dc1c2 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -133,7 +133,7 @@ Common::Error WintermuteEngine::run() {
}
int WintermuteEngine::init() {
- BaseEngine::createInstance(_targetName, _gameDescription->adDesc.gameid, _gameDescription->adDesc.language, _gameDescription->targetExecutable);
+ BaseEngine::createInstance(_targetName, _gameDescription->adDesc.gameId, _gameDescription->adDesc.language, _gameDescription->targetExecutable);
_game = new AdGame(_targetName);
if (!_game) {
return 1;
diff --git a/engines/zvision/configure.engine b/engines/zvision/configure.engine
index 226870c3fd..8681522a35 100644
--- a/engines/zvision/configure.engine
+++ b/engines/zvision/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 zvision "Z-Vision" yes "" "" "freetype2 16bit"
+add_engine zvision "Z-Vision" yes "" "" "freetype2 16bit highres"
diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp
index 5fdf17cd2b..cc967070d9 100644
--- a/engines/zvision/detection.cpp
+++ b/engines/zvision/detection.cpp
@@ -61,7 +61,7 @@ public:
ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), ZVision::zVisionGames, ZVision::optionsList) {
_maxScanDepth = 2;
_directoryGlobs = ZVision::directoryGlobs;
- _singleid = "zvision";
+ _singleId = "zvision";
}
virtual const char *getName() const {
@@ -132,7 +132,6 @@ SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
- Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
SaveStateList saveList;
// We only use readSaveGameHeader() here, which doesn't need an engine callback
@@ -155,6 +154,8 @@ SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
delete zvisionSaveMan;
+ // Sort saves based on slot number.
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -164,26 +165,7 @@ int ZVisionMetaEngine::getMaximumSaveSlot() const {
void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::String filename = Common::String::format("%s.%03u", target, slot);
-
- saveFileMan->removeSavefile(filename.c_str());
-
- Common::StringArray filenames;
- Common::String pattern = target;
- pattern += ".###";
- filenames = saveFileMan->listSavefiles(pattern.c_str());
- 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 = Common::String::format("%s.%03u", target, ++slot);
- }
- }
+ saveFileMan->removeSavefile(Common::String::format("%s.%03u", target, slot));
}
SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 81a0c04441..26f0ced625 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -441,13 +441,14 @@ template<typename PixelType>
void VectorRendererSpec<PixelType>::
gradientFill(PixelType *ptr, int width, int x, int y) {
bool ox = ((y & 1) == 1);
- int stripSize;
int curGrad = 0;
while (_gradIndexes[curGrad + 1] <= y)
curGrad++;
- stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
+ // precalcGradient assures that _gradIndexes entries always differ in
+ // their value. This assures stripSize is always different from zero.
+ int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
@@ -773,8 +774,8 @@ drawLine(int x1, int y1, int x2, int y2) {
SWAP(y1, y2);
}
- int dx = ABS(x2 - x1);
- int dy = ABS(y2 - y1);
+ uint dx = ABS(x2 - x1);
+ uint dy = ABS(y2 - y1);
// this is a point, not a line. stoopid.
if (dy == 0 && dx == 0)
@@ -803,7 +804,7 @@ drawLine(int x1, int y1, int x2, int y2) {
ptr += pitch;
}
- } else if (ABS(dx) == ABS(dy)) { // diagonal lines
+ } else if (dx == dy) { // diagonal lines
// these ones also use a fixed pitch increase
pitch += (x2 > x1) ? 1 : -1;
@@ -1034,6 +1035,11 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
+ // Don't draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
@@ -1238,6 +1244,11 @@ drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, Pixe
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int max_h = h;
@@ -1326,7 +1337,7 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P
/** GENERIC LINE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
+drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int xdir = (x2 > x1) ? 1 : -1;
@@ -1393,6 +1404,12 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Don't draw anything for empty rects. This assures dy is always different
+ // from zero.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int gradient_h = 0;
if (!inverted) {
@@ -1422,6 +1439,9 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
blendPixelPtr(floor, color, 50);
#if FIXED_POINT
+ // In this branch dx is always different from zero. This is because
+ // abs(dx) is strictly greater than abs(dy), and abs returns zero
+ // as minimal value.
int gradient = (dy << 8) / dx;
int intery = (y1 << 8) + gradient;
#else
@@ -1564,6 +1584,11 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw anything for empty rects.
+ if (size <= 0) {
+ return;
+ }
+
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
if (!inverted) {
@@ -1685,6 +1710,11 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw empty space rounded squares.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
@@ -1835,6 +1865,11 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawSquareShadow(int x, int y, int w, int h, int offset) {
+ // Do nothing for empty rects or no shadow offset.
+ if (w <= 0 || h <= 0 || offset <= 0) {
+ return;
+ }
+
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;
@@ -1956,8 +1991,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
/** LINES **/
template<typename PixelType>
void VectorRendererAA<PixelType>::
-drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
-
+drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int xdir = (x2 > x1) ? 1 : -1;
@@ -1967,7 +2001,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
*ptr = (PixelType)color;
if (dx > dy) {
- gradient = (uint32)(dy << 16) / (uint32)dx;
+ gradient = (dy << 16) / dx;
error_acc = 0;
while (--dx) {
@@ -1983,8 +2017,8 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
this->blendPixelPtr(ptr, color, ~alpha);
this->blendPixelPtr(ptr + pitch, color, alpha);
}
- } else {
- gradient = (uint32)(dx << 16) / (uint32)dy;
+ } else if (dy != 0) {
+ gradient = (dx << 16) / dy;
error_acc = 0;
while (--dy) {
@@ -2009,6 +2043,11 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
template<typename PixelType>
void VectorRendererAA<PixelType>::
drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
+ // Don't draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int x, y, px, py;
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int sw = 0, sp = 0, hp = 0;
@@ -2217,6 +2256,11 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
template<typename PixelType>
void VectorRendererAA<PixelType>::
drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw empty space rounded squares.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int x, y;
const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int px, py;
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index f47cc3997a..3e54608b8e 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -150,7 +150,7 @@ protected:
* @see VectorRendererAA::drawCircleAlg
*/
virtual void drawLineAlg(int x1, int y1, int x2, int y2,
- int dx, int dy, PixelType color);
+ uint dx, uint dy, PixelType color);
virtual void drawCircleAlg(int x, int y, int r,
PixelType color, FillMode fill_m);
@@ -278,7 +278,7 @@ protected:
*
* @see VectorRenderer::drawLineAlg()
*/
- virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color);
+ virtual void drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color);
/**
* "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991
diff --git a/graphics/font.cpp b/graphics/font.cpp
index dba48249bc..d709758948 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -21,6 +21,7 @@
*/
#include "graphics/font.h"
+#include "graphics/managed_surface.h"
#include "common/array.h"
#include "common/util.h"
@@ -273,6 +274,16 @@ void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y,
drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
}
+void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax, useEllipsis);
+ dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
+}
+
+void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align) const {
+ drawString(&dst->_innerSurface, str, x, y, w, color, align);
+ dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
+}
+
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
return wordWrapTextImpl(*this, str, maxWidth, lines);
}
diff --git a/graphics/font.h b/graphics/font.h
index 35f6792d7f..62e71a8568 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -34,6 +34,7 @@ template<class T> class Array;
namespace Graphics {
struct Surface;
+class ManagedSurface;
/** Text alignment modes */
enum TextAlign {
@@ -145,6 +146,8 @@ public:
// TODO: Add doxygen comments to this
void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
+ void drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+ void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
/**
* Compute and return the width the string str has when rendered using this font.
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
new file mode 100644
index 0000000000..e493ab9f4e
--- /dev/null
+++ b/graphics/managed_surface.cpp
@@ -0,0 +1,260 @@
+/* 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 "graphics/managed_surface.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Graphics {
+
+const int SCALE_THRESHOLD = 0x100;
+
+ManagedSurface::ManagedSurface() :
+ w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+ _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
+}
+
+ManagedSurface::ManagedSurface(const ManagedSurface &surf) :
+ w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+ _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
+ *this = surf;
+}
+
+ManagedSurface::ManagedSurface(int width, int height) :
+ w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+ _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
+ create(width, height);
+}
+
+ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) :
+ w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+ _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
+ create(width, height, format);
+}
+
+ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) :
+ w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+ _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
+ create(surf, bounds);
+}
+
+ManagedSurface::~ManagedSurface() {
+ free();
+}
+
+ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) {
+ // Free any current surface
+ free();
+
+ if (surf._disposeAfterUse == DisposeAfterUse::YES) {
+ // Create a new surface and copy the pixels from the source surface
+ create(surf.w, surf.h, surf.format);
+ Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() +
+ surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels());
+ } else {
+ // Source isn't managed, so simply copy its fields
+ _owner = surf._owner;
+ _offsetFromOwner = surf._offsetFromOwner;
+ void *srcPixels = (void *)surf._innerSurface.getPixels();
+ _innerSurface.setPixels(srcPixels);
+ _innerSurface.w = surf.w;
+ _innerSurface.h = surf.h;
+ _innerSurface.pitch = surf.pitch;
+ this->format = surf.format;
+ }
+
+ return *this;
+}
+
+void ManagedSurface::setPixels(void *newPixels) {
+ free();
+ _innerSurface.setPixels(newPixels);
+}
+
+void ManagedSurface::create(uint16 width, uint16 height) {
+ create(width, height, PixelFormat::createFormatCLUT8());
+}
+
+void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixelFormat) {
+ free();
+ _innerSurface.create(width, height, pixelFormat);
+
+ _disposeAfterUse = DisposeAfterUse::YES;
+ markAllDirty();
+}
+
+void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) {
+ free();
+
+ _offsetFromOwner = Common::Point(bounds.left, bounds.top);
+ _innerSurface.setPixels(surf.getBasePtr(bounds.left, bounds.top));
+ _innerSurface.pitch = surf.pitch;
+ _innerSurface.format = surf.format;
+ _innerSurface.w = bounds.width();
+ _innerSurface.h = bounds.height();
+ _owner = &surf;
+ _disposeAfterUse = DisposeAfterUse::NO;
+}
+
+void ManagedSurface::free() {
+ if (_disposeAfterUse == DisposeAfterUse::YES)
+ _innerSurface.free();
+
+ _disposeAfterUse = DisposeAfterUse::NO;
+ _owner = nullptr;
+ _offsetFromOwner = Common::Point(0, 0);
+}
+
+bool ManagedSurface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
+ if (destBounds.left >= this->w || destBounds.top >= this->h ||
+ destBounds.right <= 0 || destBounds.bottom <= 0)
+ return false;
+
+ // Clip the bounds if necessary to fit on-screen
+ if (destBounds.right > this->w) {
+ srcBounds.right -= destBounds.right - this->w;
+ destBounds.right = this->w;
+ }
+
+ if (destBounds.bottom > this->h) {
+ srcBounds.bottom -= destBounds.bottom - this->h;
+ destBounds.bottom = this->h;
+ }
+
+ if (destBounds.top < 0) {
+ srcBounds.top += -destBounds.top;
+ destBounds.top = 0;
+ }
+
+ if (destBounds.left < 0) {
+ srcBounds.left += -destBounds.left;
+ destBounds.left = 0;
+ }
+
+ return true;
+}
+
+void ManagedSurface::blitFrom(const Surface &src) {
+ blitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Point(0, 0));
+}
+
+void ManagedSurface::blitFrom(const Surface &src, const Common::Point &destPos) {
+ blitFrom(src, Common::Rect(0, 0, src.w, src.h), destPos);
+}
+
+void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect,
+ const Common::Point &destPos) {
+ Common::Rect srcBounds = srcRect;
+ Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(),
+ destPos.y + srcRect.height());
+ assert(src.format.bytesPerPixel == format.bytesPerPixel);
+
+ if (!srcRect.isValidRect() || !clip(srcBounds, destBounds))
+ return;
+
+ for (int y = 0; y < srcBounds.height(); ++y) {
+ const byte *srcP = (const byte *)src.getBasePtr(srcBounds.left, srcBounds.top + y);
+ byte *destP = (byte *)getBasePtr(destBounds.left, destBounds.top + y);
+ Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP);
+ }
+
+ addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, uint transColor, bool flipped, uint overrideColor) {
+ transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(0, 0, this->w, this->h),
+ transColor, false, overrideColor);
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Point &destPos,
+ uint transColor, bool flipped, uint overrideColor) {
+ transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(destPos.x, destPos.y,
+ destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
+ const Common::Point &destPos, uint transColor, bool flipped, uint overrideColor) {
+ transBlitFrom(src, srcRect, Common::Rect(destPos.x, destPos.y,
+ destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
+}
+
+template<typename T>
+void transBlit(const Surface &src, const Common::Rect &srcRect, const Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
+ int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
+ int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
+
+ // Loop through drawing output lines
+ for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) {
+ if (destY < 0 || destY >= dest->h)
+ continue;
+ const T *srcLine = (const T *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
+ T *destLine = (T *)dest->getBasePtr(destRect.left, destY);
+
+ // Loop through drawing the pixels of the row
+ for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) {
+ if (destX < 0 || destX >= dest->w)
+ continue;
+
+ T srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD];
+ if (srcVal != transColor) {
+ destLine[xCtr] = overrideColor ? overrideColor : srcVal;
+ }
+ }
+ }
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
+ const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
+ if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0)
+ return;
+
+ if (format.bytesPerPixel == 1)
+ transBlit<byte>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+ else if (format.bytesPerPixel == 2)
+ transBlit<uint16>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+ else if (format.bytesPerPixel == 4)
+ transBlit<uint32>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+ else
+ error("Surface::transBlitFrom: bytesPerPixel must be 1, 2, or 4");
+
+ // Mark the affected area
+ addDirtyRect(destRect);
+}
+
+void ManagedSurface::markAllDirty() {
+ addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void ManagedSurface::addDirtyRect(const Common::Rect &r) {
+ if (_owner) {
+ Common::Rect bounds = r;
+ bounds.clip(Common::Rect(0, 0, this->w, this->h));
+ bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y);
+ _owner->addDirtyRect(bounds);
+ }
+}
+
+void ManagedSurface::clear(uint color) {
+ fillRect(getBounds(), color);
+}
+
+} // End of namespace Graphics
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
new file mode 100644
index 0000000000..bd0632a493
--- /dev/null
+++ b/graphics/managed_surface.h
@@ -0,0 +1,376 @@
+/* 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 GRAPHICS_MANAGED_SURFACE_H
+#define GRAPHICS_MANAGED_SURFACE_H
+
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "common/rect.h"
+#include "common/types.h"
+
+namespace Graphics {
+
+class Font;
+
+/**
+ * A derived graphics surface, which handles automatically managing the allocated
+ * surface data block, as well as introducing several new blitting methods
+ */
+class ManagedSurface {
+ friend class Font;
+private:
+ /**
+ * The Graphics::Surface that the managed surface encapsulates
+ */
+ Surface _innerSurface;
+
+ /**
+ * If set, the inner surface will be freed when the surface is recreated,
+ * as well as when the surface is destroyed
+ */
+ DisposeAfterUse::Flag _disposeAfterUse;
+
+ /**
+ * Stores the owning surface if this If this managed surface represents
+ * a sub-section of another
+ */
+ ManagedSurface *_owner;
+
+ /**
+ * For sub-section areas of an owning parent managed surface, this represents
+ * the offset from the parent's top-left corner this sub-surface starts at
+ */
+ Common::Point _offsetFromOwner;
+protected:
+ /**
+ * Clips the given source bounds so the passed destBounds will be entirely on-screen
+ */
+ bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
+
+ /**
+ * Base method that descendent classes can override for recording affected
+ * dirty areas of the surface
+ */
+ virtual void addDirtyRect(const Common::Rect &r);
+public:
+ uint16 &w;
+ uint16 &h;
+ uint16 &pitch;
+ PixelFormat &format;
+public:
+ /**
+ * Create the managed surface
+ */
+ ManagedSurface();
+
+ /**
+ * Create a managed surface from another one.
+ * If the source surface is maintaining it's own surface data, then
+ * this surface will create it's own surface of the same size and copy
+ * the contents from the source surface
+ */
+ ManagedSurface(const ManagedSurface &surf);
+
+ /**
+ * Create the managed surface
+ */
+ ManagedSurface(int width, int height);
+
+ /**
+ * Create the managed surface
+ */
+ ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat);
+
+ /**
+ * Create the managed surface
+ */
+ ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds);
+
+ /**
+ * Destroy the managed surface
+ */
+ virtual ~ManagedSurface();
+
+ /**
+ * Implements automatic conversion to a Graphics::Surface by
+ * simply returning the inner surface. This must be const,
+ * because we don't want changes being done directly to it,
+ * since it would bypass dirty rect handling
+ */
+ operator const Surface &() const { return _innerSurface; }
+ const Surface &rawSurface() const { return _innerSurface; }
+
+ /**
+ * Reassign one managed surface to another one
+ * Note that if the source has a managed surface, it will be duplicated
+ */
+ ManagedSurface &operator=(const ManagedSurface &surf);
+
+ /**
+ * Returns true if the surface has not yet been allocated
+ */
+ bool empty() const { return w == 0 || h == 0 || _innerSurface.getPixels() == nullptr; }
+
+ /**
+ * Returns true if the surface is managing its own pixels
+ */
+ DisposeAfterUse::Flag disposeAfterUse() const { return _disposeAfterUse; }
+
+ /**
+ * Return a pointer to the pixel at the specified point.
+ *
+ * @param x The x coordinate of the pixel.
+ * @param y The y coordinate of the pixel.
+ * @return Pointer to the pixel.
+ */
+ inline const void *getBasePtr(int x, int y) const {
+ return _innerSurface.getBasePtr(x, y);
+ }
+
+ /**
+ * Return a pointer to the pixel at the specified point.
+ *
+ * @param x The x coordinate of the pixel.
+ * @param y The y coordinate of the pixel.
+ * @return Pointer to the pixel.
+ */
+ inline void *getBasePtr(int x, int y) {
+ return _innerSurface.getBasePtr(x, y);
+ }
+
+ /**
+ * Get a reference to the pixel data
+ */
+ inline void *getPixels() { return _innerSurface.getPixels(); }
+ inline const void *getPixels() const { return _innerSurface.getPixels(); }
+
+ /**
+ * Sets the pixel data.
+ */
+ virtual void setPixels(void *newPixels);
+
+ /**
+ * Allocate memory for the pixel data of the surface.
+ */
+ virtual void create(uint16 width, uint16 height);
+
+ /**
+ * Allocate memory for the pixel data of the surface.
+ */
+ virtual void create(uint16 width, uint16 height, const PixelFormat &pixelFormat);
+
+ /**
+ * Sets up the surface as a sub-section of another passed parent surface. This surface
+ * will not own the pixels, and any dirty rect notifications will automatically be
+ * passed to the original parent surface.
+ * @remarks Note that this differs from Graphics::Surface::getSubArea, in that that
+ * method only adds a single initial dirty rect for the whole area, and then none further
+ */
+ virtual void create(ManagedSurface &surf, const Common::Rect &bounds);
+
+ /**
+ * Release the memory used by the pixels memory of this surface. This is the
+ * counterpart to create().
+ */
+ virtual void free();
+
+ /**
+ * Clears any pending dirty rects that have been generated for the surface
+ */
+ virtual void clearDirtyRects() {}
+
+ /**
+ * When the managed surface is a sub-section of a parent surface, returns the
+ * the offset in the parent surface that the surface starts at
+ */
+ const Common::Point getOffsetFromOwner() const { return _offsetFromOwner; }
+
+ /**
+ * Return a rect giving the bounds of the surface
+ */
+ const Common::Rect getBounds() const {
+ return Common::Rect(0, 0, this->w, this->h);
+ }
+
+ /**
+ * Copies another surface into this one
+ */
+ void blitFrom(const Surface &src);
+
+ /**
+ * Copies another surface into this one at a given destination position
+ */
+ void blitFrom(const Surface &src, const Common::Point &destPos);
+
+ /**
+ * Copies another surface into this one at a given destination position
+ */
+ void blitFrom(const Surface &src, const Common::Rect &srcRect,
+ const Common::Point &destPos);
+
+ /**
+ * Copies another surface into this one ignoring pixels of a designated transparent color
+ * @param src Source surface
+ * @param transColor Transparency color to ignore copying
+ * @param flipped Specifies whether to horizontally flip the image
+ * @param overrideColor Optional color to use instead of non-transparent pixels from
+ * the source surface
+ */
+ void transBlitFrom(const Surface &src, uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+ /**
+ * Copies another surface into this one ignoring pixels of a designated transparent color
+ * @param src Source surface
+ * @param destPos Destination position to draw the surface
+ * @param transColor Transparency color to ignore copying
+ * @param flipped Specifies whether to horizontally flip the image
+ * @param overrideColor Optional color to use instead of non-transparent pixels from
+ * the source surface
+ */
+ void transBlitFrom(const Surface &src, const Common::Point &destPos,
+ uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+ /**
+ * Copies another surface into this one ignoring pixels of a designated transparent color
+ * @param src Source surface
+ * @param srcRect Sub-section of source surface to draw
+ * @param destPos Destination position to draw the surface
+ * @param transColor Transparency color to ignore copying
+ * @param flipped Specifies whether to horizontally flip the image
+ * @param overrideColor Optional color to use instead of non-transparent pixels from
+ * the source surface
+ */
+ void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Point &destPos,
+ uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+ /**
+ * Copies another surface into this one ignoring pixels of a designated transparent color
+ * @param src Source surface
+ * @param srcRect Sub-section of source surface to draw
+ * @param destRect Destination area to draw the surface in. This can be sized differently
+ * then srcRect, allowing for arbitrary scaling of the image
+ * @param transColor Transparency color to ignore copying
+ * @param flipped Specifies whether to horizontally flip the image
+ * @param overrideColor Optional color to use instead of non-transparent pixels from
+ * the source surface
+ */
+ void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Rect &destRect,
+ uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+ /**
+ * Clear the entire surface
+ */
+ void clear(uint color = 0);
+
+ /**
+ * Mark the entire surface as dirty
+ */
+ void markAllDirty();
+
+ /**
+ * Copies a bitmap to the Surface internal buffer. The pixel format
+ * of buffer must match the pixel format of the Surface.
+ */
+ void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
+ _innerSurface.copyRectToSurface(buffer, srcPitch, destX, destY, width, height);
+ }
+
+ /**
+ * Copies a bitmap to the Surface internal buffer. The pixel format
+ * of buffer must match the pixel format of the Surface.
+ */
+ void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect) {
+ _innerSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
+ }
+
+ /**
+ * Copy the data from another Surface, reinitializing the
+ * surface to match the dimensions of the passed surface
+ */
+ void copyFrom(const ManagedSurface &surf) {
+ clearDirtyRects();
+ _innerSurface.copyFrom(surf._innerSurface);
+ }
+
+ /**
+ * Draw a line.
+ */
+ void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
+ _innerSurface.drawLine(x0, y0, x1, y1, color);
+ addDirtyRect(Common::Rect(x0, y0, x1, y1));
+ }
+
+ /**
+ * Draw a thick line.
+ */
+ void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
+ _innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, color);
+ addDirtyRect(Common::Rect(x0, y0, x1 + penX, y1 + penY));
+ }
+
+ /**
+ * Draw a horizontal line.
+ */
+ void hLine(int x, int y, int x2, uint32 color) {
+ _innerSurface.hLine(x, y, x2, color);
+ addDirtyRect(Common::Rect(x, y, x2 + 1, y + 1));
+ }
+
+ /**
+ * Draw a vertical line.
+ */
+ void vLine(int x, int y, int y2, uint32 color) {
+ _innerSurface.vLine(x, y, y2, color);
+ addDirtyRect(Common::Rect(x, y, x + 1, y2 + 1));
+ }
+
+ /**
+ * Fill a rect with a given color.
+ */
+ void fillRect(Common::Rect r, uint32 color) {
+ _innerSurface.fillRect(r, color);
+ addDirtyRect(r);
+ }
+
+ /**
+ * Draw a frame around a specified rect.
+ */
+ void frameRect(const Common::Rect &r, uint32 color) {
+ _innerSurface.frameRect(r, color);
+ addDirtyRect(r);
+ }
+
+ /**
+ * Returns a sub-area of the screen, but only adds a single initial dirty rect
+ * for the retrieved area.
+ */
+ Surface getSubArea(const Common::Rect &area) {
+ addDirtyRect(area);
+ return _innerSurface.getSubArea(area);
+ }
+};
+
+} // End of namespace Graphics
+
+
+#endif
diff --git a/graphics/module.mk b/graphics/module.mk
index b6919cf1ab..90f6a3199c 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -12,10 +12,12 @@ MODULE_OBJS := \
fonts/ttf.o \
fonts/winfont.o \
maccursor.o \
+ managed_surface.o \
pixelformat.o \
primitives.o \
scaler.o \
scaler/thumbnail_intern.o \
+ screen.o \
sjis.o \
surface.o \
transform_struct.o \
diff --git a/graphics/primitives.cpp b/graphics/primitives.cpp
index 564bdb9673..ac1c58b1d8 100644
--- a/graphics/primitives.cpp
+++ b/graphics/primitives.cpp
@@ -20,7 +20,9 @@
*
*/
+#include "common/algorithm.h"
#include "common/util.h"
+#include "graphics/primitives.h"
namespace Graphics {
@@ -62,6 +64,22 @@ void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, i
}
}
+void drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ if (x1 > x2)
+ SWAP(x1, x2);
+
+ for (int x = x1; x <= x2; x++)
+ (*plotProc)(x, y, color, data);
+}
+
+void drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ if (y1 > y2)
+ SWAP(y1, y2);
+
+ for (int y = y1; y <= y2; y++)
+ (*plotProc)(x, y, color, data);
+}
+
void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data) {
assert(penX > 0 && penY > 0);
@@ -79,4 +97,335 @@ void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color
drawLine(x0 + x, y0 + y, x1 + x, y1 + y, color, plotProc, data);
}
+/* Bresenham as presented in Foley & Van Dam */
+/* Code is based on GD lib http://libgd.github.io/ */
+void drawThickLine2(int x1, int y1, int x2, int y2, int thick, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ int incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int wid;
+ int w, wstart;
+
+ int dx = abs(x2 - x1);
+ int dy = abs(y2 - y1);
+
+ if (dx == 0) {
+ if (y1 > y2)
+ SWAP(y1, y2);
+ Common::Rect r(x1, y1, x1 + thick - 1, y2);
+ drawFilledRect(r, color, plotProc, data);
+ return;
+ } else if (dy == 0) {
+ if (x1 > x2)
+ SWAP(x1, x2);
+ Common::Rect r(x1, y1, x2, y1 + thick - 1);
+ drawFilledRect(r, color, plotProc, data);
+ return;
+ }
+
+ if (dy <= dx) {
+ /* More-or-less horizontal. use wid for vertical stroke */
+ /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
+
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double ac = cos(atan2((double)dy, (double)dx));
+ if (ac != 0) {
+ wid = thick / ac;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0) {
+ wid = 1;
+ }
+ d = 2 * dy - dx;
+ incr1 = 2 * dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+
+ /* Set up line thickness */
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, y, color, data);
+
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y++;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, w, color, data);
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y--;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, w, color, data);
+ }
+ }
+ } else {
+ /* More-or-less vertical. use wid for horizontal stroke */
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double as = sin(atan2((double)dy, (double)dx));
+ if (as != 0) {
+ wid = thick / as;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0)
+ wid = 1;
+
+ d = 2 * dx - dy;
+ incr1 = 2 * dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+
+ /* Set up line thickness */
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x++;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x--;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+ }
+ }
+ }
+}
+
+void drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ for (int y = rect.top; y <= rect.bottom; y++)
+ drawHLine(rect.left, rect.right, y, color, plotProc, data);
+}
+
+// http://members.chello.at/easyfilter/bresenham.html
+void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
+ if (rect.height() < rect.width()) {
+ int x = -arc, y = 0, err = 2-2*arc; /* II. Quadrant */
+ int dy = rect.height() - arc * 2;
+ int r = arc;
+ int stop = 0;
+ int lastx = 0, lasty = 0;
+ if (dy < 0)
+ stop = -dy / 2;
+
+ do {
+ if (filled) {
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left+x+r, rect.top-y+r-stop, color, data);
+ (*plotProc)(rect.right-x-r, rect.top-y+r-stop, color, data);
+ (*plotProc)(rect.left+x+r, rect.bottom+y-r+stop, color, data);
+ (*plotProc)(rect.right-x-r, rect.bottom+y-r+stop, color, data);
+
+ lastx = x;
+ lasty = y;
+ }
+ arc = err;
+ if (arc <= y) err += ++y*2+1; /* e_xy+e_y < 0 */
+ if (arc > x || err > y) err += ++x*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
+ if (stop && y > stop)
+ break;
+ } while (x < 0);
+
+ if (!filled) {
+ x = lastx;
+ y = lasty;
+
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
+ }
+
+ for (int i = 0; i < dy; i++) {
+ if (filled) {
+ drawHLine(rect.left, rect.right, rect.top + r + i, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left, rect.top + r + i, color, data);
+ (*plotProc)(rect.right, rect.top + r + i, color, data);
+ }
+ }
+ } else {
+ int y = -arc, x = 0, err = 2-2*arc; /* II. Quadrant */
+ int dx = rect.width() - arc * 2;
+ int r = arc;
+ int stop = 0;
+ int lastx = 0, lasty = 0;
+ if (dx < 0)
+ stop = -dx / 2;
+
+ do {
+ if (filled) {
+ drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left-x+r-stop, rect.top+y+r, color, data);
+ (*plotProc)(rect.left-x+r-stop, rect.bottom-y-r, color, data);
+ (*plotProc)(rect.right+x-r+stop, rect.top+y+r, color, data);
+ (*plotProc)(rect.right+x-r+stop, rect.bottom-y-r, color, data);
+
+ lastx = x;
+ lasty = y;
+ }
+
+ arc = err;
+ if (arc <= x) err += ++x*2+1; /* e_xy+e_y < 0 */
+ if (arc > y || err > x) err += ++y*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
+ if (stop && x > stop)
+ break;
+ } while (y < 0);
+
+ if (!filled) {
+ x = lastx;
+ y = lasty;
+ drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ }
+
+ for (int i = 0; i < dx; i++) {
+ if (filled) {
+ drawVLine(rect.left + r + i, rect.top, rect.bottom, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left + r + i, rect.top, color, data);
+ (*plotProc)(rect.left + r + i, rect.bottom, color, data);
+ }
+ }
+ }
+}
+
+// Based on public-domain code by Darel Rex Finley, 2007
+// http://alienryderflex.com/polygon_fill/
+void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ int *nodeX = (int *)calloc(npoints, sizeof(int));
+ int i, j;
+
+ // Loop through the rows of the image.
+ for (int pixelY = bbox.top; pixelY < bbox.bottom; pixelY++) {
+ // Build a list of nodes.
+ int nodes = 0;
+ j = npoints - 1;
+
+ for (i = 0; i < npoints; i++) {
+ if ((polyY[i] < pixelY && polyY[j] >= pixelY) || (polyY[j] < pixelY && polyY[i] >= pixelY)) {
+ nodeX[nodes++] = (int)(polyX[i] + (double)(pixelY - polyY[i]) / (double)(polyY[j]-polyY[i]) *
+ (double)(polyX[j] - polyX[i]) + 0.5);
+ }
+ j = i;
+ }
+
+ // Sort the nodes
+ Common::sort(nodeX, &nodeX[nodes]);
+
+ // Fill the pixels between node pairs.
+ for (i = 0; i < nodes; i += 2) {
+ if (nodeX[i ] >= bbox.right)
+ break;
+ if (nodeX[i + 1] > bbox.left) {
+ nodeX[i] = MAX<int16>(nodeX[i], bbox.left);
+ nodeX[i + 1] = MIN<int16>(nodeX[i + 1], bbox.right);
+
+ drawHLine(nodeX[i], nodeX[i + 1], pixelY, color, plotProc, data);
+ }
+ }
+ }
+
+ free(nodeX);
+}
+
+// http://members.chello.at/easyfilter/bresenham.html
+void drawEllipse(int x0, int y0, int x1, int y1, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
+ int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
+ long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ long err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */
+ if (y0 > y1) y0 = y1; /* .. exchange them */
+ y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+
+ do {
+ if (filled) {
+ drawHLine(x0, x1, y0, color, plotProc, data);
+ drawHLine(x0, x1, y1, color, plotProc, data);
+ } else {
+ (*plotProc)(x1, y0, color, data); /* I. Quadrant */
+ (*plotProc)(x0, y0, color, data); /* II. Quadrant */
+ (*plotProc)(x0, y1, color, data); /* III. Quadrant */
+ (*plotProc)(x1, y1, color, data); /* IV. Quadrant */
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ while (y0-y1 < b) { /* too early stop of flat ellipses a=1 */
+ if (filled) {
+ drawHLine(x0-1, x0-1, y0, color, plotProc, data); /* -> finish tip of ellipse */
+ drawHLine(x1+1, x1+1, y0, color, plotProc, data);
+ drawHLine(x0-1, x0-1, y1, color, plotProc, data);
+ drawHLine(x1+1, x1+1, y1, color, plotProc, data);
+ } else {
+ (*plotProc)(x0-1, y0, color, data); /* -> finish tip of ellipse */
+ (*plotProc)(x1+1, y0, color, data);
+ (*plotProc)(x0-1, y1, color, data);
+ (*plotProc)(x1+1, y1, color, data);
+ }
+ y0++;
+ y1--;
+ }
+}
+
} // End of namespace Graphics
diff --git a/graphics/primitives.h b/graphics/primitives.h
index a3e8ab1565..62dc10bfdf 100644
--- a/graphics/primitives.h
+++ b/graphics/primitives.h
@@ -23,10 +23,21 @@
#ifndef GRAPHICS_PRIMITIVES_H
#define GRAPHICS_PRIMITIVES_H
+#include "common/rect.h"
+
namespace Graphics {
void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data);
void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawThickLine2(int x1, int y1, int x2, int y2, int thick, int color,
+ void (*plotProc)(int, int, int, void *), void *data);
+void drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data);
+void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color,
+ void (*plotProc)(int, int, int, void *), void *data);
+void drawEllipse(int x0, int y0, int x1, int y1, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data);
} // End of namespace Graphics
diff --git a/graphics/screen.cpp b/graphics/screen.cpp
new file mode 100644
index 0000000000..4169c98035
--- /dev/null
+++ b/graphics/screen.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/algorithm.h"
+#include "graphics/screen.h"
+#include "graphics/palette.h"
+
+namespace Graphics {
+
+Screen::Screen(): ManagedSurface() {
+ create(g_system->getWidth(), g_system->getHeight());
+}
+
+Screen::Screen(int width, int height): ManagedSurface() {
+ create(width, height);
+}
+
+Screen::Screen(int width, int height, PixelFormat pixelFormat): ManagedSurface() {
+ create(width, height, pixelFormat);
+}
+
+void Screen::update() {
+ // Merge the dirty rects
+ mergeDirtyRects();
+
+ // Loop through copying dirty areas to the physical screen
+ Common::List<Common::Rect>::iterator i;
+ for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
+ const Common::Rect &r = *i;
+ const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
+ g_system->copyRectToScreen(srcP, pitch, r.left, r.top,
+ r.width(), r.height());
+ }
+
+ // Signal the physical screen to update
+ g_system->updateScreen();
+ _dirtyRects.clear();
+}
+
+
+void Screen::addDirtyRect(const Common::Rect &r) {
+ Common::Rect bounds = r;
+ bounds.clip(getBounds());
+ bounds.translate(getOffsetFromOwner().x, getOffsetFromOwner().y);
+
+ if (bounds.width() > 0 && bounds.height() > 0)
+ _dirtyRects.push_back(bounds);
+}
+
+void Screen::makeAllDirty() {
+ addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void Screen::mergeDirtyRects() {
+ Common::List<Common::Rect>::iterator rOuter, rInner;
+
+ // Process the dirty rect list to find any rects to merge
+ for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+ rInner = rOuter;
+ while (++rInner != _dirtyRects.end()) {
+
+ if ((*rOuter).intersects(*rInner)) {
+ // These two rectangles overlap, so merge them
+ unionRectangle(*rOuter, *rOuter, *rInner);
+
+ // remove the inner rect from the list
+ _dirtyRects.erase(rInner);
+
+ // move back to beginning of list
+ rInner = rOuter;
+ }
+ }
+ }
+}
+
+bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+ destRect = src1;
+ destRect.extend(src2);
+
+ return !destRect.isEmpty();
+}
+
+void Screen::getPalette(byte palette[PALETTE_SIZE]) {
+ assert(format.bytesPerPixel == 1);
+ g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
+}
+
+void Screen::getPalette(byte *palette, uint start, uint num) {
+ assert(format.bytesPerPixel == 1);
+ g_system->getPaletteManager()->grabPalette(palette, start, num);
+}
+
+void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
+ assert(format.bytesPerPixel == 1);
+ g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
+}
+
+void Screen::setPalette(const byte *palette, uint start, uint num) {
+ assert(format.bytesPerPixel == 1);
+ g_system->getPaletteManager()->setPalette(palette, start, num);
+}
+
+void Screen::clearPalette() {
+ byte palette[PALETTE_SIZE];
+ Common::fill(&palette[0], &palette[PALETTE_SIZE], 0);
+ setPalette(palette);
+}
+
+} // End of namespace Graphics
diff --git a/graphics/screen.h b/graphics/screen.h
new file mode 100644
index 0000000000..29816120f1
--- /dev/null
+++ b/graphics/screen.h
@@ -0,0 +1,118 @@
+/* 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 GRAPHICS_SCREEN_H
+#define GRAPHICS_SCREEN_H
+
+#include "graphics/managed_surface.h"
+#include "graphics/pixelformat.h"
+#include "common/list.h"
+#include "common/rect.h"
+
+namespace Graphics {
+
+#define PALETTE_COUNT 256
+#define PALETTE_SIZE (256 * 3)
+
+/**
+ * Implements a specialised surface that represents the screen.
+ * It keeps track of any areas of itself that are updated by drawing
+ * calls, and provides an update that method that blits the affected
+ * areas to the physical screen
+ */
+class Screen : virtual public ManagedSurface {
+private:
+ /**
+ * List of affected areas of the screen
+ */
+ Common::List<Common::Rect> _dirtyRects;
+private:
+ /**
+ * Merges together overlapping dirty areas of the screen
+ */
+ void mergeDirtyRects();
+
+ /**
+ * Returns the union of two dirty area rectangles
+ */
+ bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+protected:
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
+ virtual void addDirtyRect(const Common::Rect &r);
+public:
+ Screen();
+ Screen(int width, int height);
+ Screen(int width, int height, PixelFormat pixelFormat);
+
+ /**
+ * Returns true if there are any pending screen updates (dirty areas)
+ */
+ bool isDirty() const { return !_dirtyRects.empty(); }
+
+ /**
+ * Marks the whole screen as dirty. This forces the next call to update
+ * to copy the entire screen contents
+ */
+ void makeAllDirty();
+
+ /**
+ * Clear the current dirty rects list
+ */
+ virtual void clearDirtyRects() { _dirtyRects.clear(); }
+
+ /**
+ * Updates the screen by copying any affected areas to the system
+ */
+ virtual void update();
+
+ /**
+ * Return the currently active palette
+ */
+ void getPalette(byte palette[PALETTE_SIZE]);
+
+ /**
+ * Return a portion of the currently active palette
+ */
+ void getPalette(byte *palette, uint start, uint num);
+
+ /**
+ * Set the palette
+ */
+ void setPalette(const byte palette[PALETTE_SIZE]);
+
+ /**
+ * Set a subsection of the palette
+ */
+ void setPalette(const byte *palette, uint start, uint num);
+
+ /**
+ * Clears the current palette, setting all entries to black
+ */
+ void clearPalette();
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index 802ad09cbb..a3037e5ad5 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -67,7 +67,7 @@ HeaderState loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header,
header.size = in.readUint32BE();
header.version = in.readByte();
- // Do a check whether any read errors had occured. If so we cannot use the
+ // Do a check whether any read errors had occurred. If so we cannot use the
// values obtained for size and version because they might be bad.
if (in.err() || in.eos()) {
// TODO: We fake that there is no header. This is actually not quite
diff --git a/gui/credits.h b/gui/credits.h
index cda523bb79..cb9a10fec4 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -347,6 +347,9 @@ static const char *credits[] = {
"C1""Dreamcast",
"C0""Marcus Comstedt",
"",
+"C1""GCW0",
+"C0""Eugene Sandulenko",
+"",
"C1""GPH Devices (GP2X, GP2XWiz & Caanoo)",
"C0""John Willis",
"",
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index 6ff10267db..9557da1206 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -724,6 +724,10 @@ int PredictiveDialog::binarySearch(const char *const *const dictLine, const Comm
}
bool PredictiveDialog::matchWord() {
+ // If there is no dictionary, then there is no match.
+ if (_unitedDict.dictLineCount <= 0)
+ return false;
+
// If no text has been entered, then there is no match.
if (_currentCode.empty())
return false;
@@ -981,6 +985,7 @@ void PredictiveDialog::loadAllDictionary(Dict &dict) {
Common::File *inFile = new Common::File();
if (!inFile->open(ConfMan.get(dict.nameDict))) {
warning("Predictive Dialog: cannot read file: %s", dict.defaultFilename.c_str());
+ delete inFile;
return;
}
loadDictionary(inFile, dict);
diff --git a/gui/predictivedialog.h b/gui/predictivedialog.h
index 37c80a2a14..4c167c3efa 100644
--- a/gui/predictivedialog.h
+++ b/gui/predictivedialog.h
@@ -85,6 +85,7 @@ private:
struct Dict {
Dict() : dictLine(nullptr), dictText(nullptr), dictActLine(nullptr),
dictLineCount(0), dictTextSize(0) {}
+ ~Dict() { free(dictText); }
char **dictLine;
char *dictText;
char *dictActLine; // using only for united dict...
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index 58e1b5b2b2..b0da793cdf 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/image/codecs/indeo3.cpp b/image/codecs/indeo3.cpp
index af9120ca93..560658d1f5 100644
--- a/image/codecs/indeo3.cpp
+++ b/image/codecs/indeo3.cpp
@@ -391,6 +391,11 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
int rle_v1, rle_v2, rle_v3;
uint16 res;
+ if ((width & 3) != 0) {
+ // This isn't a valid width according to http://wiki.multimedia.cx/index.php?title=Indeo_3
+ warning("Indeo3 file with width not divisible by 4. This will cause unaligned writes");
+ }
+
bit_buf = 0;
ref_vectors = NULL;
@@ -479,7 +484,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
if (cmd == 0 || ref_vectors != NULL) {
for (lp1 = 0; lp1 < blks_width; lp1++) {
for (i = 0, j = 0; i < blks_height; i++, j += width_tbl[1])
- ((uint32 *)cur_frm_pos)[j] = ((uint32 *)ref_frm_pos)[j];
+ ((uint32 *)cur_frm_pos)[j] = READ_UINT32(((uint32 *)ref_frm_pos)+j);
cur_frm_pos += 4;
ref_frm_pos += 4;
}
@@ -526,7 +531,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
switch (correction_type_sp[0][k]) {
case 0:
- *cur_lp = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ *cur_lp = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
lp2++;
break;
case 1:
@@ -540,9 +545,9 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
//warning("Glitch");
return;
}
- res = ((FROM_LE_16(((uint16 *)(ref_lp))[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ res = ((READ_LE_UINT16(((uint16 *)(ref_lp))) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
((uint16 *)cur_lp)[0] = FROM_LE_16(res);
- res = ((FROM_LE_16(((uint16 *)(ref_lp))[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ res = ((READ_LE_UINT16(((uint16 *)(ref_lp))+1) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
((uint16 *)cur_lp)[1] = FROM_LE_16(res);
buf1++;
lp2++;
@@ -550,14 +555,14 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 2:
if (lp2 == 0) {
for (i = 0, j = 0; i < 2; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 += 2;
}
break;
case 3:
if (lp2 < 2) {
for (i = 0, j = 0; i < (3 - lp2); i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 = 3;
}
break;
@@ -567,7 +572,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
if (rle_v1 == 1 || ref_vectors != NULL) {
for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
}
RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
@@ -580,7 +585,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
LP2_CHECK(buf1,rle_v3,lp2)
case 4:
for (i = 0, j = 0; i < (4 - lp2); i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 = 4;
break;
@@ -600,7 +605,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
}
if (ref_vectors != NULL) {
for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
}
lp2 = 4;
break;
@@ -645,18 +650,18 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
switch (correction_type_sp[lp2 & 0x01][k]) {
case 0:
- cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
if (lp2 > 0 || flag1 == 0 || strip->ypos != 0)
cur_lp[0] = ((cur_lp[-width_tbl[1]] >> 1) + (cur_lp[width_tbl[1]] >> 1)) & 0xFEFEFEFE;
else
- cur_lp[0] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[0] = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
lp2++;
break;
case 1:
- res = ((FROM_LE_16(((uint16 *)ref_lp)[0]) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
+ res = ((READ_LE_UINT16(((uint16 *)ref_lp)) >> 1) + correction_lp[lp2 & 0x01][*buf1]) << 1;
((uint16 *)cur_lp)[width_tbl[2]] = FROM_LE_16(res);
- res = ((FROM_LE_16(((uint16 *)ref_lp)[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
+ res = ((READ_LE_UINT16(((uint16 *)ref_lp)+1) >> 1) + correction_lp[lp2 & 0x01][k]) << 1;
((uint16 *)cur_lp)[width_tbl[2]+1] = FROM_LE_16(res);
if (lp2 > 0 || flag1 == 0 || strip->ypos != 0)
@@ -670,7 +675,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 2:
if (lp2 == 0) {
for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
- cur_lp[j] = *ref_lp;
+ cur_lp[j] = READ_UINT32(ref_lp);
lp2 += 2;
}
break;
@@ -678,7 +683,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 3:
if (lp2 < 2) {
for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
- cur_lp[j] = *ref_lp;
+ cur_lp[j] = READ_UINT32(ref_lp);
lp2 = 3;
}
break;
@@ -703,7 +708,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
if (rle_v1 == 1) {
for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
}
RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
@@ -716,7 +721,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
LP2_CHECK(buf1,rle_v3,lp2)
case 4:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
- cur_lp[j] = *ref_lp;
+ cur_lp[j] = READ_UINT32(ref_lp);
lp2 = 4;
break;
@@ -756,8 +761,8 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
k = *buf1++;
cur_lp = ((uint32 *)cur_frm_pos) + width_tbl[lp2 * 2];
ref_lp = ((uint32 *)cur_frm_pos) + width_tbl[(lp2 * 2) - 1];
- lv1 = ref_lp[0];
- lv2 = ref_lp[1];
+ lv1 = READ_UINT32(ref_lp);
+ lv2 = READ_UINT32(ref_lp+1);
if (lp2 == 0 && flag1 != 0) {
#if defined(SCUMM_BIG_ENDIAN)
lv1 = lv1 & 0xFF00FF00;
@@ -936,28 +941,28 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 0:
lv1 = correctionloworder_lp[lp2 & 0x01][k];
lv2 = correctionhighorder_lp[lp2 & 0x01][k];
- cur_lp[0] = FROM_LE_32(((FROM_LE_32(ref_lp[0]) >> 1) + lv1) << 1);
- cur_lp[1] = FROM_LE_32(((FROM_LE_32(ref_lp[1]) >> 1) + lv2) << 1);
- cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
- cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ cur_lp[0] = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + lv1) << 1);
+ cur_lp[1] = FROM_LE_32(((READ_LE_UINT32(ref_lp+1) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((READ_LE_UINT32(ref_lp+width_tbl[1]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((READ_LE_UINT32(ref_lp+width_tbl[1]+1) >> 1) + lv2) << 1);
lp2++;
break;
case 1:
lv1 = correctionloworder_lp[lp2 & 0x01][*buf1++];
lv2 = correctionloworder_lp[lp2 & 0x01][k];
- cur_lp[0] = FROM_LE_32(((FROM_LE_32(ref_lp[0]) >> 1) + lv1) << 1);
- cur_lp[1] = FROM_LE_32(((FROM_LE_32(ref_lp[1]) >> 1) + lv2) << 1);
- cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + lv1) << 1);
- cur_lp[width_tbl[1]+1] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]+1]) >> 1) + lv2) << 1);
+ cur_lp[0] = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + lv1) << 1);
+ cur_lp[1] = FROM_LE_32(((READ_LE_UINT32(ref_lp+1) >> 1) + lv2) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((READ_LE_UINT32(ref_lp+width_tbl[1]) >> 1) + lv1) << 1);
+ cur_lp[width_tbl[1]+1] = FROM_LE_32(((READ_LE_UINT32(ref_lp+width_tbl[1]+1) >> 1) + lv2) << 1);
lp2++;
break;
case 2:
if (lp2 == 0) {
for (i = 0, j = 0; i < 4; i++, j += width_tbl[1]) {
- cur_lp[j] = ref_lp[j];
- cur_lp[j+1] = ref_lp[j+1];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
+ cur_lp[j+1] = READ_UINT32(ref_lp+j+1);
}
lp2 += 2;
}
@@ -966,8 +971,8 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 3:
if (lp2 < 2) {
for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1]) {
- cur_lp[j] = ref_lp[j];
- cur_lp[j+1] = ref_lp[j+1];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
+ cur_lp[j+1] = READ_UINT32(ref_lp+j+1);
}
lp2 = 3;
}
@@ -977,8 +982,8 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
if (lp2 == 0) {
RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
for (i = 0, j = 0; i < 8; i++, j += width_tbl[1]) {
- ((uint32 *)cur_frm_pos)[j] = ((uint32 *)ref_frm_pos)[j];
- ((uint32 *)cur_frm_pos)[j+1] = ((uint32 *)ref_frm_pos)[j+1];
+ ((uint32 *)cur_frm_pos)[j] = READ_UINT32(((uint32 *)ref_frm_pos)+j);
+ ((uint32 *)cur_frm_pos)[j+1] = READ_UINT32(((uint32 *)ref_frm_pos)+j+1);
}
RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
break;
@@ -992,8 +997,8 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 6:
case 4:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
- cur_lp[j] = ref_lp[j];
- cur_lp[j+1] = ref_lp[j+1];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
+ cur_lp[j+1] = READ_UINT32(ref_lp+j+1);
}
lp2 = 4;
break;
@@ -1037,8 +1042,8 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
switch (correction_type_sp[lp2 & 0x01][k]) {
case 0:
- cur_lp[0] = FROM_LE_32(((FROM_LE_32(*ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
- cur_lp[width_tbl[1]] = FROM_LE_32(((FROM_LE_32(ref_lp[width_tbl[1]]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[0] = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
+ cur_lp[width_tbl[1]] = FROM_LE_32(((READ_LE_UINT32(ref_lp+width_tbl[1]) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
lp2++;
break;
@@ -1051,13 +1056,13 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
lv1 = (uint16)(correction_lp[lp2 & 0x01][*buf1++]);
lv2 = (uint16)(correction_lp[lp2 & 0x01][k]);
- res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[0]) >> 1) + lv1) << 1);
+ res = (uint16)(((READ_LE_UINT16(((uint16 *)ref_lp)) >> 1) + lv1) << 1);
((uint16 *)cur_lp)[0] = FROM_LE_16(res);
- res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[1]) >> 1) + lv2) << 1);
+ res = (uint16)(((READ_LE_UINT16(((uint16 *)ref_lp)+1) >> 1) + lv2) << 1);
((uint16 *)cur_lp)[1] = FROM_LE_16(res);
- res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[width_tbl[2]]) >> 1) + lv1) << 1);
+ res = (uint16)(((READ_LE_UINT16(((uint16 *)ref_lp)+width_tbl[2]) >> 1) + lv1) << 1);
((uint16 *)cur_lp)[width_tbl[2]] = FROM_LE_16(res);
- res = (uint16)(((FROM_LE_16(((uint16 *)ref_lp)[width_tbl[2]+1]) >> 1) + lv2) << 1);
+ res = (uint16)(((READ_LE_UINT16(((uint16 *)ref_lp)+width_tbl[2]+1) >> 1) + lv2) << 1);
((uint16 *)cur_lp)[width_tbl[2]+1] = FROM_LE_16(res);
lp2++;
break;
@@ -1065,7 +1070,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 2:
if (lp2 == 0) {
for (i = 0, j = 0; i < 4; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 += 2;
}
break;
@@ -1073,7 +1078,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 3:
if (lp2 < 2) {
for (i = 0, j = 0; i < 6 - (lp2 * 2); i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 = 3;
}
break;
@@ -1083,7 +1088,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
for (i = 0, j = 0; i < 8; i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
RLE_V2_CHECK(buf1,rle_v2, rle_v3,lp2)
break;
@@ -1097,7 +1102,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
case 4:
case 6:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
- cur_lp[j] = ref_lp[j];
+ cur_lp[j] = READ_UINT32(ref_lp+j);
lp2 = 4;
break;
diff --git a/image/codecs/rpza.cpp b/image/codecs/rpza.cpp
index 8d648e1cc1..db0d512f45 100644
--- a/image/codecs/rpza.cpp
+++ b/image/codecs/rpza.cpp
@@ -50,6 +50,7 @@ RPZADecoder::~RPZADecoder() {
}
delete[] _ditherPalette;
+ delete[] _colorMap;
}
#define ADVANCE_BLOCK() \
diff --git a/po/be_BY.po b/po/be_BY.po
index 9f72e650d2..5b80dc19aa 100644
--- a/po/be_BY.po
+++ b/po/be_BY.po
@@ -7,16 +7,17 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-02-02 23:16+0300\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-21 23:32+0300\n"
"Last-Translator: Ivan Lukyanov <greencis@mail.ru>\n"
"Language-Team: Ivan Lukyanov <greencis@mail.ru>\n"
"Language: Belarusian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-5\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Poedit 1.8.6\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Poedit 1.8.7\n"
#: gui/about.cpp:94
#, c-format
@@ -37,7 +38,7 @@ msgstr "¿ÐÚÐ×ÒÐæì áåÐÒÐÝëï äÐÙÛë"
#: gui/browser.cpp:68
msgid "Show files marked with the hidden attribute"
-msgstr "¿ÐÚÐ×ÒÐæì äÐÙÛë × ÐâàëÑãâÐÜ \"áåÐÒÐæì\""
+msgstr "¿ÐÚÐ×ÒÐæì äÐÙÛë × ÐâàëÑãâÐÜ \"áåÐÒÐÝë\""
#: gui/browser.cpp:72
msgid "Go up"
@@ -190,11 +191,11 @@ msgstr "»öÝÕÙÝÐï"
#: gui/fluidsynth-dialog.cpp:145
msgid "Fourth-order"
-msgstr "ÇÐæÒñàâÐÓÐ ßÐàÐÔÚÐ"
+msgstr "ÇÐæÒñàâÐÓÐ ßÐàÐÔÚã"
#: gui/fluidsynth-dialog.cpp:146
msgid "Seventh-order"
-msgstr "ÁñÜÐÓÐ ßÐàÐÔÚÐ"
+msgstr "ÁñÜÐÓÐ ßÐàÐÔÚã"
#: gui/fluidsynth-dialog.cpp:150
msgid "Reset"
@@ -224,7 +225,8 @@ msgid "OK"
msgstr "OK"
#: gui/fluidsynth-dialog.cpp:217
-msgid "Do you really want to reset all FluidSynth settings to their default values?"
+msgid ""
+"Do you really want to reset all FluidSynth settings to their default values?"
msgstr "²ë áÐßàÐþÔë ÖÐÔÐÕæÕ áÚöÝãæì ÝÐÛÐÔë FluidSynth ßÐ ×ÜÐþçÐÝÝö?"
#: gui/gui-manager.cpp:119 backends/keymapper/remap-dialog.cpp:53
@@ -289,8 +291,12 @@ msgid "ID:"
msgstr "ID:"
#: gui/launcher.cpp:197 gui/launcher.cpp:199 gui/launcher.cpp:200
-msgid "Short game identifier used for referring to saved games and running the game from the command line"
-msgstr "ºÐàÞâÚö öÔíÝâëäöÚÐâÐà, ÒëÚÐàëáâÞþÒÐÝë ÔÛï öÜñÝÐþ ×ÐåÐÒÐÝÝïþ ÓãÛìÝïþ ö ÔÛï ×ÐßãáÚã × ÚÐÜÐÝÔÝÐÓÐ àÐÔÚÐ"
+msgid ""
+"Short game identifier used for referring to saved games and running the game "
+"from the command line"
+msgstr ""
+"ºÐàÞâÚö öÔíÝâëäöÚÐâÐà, ÒëÚÐàëáâÞþÒÐÝë ÔÛï öÜñÝÐþ ×ÐåÐÒÐÝÝïþ ÓãÛìÝïþ ö ÔÛï "
+"×ÐßãáÚã × ÚÐÜÐÝÔÝÐÓÐ àÐÔÚÐ"
#: gui/launcher.cpp:199
msgctxt "lowres"
@@ -311,8 +317,12 @@ msgid "Language:"
msgstr "¼ÞÒÐ:"
#: gui/launcher.cpp:210 gui/launcher.cpp:211
-msgid "Language of the game. This will not turn your Spanish game version into English"
-msgstr "¼ÞÒÐ ÓãÛìÝö. ·ÜÕÝÐ ÓíâÐÙ ÝÐÛÐÔë ÝÕ ßÕàÐâÒÞàëæì àãáÚãî ÒÕàáöî ÓãÛìÝö þ ÑÕÛÐàãáÚãî"
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"¼ÞÒÐ ÓãÛìÝö. ·ÜÕÝÐ ÓíâÐÙ ÝÐÛÐÔë ÝÕ ßÕàÐâÒÞàëæì àãáÚãî ÒÕàáöî ÓãÛìÝö þ "
+"ÑÕÛÐàãáÚãî"
#: gui/launcher.cpp:212 gui/launcher.cpp:226 gui/options.cpp:87
#: gui/options.cpp:735 gui/options.cpp:748 gui/options.cpp:1208
@@ -580,23 +590,27 @@ msgid "Search:"
msgstr "¿ÞèãÚ:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "·ÐÓàã×öæì ÓãÛìÝî:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "·ÐÓàã×öæì"
#: gui/launcher.cpp:794
-msgid "Do you really want to run the mass game detector? This could potentially add a huge number of games."
-msgstr "²ë áÐßàÐþÔë ÖÐÔÐÕæÕ ×Ðßãáæöæì ÔíâíÚâÐà ãáöå ÓãÛìÝïþ? ³íâÐ ßÐâíÝæëïÛìÝÐ ÜÞÖÐ ÔÐÔÐæì ÒïÛöÚãî ÚÞÛìÚÐáæì ÓãÛìÝïþ."
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"²ë áÐßàÐþÔë ÖÐÔÐÕæÕ ×Ðßãáæöæì ÔíâíÚâÐà ãáöå ÓãÛìÝïþ? ³íâÐ ßÐâíÝæëïÛìÝÐ ÜÞÖÐ "
+"ÔÐÔÐæì ÒïÛöÚãî ÚÞÛìÚÐáæì ÓãÛìÝïþ."
#: gui/launcher.cpp:843
msgid "ScummVM couldn't open the specified directory!"
@@ -748,7 +762,7 @@ msgid "Special dithering modes supported by some games"
msgstr "ÁßÕæëïÛìÝëï àíÖëÜë àíÝÔíàëÝÓã, ßÐÔâàëÜÞþÒÐÝëï ÝÕÚÐâÞàëÜö ÓãÛìÝïÜö"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "¿ÞþÝÐíÚàÐÝÝë àíÖëÜ"
@@ -799,8 +813,12 @@ msgid "Output rate:"
msgstr "ÇÐèçëÝï ÓãÚã:"
#: gui/options.cpp:809 gui/options.cpp:810
-msgid "Higher value specifies better sound quality but may be not supported by your soundcard"
-msgstr "±ÞÛìèëï ×ÝÐçíÝÝö ×ÐÔÐîæì ÛÕßèãî ïÚÐáæì ÓãÚã, ÐÔÝÐÚ ïÝë ÜÞÓãæì ÝÕ ßÐÔâàëÜÛöÒÐææÐ ÒÐèÐÙ ÓãÚÐÒÞÙ ÚÐàâÐÙ"
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"±ÞÛìèëï ×ÝÐçíÝÝö ×ÐÔÐîæì ÛÕßèãî ïÚÐáæì ÓãÚã, ÐÔÝÐÚ ïÝë ÜÞÓãæì ÝÕ "
+"ßÐÔâàëÜÛöÒÐææÐ ÒÐèÐÙ ÓãÚÐÒÞÙ ÚÐàâÐÙ"
#: gui/options.cpp:820
msgid "GM Device:"
@@ -824,7 +842,9 @@ msgstr "SoundFont:"
#: gui/options.cpp:854 gui/options.cpp:856 gui/options.cpp:857
msgid "SoundFont is supported by some audio cards, FluidSynth and Timidity"
-msgstr "SoundFont'ë ßÐÔâàëÜÛöÒÐîææÐ ÝÕÚÐâÞàëÜö ÓãÚÐÒëÜö ÚÐàâÐÜö, FluidSynth Ôë Timidity"
+msgstr ""
+"SoundFont'ë ßÐÔâàëÜÛöÒÐîææÐ ÝÕÚÐâÞàëÜö ÓãÚÐÒëÜö ÚÐàâÐÜö, FluidSynth Ôë "
+"Timidity"
#: gui/options.cpp:856
msgctxt "lowres"
@@ -853,15 +873,21 @@ msgstr "½ÐÛ. MT-32:"
#: gui/options.cpp:879
msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
-msgstr "¿ÐÚÐ×ÒÐÕ ÓãÚÐÒãî ßàëÛÐÔã ßÐ ×ÜÐþçÐÝÝö ÔÛï ÒëÒÐÔã ÝÐ Roland MT-32/LAPC1/CM32l/CM64"
+msgstr ""
+"¿ÐÚÐ×ÒÐÕ ÓãÚÐÒãî ßàëÛÐÔã ßÐ ×ÜÐþçÐÝÝö ÔÛï ÒëÒÐÔã ÝÐ Roland MT-32/LAPC1/CM32l/"
+"CM64"
#: gui/options.cpp:884
msgid "True Roland MT-32 (disable GM emulation)"
msgstr "ÁÐßàÐþÔÝë Roland MT-32 (×ÐÑÐàÐÝöæì íÜãÛïæëî GM)"
#: gui/options.cpp:884 gui/options.cpp:886
-msgid "Check if you want to use your real hardware Roland-compatible sound device connected to your computer"
-msgstr "°Ô×ÝÐçæÕ, ÚÐÛö þ ÒÐá ßÐÔÚÛîçÐÝÐ Roland-áãÜïèçÐÛìÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ ö Òë ÖÐÔÐÕæÕ ïÕ ÒëÚÐàëáâÞþÒÐæì"
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"°Ô×ÝÐçæÕ, ÚÐÛö þ ÒÐá ßÐÔÚÛîçÐÝÐ Roland-áãÜïèçÐÛìÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ ö Òë "
+"ÖÐÔÐÕæÕ ïÕ ÒëÚÐàëáâÞþÒÐæì"
#: gui/options.cpp:886
msgctxt "lowres"
@@ -873,8 +899,12 @@ msgid "Roland GS Device (enable MT-32 mappings)"
msgstr "ÀíÖëÜ Roland GS (ÔÐ×ÒÞÛöæì ÜÐßöÝÓ MT-32)"
#: gui/options.cpp:889
-msgid "Check if you want to enable patch mappings to emulate an MT-32 on a Roland GS device"
-msgstr "°Ô×ÝÐçæÕ, ÚÐÛö ÖÐÔÐÕæÕ ÔÐ×ÒÞÛöæì ÜÐßöÝÓ ÔÛï íÜãÛïæëö MT-32 ÝÐ ßàëÛÐÔ×Õ Rolans GS"
+msgid ""
+"Check if you want to enable patch mappings to emulate an MT-32 on a Roland "
+"GS device"
+msgstr ""
+"°Ô×ÝÐçæÕ, ÚÐÛö ÖÐÔÐÕæÕ ÔÐ×ÒÞÛöæì ÜÐßöÝÓ ÔÛï íÜãÛïæëö MT-32 ÝÐ ßàëÛÐÔ×Õ "
+"Rolans GS"
#: gui/options.cpp:898
msgid "Don't use Roland MT-32 music"
@@ -973,7 +1003,9 @@ msgstr "ÈÛïå ÔÐ âíÜ:"
#: gui/options.cpp:1148 gui/options.cpp:1150 gui/options.cpp:1151
msgid "Specifies path to additional data used by all games or ScummVM"
-msgstr "¿ÐÚÐ×ÒÐÕ èÛïå ÔÐ ÔÐÔÐâÚÞÒëå äÐÙÛÐþ ÔÐÔ×ÕÝëå, ÒëÚÐàëáâÞþÒÐÝëå ãáöÜö ÓãÛìÝïÜö ÐÑÞ ScummVM"
+msgstr ""
+"¿ÐÚÐ×ÒÐÕ èÛïå ÔÐ ÔÐÔÐâÚÞÒëå äÐÙÛÐþ ÔÐÔ×ÕÝëå, ÒëÚÐàëáâÞþÒÐÝëå ãáöÜö ÓãÛìÝïÜö "
+"ÐÑÞ ScummVM"
#: gui/options.cpp:1157
msgid "Plugins Path:"
@@ -1039,8 +1071,12 @@ msgid "Select directory for plugins"
msgstr "°ÑïàëæÕ ÔëàíÚâÞàëî × ßÛÐÓöÝÐÜö"
#: gui/options.cpp:1467
-msgid "The theme you selected does not support your current language. If you want to use this theme you need to switch to another language first."
-msgstr "ÂíÜÐ, ÐÑàÐÝÐï ÒÐÜö, ÝÕ ßÐÔâàëÜÛöÒÐÕ ÑïÓãçãî ÜÞÒã. ºÐÛö Òë ÖÐÔÐÕæÕ ÒëÚÐàëáâÞþÒÐæì Óíâãî âíÜã, ÒÐÜ ÝÕÐÑåÞÔÝÐ áßÐçÐâÚã ßÕàÐÚÛîçëææÐ ÝÐ öÝèãî ÜÞÒã."
+msgid ""
+"The theme you selected does not support your current language. If you want "
+"to use this theme you need to switch to another language first."
+msgstr ""
+"ÂíÜÐ, ÐÑàÐÝÐï ÒÐÜö, ÝÕ ßÐÔâàëÜÛöÒÐÕ ÑïÓãçãî ÜÞÒã. ºÐÛö Òë ÖÐÔÐÕæÕ "
+"ÒëÚÐàëáâÞþÒÐæì Óíâãî âíÜã, ÒÐÜ ÝÕÐÑåÞÔÝÐ áßÐçÐâÚã ßÕàÐÚÛîçëææÐ ÝÐ öÝèãî ÜÞÒã."
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
@@ -1324,12 +1360,12 @@ msgstr "PC-9821 (256 ÚÞÛÕàÐþ)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 ÚÞÛÕàÐþ)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules ·ïÛñÝë"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ±ãàèâëÝÐÒë"
@@ -1341,7 +1377,8 @@ msgstr "·ÔÐÕææÐ, èâÞ ÓãÛìÝï '%s' ïèçí ÝÕÒïÔÞÜÐ."
#: engines/advancedDetector.cpp:318
msgid "Please, report the following data to the ScummVM team along with name"
-msgstr "ºÐÛö ÛÐáÚÐ, ßÕàÐÔÐÙæÕ ÝÐáâãßÝëï ÔÐÔ×ÕÝëï ÚÐÜÐÝÔ×Õ ScummVM àÐ×ÐÜ × ÝÐ×ÒÐÙ"
+msgstr ""
+"ºÐÛö ÛÐáÚÐ, ßÕàÐÔÐÙæÕ ÝÐáâãßÝëï ÔÐÔ×ÕÝëï ÚÐÜÐÝÔ×Õ ScummVM àÐ×ÐÜ × ÝÐ×ÒÐÙ"
#: engines/advancedDetector.cpp:320
msgid "of the game you tried to add and its version/language/etc.:"
@@ -1380,11 +1417,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "³~Ð~ÛÞþÝÐÕ ÜÕÝî"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "·ÐåÐÒÐæì ÓãÛìÝî:"
@@ -1393,22 +1434,37 @@ msgstr "·ÐåÐÒÐæì ÓãÛìÝî:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "·ÐåÐÒÐæì"
#: engines/dialogs.cpp:145
-msgid "Sorry, this engine does not currently provide in-game help. Please consult the README for basic information, and for instructions on how to obtain further assistance."
-msgstr "¿àÐÑÐçæÕ, ÐÛÕ Óíâë àãåÐÒöçÞÚ ßÐÚãÛì ÝÕ ßÐÔÐÕ ÔÐßÐÜÞÓö þÝãâàë ÓãÛìÝö. ºÐÛö ÛÐáÚÐ, ×ÒïàÝöæÕáï ÔÐ äÐÙÛÐ README ×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì ÔÐÛÕÙèãî ÔÐßÐÜÞÓã."
+msgid ""
+"Sorry, this engine does not currently provide in-game help. Please consult "
+"the README for basic information, and for instructions on how to obtain "
+"further assistance."
+msgstr ""
+"¿àÐÑÐçæÕ, ÐÛÕ Óíâë àãåÐÒöçÞÚ ßÐÚãÛì ÝÕ ßÐÔÐÕ ÔÐßÐÜÞÓö þÝãâàë ÓãÛìÝö. ºÐÛö "
+"ÛÐáÚÐ, ×ÒïàÝöæÕáï ÔÐ äÐÙÛÐ README ×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ "
+"öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì ÔÐÛÕÙèãî ÔÐßÐÜÞÓã."
#: engines/dialogs.cpp:234 engines/pegasus/pegasus.cpp:393
#, c-format
-msgid "Gamestate save failed (%s)! Please consult the README for basic information, and for instructions on how to obtain further assistance."
-msgstr "½Õ ÐâàëÜÐÛÐáï ×ÐåÐÒÐæì ÓãÛìÝî (%s)! ºÐÛö ÛÐáÚÐ, ×ÒïàÝöæÕáï ÔÐ äÐÙÛÐ README ×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì ÔÐÛÕÙèãî ÔÐßÐÜÞÓã."
+msgid ""
+"Gamestate save failed (%s)! Please consult the README for basic information, "
+"and for instructions on how to obtain further assistance."
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ×ÐåÐÒÐæì ÓãÛìÝî (%s)! ºÐÛö ÛÐáÚÐ, ×ÒïàÝöæÕáï ÔÐ äÐÙÛÐ README "
+"×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì ÔÐÛÕÙèãî "
+"ÔÐßÐÜÞÓã."
#: engines/dialogs.cpp:307 engines/mohawk/dialogs.cpp:109
#: engines/mohawk/dialogs.cpp:170 engines/tsage/dialogs.cpp:106
@@ -1441,24 +1497,28 @@ msgid "Could not apply fullscreen setting."
msgstr "½Õ ÜÐÓã þÖëæì ßÞþÝÐíÚàÐÝÝë àíÖëÜ."
#: engines/engine.cpp:461
-msgid "You appear to be playing this game directly\n"
+msgid ""
+"You appear to be playing this game directly\n"
"from the CD. This is known to cause problems,\n"
"and it is therefore recommended that you copy\n"
"the data files to your hard disk instead.\n"
"See the README file for details."
-msgstr "·ÔÐÕææÐ, Òë áßàÐÑãÕæÕ ×Ðßãáæöæì Óíâã ÓãÛìÝî ßàÐÜÐ\n"
+msgstr ""
+"·ÔÐÕææÐ, Òë áßàÐÑãÕæÕ ×Ðßãáæöæì Óíâã ÓãÛìÝî ßàÐÜÐ\n"
"× CD. ³íâÐ ×ÒëçÐÙÝÐ ÒëÚÛöÚÐÕ ßàÐÑÛÕÜë, ö âÐÜã\n"
"Üë àíÚÐÜÕÝÔãÕÜ áÚÐßöïÒÐæì äÐÙÛë ÔÐÔ×ÕÝëå ÓãÛìÝö\n"
"ÝÐ ÖÞàáâÚö ÔëáÚ. ¿ÐÔàÐÑï×ÝÐáæö ÜÞÖÝÐ ×ÝÐÙáæö þ\n"
"äÐÙÛÕ README."
#: engines/engine.cpp:472
-msgid "This game has audio tracks in its disk. These\n"
+msgid ""
+"This game has audio tracks in its disk. These\n"
"tracks need to be ripped from the disk using\n"
"an appropriate CD audio extracting tool in\n"
"order to listen to the game's music.\n"
"See the README file for details."
-msgstr "´ëáÚ ÓíâÐÙ ÓãÛìÝö þâàëÜÞþÒÐÕ ÓãÚÐÒëï ÔÐàÞÖÚö. ¦å\n"
+msgstr ""
+"´ëáÚ ÓíâÐÙ ÓãÛìÝö þâàëÜÞþÒÐÕ ÓãÚÐÒëï ÔÐàÞÖÚö. ¦å\n"
"ÝÕÐÑåÞÔÝÐ ßÕàÐßöáÐæì × ÔëáÚÐ × ÔÐßÐÜÞÓÐÙ\n"
"ÐÔßÐÒÕÔÝÐÙ ßàÐÓàÐÜë ÔÛï ÚÐßöïÒÐÝÝï\n"
"ÐþÔëñ ÔëáÚÐþ, ö âÞÛìÚö ßÐáÛï ÓíâÐÓÐ þ ÓãÛìÝö\n"
@@ -1467,12 +1527,23 @@ msgstr "´ëáÚ ÓíâÐÙ ÓãÛìÝö þâàëÜÞþÒÐÕ ÓãÚÐÒëï ÔÐàÞÖÚö. ¦å\n"
#: engines/engine.cpp:530
#, c-format
-msgid "Gamestate load failed (%s)! Please consult the README for basic information, and for instructions on how to obtain further assistance."
-msgstr "½Õ ÐâàëÜÐÛÐáï ßàÐçëâÐæì ×ÐåÐÒÐÝÝÕ ÓãÛìÝö (%s)! ºÐÛö ÛÐáÚÐ, ×ÒïàÝöæÕáï þ äÐÙÛ README ×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì ÔÐÛÕÙèãî ÔÐßÐÜÞÓã."
+msgid ""
+"Gamestate load failed (%s)! Please consult the README for basic information, "
+"and for instructions on how to obtain further assistance."
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ßàÐçëâÐæì ×ÐåÐÒÐÝÝÕ ÓãÛìÝö (%s)! ºÐÛö ÛÐáÚÐ, ×ÒïàÝöæÕáï þ äÐÙÛ "
+"README ×Ð ÑÐ×ÐÒÐÙ öÝäÐàÜÐæëïÙ, Ð âÐÚáÐÜÐ öÝáâàãÚæëïÜö ßàÐ âÞÕ, ïÚ ÐâàëÜÐæì "
+"ÔÐÛÕÙèãî ÔÐßÐÜÞÓã."
#: engines/engine.cpp:543
-msgid "WARNING: The game you are about to start is not yet fully supported by ScummVM. As such, it is likely to be unstable, and any saves you make might not work in future versions of ScummVM."
-msgstr "¿°¿ÏÀÍ´¶°½½µ: ³ãÛìÝï, ïÚãî Òë ×ÑöàÐÕæÕáï ×Ðßãáæöæì, ïèçí ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ ScummVM æÐÛÚÐÜ. ÏÝÐ, åãâçíÙ ×Ð þáñ, ÝÕ ÑãÔ×Õ ßàÐæÐÒÐæì áâÐÑöÛìÝÐ, ö ×ÐåÐÒÐÝÝö ÓãÛìÝïþ ÜÞÓãæì ÝÕ ßàÐæÐÒÐæì ã ÑãÔãçëå ÒÕàáöïå ScummVM."
+msgid ""
+"WARNING: The game you are about to start is not yet fully supported by "
+"ScummVM. As such, it is likely to be unstable, and any saves you make might "
+"not work in future versions of ScummVM."
+msgstr ""
+"¿°¿ÏÀÍ´¶°½½µ: ³ãÛìÝï, ïÚãî Òë ×ÑöàÐÕæÕáï ×Ðßãáæöæì, ïèçí ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ "
+"ScummVM æÐÛÚÐÜ. ÏÝÐ, åãâçíÙ ×Ð þáñ, ÝÕ ÑãÔ×Õ ßàÐæÐÒÐæì áâÐÑöÛìÝÐ, ö "
+"×ÐåÐÒÐÝÝö ÓãÛìÝïþ ÜÞÓãæì ÝÕ ßàÐæÐÒÐæì ã ÑãÔãçëå ÒÕàáöïå ScummVM."
#: engines/engine.cpp:546
msgid "Start anyway"
@@ -1496,8 +1567,12 @@ msgstr "¿àÐÜë FM ALSA"
#: audio/mididrv.cpp:209
#, c-format
-msgid "The selected audio device '%s' was not found (e.g. might be turned off or disconnected)."
-msgstr "°ÑàÐÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÑëÛÐ ×ÝÞÙÔ×ÕÝÐ (ÜÐÓçëÜÐ, ïÝÐ ÒëÚÛîçÐÝÐ æö ÝÕ ßÐÔÚÛîçÐÝÐ)."
+msgid ""
+"The selected audio device '%s' was not found (e.g. might be turned off or "
+"disconnected)."
+msgstr ""
+"°ÑàÐÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÑëÛÐ ×ÝÞÙÔ×ÕÝÐ (ÜÐÓçëÜÐ, ïÝÐ ÒëÚÛîçÐÝÐ æö ÝÕ "
+"ßÐÔÚÛîçÐÝÐ)."
#: audio/mididrv.cpp:209 audio/mididrv.cpp:221 audio/mididrv.cpp:257
#: audio/mididrv.cpp:272
@@ -1506,18 +1581,30 @@ msgstr "ÁßàÐÑãî ÒëÚÐàëáâÐæì öÝèãî ÔÐáâãßÝãî ßàëÛÐÔã..."
#: audio/mididrv.cpp:221
#, c-format
-msgid "The selected audio device '%s' cannot be used. See log file for more information."
-msgstr "°ÑàÐÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÜÞÖÐ Ñëæì áÚÐàëáâÐÝÐ. ³ÛïÔ×öæÕ äÐÙÛ ßàÐâÐÚÞÛã ÔÛï ÑÞÛìè ßÐÔàÐÑï×ÝÐÙ öÝäÐàÜÐæëö."
+msgid ""
+"The selected audio device '%s' cannot be used. See log file for more "
+"information."
+msgstr ""
+"°ÑàÐÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÜÞÖÐ Ñëæì áÚÐàëáâÐÝÐ. ³ÛïÔ×öæÕ äÐÙÛ "
+"ßàÐâÐÚÞÛã ÔÛï ÑÞÛìè ßÐÔàÐÑï×ÝÐÙ öÝäÐàÜÐæëö."
#: audio/mididrv.cpp:257
#, c-format
-msgid "The preferred audio device '%s' was not found (e.g. might be turned off or disconnected)."
-msgstr "¿ÕàÐÒÐÖÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÑëÛÐ ×ÝÞÙÔ×ÕÝÐ (ÜÐÓçëÜÐ, ïÝÐ ÒëÚÛîçÐÝÐ æö ÝÕ ßÐÔÚÛîçÐÝÐ)."
+msgid ""
+"The preferred audio device '%s' was not found (e.g. might be turned off or "
+"disconnected)."
+msgstr ""
+"¿ÕàÐÒÐÖÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÑëÛÐ ×ÝÞÙÔ×ÕÝÐ (ÜÐÓçëÜÐ, ïÝÐ ÒëÚÛîçÐÝÐ æö "
+"ÝÕ ßÐÔÚÛîçÐÝÐ)."
#: audio/mididrv.cpp:272
#, c-format
-msgid "The preferred audio device '%s' cannot be used. See log file for more information."
-msgstr "¿ÕàÐÒÐÖÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÜÞÖÐ Ñëæì áÚÐàëáâÐÝÐ. ³ÛïÔ×öæÕ äÐÙÛ ßàÐâÐÚÞÛã ÔÛï ÑÞÛìè ßÐÔàÐÑï×ÝÐÙ öÝäÐàÜÐæëö."
+msgid ""
+"The preferred audio device '%s' cannot be used. See log file for more "
+"information."
+msgstr ""
+"¿ÕàÐÒÐÖÝÐï ÓãÚÐÒÐï ßàëÛÐÔÐ '%s' ÝÕ ÜÞÖÐ Ñëæì áÚÐàëáâÐÝÐ. ³ÛïÔ×öæÕ äÐÙÛ "
+"ßàÐâÐÚÞÛã ÔÛï ÑÞÛìè ßÐÔàÐÑï×ÝÐÙ öÝäÐàÜÐæëö."
#: audio/mods/paula.cpp:196
msgid "Amiga Audio Emulator"
@@ -1683,19 +1770,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "±Õ× ßÐÒÕÛöçíÝÝï"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "ºÐàíÚæëï áãÐÔÝÞáöÝ ÑÐÚÞþ ãÚÛîçÐÝÐ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "ºÐàíÚæëï áãÐÔÝÞáöÝ ÑÐÚÞþ ÒëÚÛîçÐÝÐ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "°ÚâëþÝë ÓàÐäöçÝë äöÛìâà:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "°ÚÞÝÝë àíÖëÜ"
@@ -2193,7 +2280,8 @@ msgstr "¿àë×ÝÐçëæì Ô×ÕïÝÝÕ ßÐ ßàÐÒÐÙ ßáâàëçæë"
#: backends/platform/wince/wince-sdl.cpp:520
msgid "You must map a key to the 'Right Click' action to play this game"
-msgstr "²ë ßÐÒöÝÝë ßàë×ÝÐçëæì ÚÛÐÒöèã ÝÐ Ô×ÕïÝÝÕ 'Right Click' ÔÛï ÓíâÐÙ ÓãÛìÝö"
+msgstr ""
+"²ë ßÐÒöÝÝë ßàë×ÝÐçëæì ÚÛÐÒöèã ÝÐ Ô×ÕïÝÝÕ 'Right Click' ÔÛï ÓíâÐÙ ÓãÛìÝö"
#: backends/platform/wince/wince-sdl.cpp:529
msgid "Map hide toolbar action"
@@ -2201,7 +2289,8 @@ msgstr "¿àë×ÝÐçëæì Ô×ÕïÝÝÕ 'áåÐÒÐæì ßÐÝíÛì öÝáâàãÜÕÝâÐþ'"
#: backends/platform/wince/wince-sdl.cpp:533
msgid "You must map a key to the 'Hide toolbar' action to play this game"
-msgstr "²ë ßÐÒöÝÝë ßàë×ÝÐçëæì ÚÛÐÒöèã ÝÐ Ô×ÕïÝÝÕ 'Hide toolbar' ÔÛï ÓíâÐÙ ÓãÛìÝö"
+msgstr ""
+"²ë ßÐÒöÝÝë ßàë×ÝÐçëæì ÚÛÐÒöèã ÝÐ Ô×ÕïÝÝÕ 'Hide toolbar' ÔÛï ÓíâÐÙ ÓãÛìÝö"
#: backends/platform/wince/wince-sdl.cpp:542
msgid "Map Zoom Up action (optional)"
@@ -2212,8 +2301,11 @@ msgid "Map Zoom Down action (optional)"
msgstr "¿àë×ÝÐçëæì Ô×ÕïÝÝÕ ¿ÐÜÕÝèëæì ¼ÐèâÐÑ (ÝÕÐÑÐÒï×ÚÞÒÐ)"
#: backends/platform/wince/wince-sdl.cpp:553
-msgid "Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
-msgstr "½Õ ×ÐÑãÔ×ìæÕáï ßàë×ÝÐçëæì ÚÛÐÒöèã ÔÛï Ô×ÕïÝÝï 'Hide Toolbar', ÚÐÑ ãÑÐçëæì ãÒÕáì öÝÒÕÝâÐà ã ÓãÛìÝö"
+msgid ""
+"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
+msgstr ""
+"½Õ ×ÐÑãÔ×ìæÕáï ßàë×ÝÐçëæì ÚÛÐÒöèã ÔÛï Ô×ÕïÝÝï 'Hide Toolbar', ÚÐÑ ãÑÐçëæì "
+"ãÒÕáì öÝÒÕÝâÐà ã ÓãÛìÝö"
#: backends/updates/macosx/macosx-updates.mm:67
msgid "Check for Updates..."
@@ -2224,67 +2316,90 @@ msgstr "¿àÐÒïàÐî ÐÑÝÐþÛÕÝÝö..."
#: engines/neverhood/detection.cpp:160 engines/sci/detection.cpp:404
#: engines/toltecs/detection.cpp:200 engines/zvision/detection_tables.h:51
msgid "Use original save/load screens"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã/çëâÐÝÝö ÓãÛìÝö"
+msgstr "²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã/çëâÐÝÝï ÓãÛìÝö"
#: engines/agi/detection.cpp:148 engines/cine/detection.cpp:71
#: engines/drascula/detection.cpp:303 engines/dreamweb/detection.cpp:48
#: engines/neverhood/detection.cpp:161 engines/sci/detection.cpp:405
#: engines/toltecs/detection.cpp:201
msgid "Use the original save/load screens, instead of the ScummVM ones"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã ö ×ÐåÐÒÐÝÝï ÓãÛìÝö ×ÐÜÕáâ ×àÞÑÛÕÝëå ã ScummVM"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë çëâÐÝÝï ö ×ÐåÐÒÐÝÝï ÓãÛìÝö ×ÐÜÕáâ "
+"×àÞÑÛÕÝëå ã ScummVM"
#: engines/agi/detection.cpp:157
msgid "Use an alternative palette"
msgstr "²ëÚÐàëáâÞþÒÐæì ÐÛìâíàÝÐâëþÝãî ßÐÛöâàã"
#: engines/agi/detection.cpp:158
-msgid "Use an alternative palette, common for all Amiga games. This was the old behavior"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÐÛìâíàÝÐâëþÝãî ßÐÛöâàã ÔÛï þáöå ÓãÛìÝïþ Amiga. ³íâÐ ÑëÛö áâÐàëï ßÐÒÞÔ×öÝë"
+msgid ""
+"Use an alternative palette, common for all Amiga games. This was the old "
+"behavior"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÐÛìâíàÝÐâëþÝãî ßÐÛöâàã ÔÛï þáöå ÓãÛìÝïþ Amiga. ³íâÐ ÑëÛö "
+"áâÐàëï ßÐÒÞÔ×öÝë"
#: engines/agi/detection.cpp:167
msgid "Mouse support"
msgstr "¿ÐÔâàëÜÚÐ Üëèë"
#: engines/agi/detection.cpp:168
-msgid "Enables mouse support. Allows to use mouse for movement and in game menus."
-msgstr "ÃÚÛîçÐÕ ßÐÔâàëÜÚã Üëèë. ´Ð×ÒÐÛïÕ ÒëÚÐàëáâÞþÒÐæì Üëè ÔÛï ßÕàÐÜïèçíÝÝï ö þ ÜÕÝî ÓãÛìÝö."
-
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+msgid ""
+"Enables mouse support. Allows to use mouse for movement and in game menus."
+msgstr ""
+"ÃÚÛîçÐÕ ßÐÔâàëÜÚã Üëèë. ´Ð×ÒÐÛïÕ ÒëÚÐàëáâÞþÒÐæì Üëè ÔÛï ßÕàÐÜïèçíÝÝï ö þ "
+"ÜÕÝî ÓãÛìÝö."
+
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Ã×ÝÐÒöæì ÓãÛìÝî:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Ã×ÝÐÒöæì"
#: engines/agos/saveload.cpp:160 engines/scumm/scumm.cpp:2377
#, c-format
-msgid "Failed to load game state from file:\n"
+msgid ""
+"Failed to load game state from file:\n"
"\n"
"%s"
-msgstr "½Õ ÐâàëÜÐÛÐáï ×ÐÓàã×öæì ÓãÛìÝî × äÐÙÛÐ:\n"
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ×ÐÓàã×öæì ÓãÛìÝî × äÐÙÛÐ:\n"
"\n"
"%s"
#: engines/agos/saveload.cpp:195 engines/scumm/scumm.cpp:2370
#, c-format
-msgid "Failed to save game state to file:\n"
+msgid ""
+"Failed to save game state to file:\n"
"\n"
"%s"
-msgstr "½Õ ÐâàëÜÐÛÐáï ×ÐßöáÐæì ÓãÛìÝî þ äÐÙÛ:\n"
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ×ÐßöáÐæì ÓãÛìÝî þ äÐÙÛ:\n"
"\n"
"%s"
#: engines/agos/saveload.cpp:203 engines/scumm/scumm.cpp:2388
#, c-format
-msgid "Successfully saved game state in file:\n"
+msgid ""
+"Successfully saved game state in file:\n"
"\n"
"%s"
-msgstr "³ãÛìÝï ßÐáßïåÞÒÐ ×ÐåÐÒÐÝÐ þ äÐÙÛ:\n"
+msgstr ""
+"³ãÛìÝï ßÐáßïåÞÒÐ ×ÐåÐÒÐÝÐ þ äÐÙÛ:\n"
"\n"
"%s"
@@ -2302,16 +2417,21 @@ msgid "Enable Color Blind Mode by default"
msgstr "ÃÚÛîçëæì àíÖëÜ ÔÛï ÛîÔ×ÕÙ áÐ áÛÐÑëÜ ãáßàëÜÐÝÝÕÜ ÚÞÛÕàã"
#: engines/drascula/saveload.cpp:47
-msgid "ScummVM found that you have old savefiles for Drascula that should be converted.\n"
-"The old save game format is no longer supported, so you will not be able to load your games if you don't convert them.\n"
+msgid ""
+"ScummVM found that you have old savefiles for Drascula that should be "
+"converted.\n"
+"The old save game format is no longer supported, so you will not be able to "
+"load your games if you don't convert them.\n"
"\n"
-"Press OK to convert them now, otherwise you will be asked again the next time you start the game.\n"
-""
-msgstr "ScummVM ÒëïÒöþ ã ÒÐá ×ÐåÐÒÐÝÝö ÓãÛìÝö Drascula ã áâÐàëÜ äÐàÜÐæÕ.\n"
-"ÁâÐàë äÐàÜÐâ ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ, ö, ÚÐÑ ×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ïÝë ßÐÒöÝÝë Ñëæì ßÕàÐÒÕÔ×ÕÝë þ ÝÞÒë äÐàÜÐâ.\n"
+"Press OK to convert them now, otherwise you will be asked again the next "
+"time you start the game.\n"
+msgstr ""
+"ScummVM ÒëïÒöþ ã ÒÐá ×ÐåÐÒÐÝÝö ÓãÛìÝö Drascula ã áâÐàëÜ äÐàÜÐæÕ.\n"
+"ÁâÐàë äÐàÜÐâ ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ, ö, ÚÐÑ ×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ïÝë "
+"ßÐÒöÝÝë Ñëæì ßÕàÐÒÕÔ×ÕÝë þ ÝÞÒë äÐàÜÐâ.\n"
"\n"
-"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÒÕáæö öå ã ÝÞÒë äÐàÜÐâ ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã ÓíâÐ ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ×ÝÞþ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
-""
+"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÒÕáæö öå ã ÝÞÒë äÐàÜÐâ ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã "
+"ÓíâÐ ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ×ÝÞþ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
#: engines/dreamweb/detection.cpp:57
msgid "Use bright palette mode"
@@ -2462,12 +2582,14 @@ msgid "Choose Spell"
msgstr "°ÑàÐæì ×ÐÓÐÒÞà"
#: engines/kyra/sound_midi.cpp:477
-msgid "You appear to be using a General MIDI device,\n"
+msgid ""
+"You appear to be using a General MIDI device,\n"
"but your game only supports Roland MT32 MIDI.\n"
"We try to map the Roland MT32 instruments to\n"
"General MIDI ones. It is still possible that\n"
"some tracks sound incorrect."
-msgstr "·ÔÐÕææÐ, Òë áßàÐÑãÕæÕ ÒëÚÐàëáâÞþÒÐæì ßàëÛÐÔã\n"
+msgstr ""
+"·ÔÐÕææÐ, Òë áßàÐÑãÕæÕ ÒëÚÐàëáâÞþÒÐæì ßàëÛÐÔã\n"
"General MIDI, ÐÛÕ ÓíâÐï ÓãÛìÝï ßÐÔâàëÜÛöÒÐÕ âÞÛìÚö\n"
"Roland MT32 MIDI. ¼ë ßÐáßàÐÑãÕÜ ßÐÔÐÑàÐæì General\n"
"MIDI-ßàëÛÐÔë, ßÐÔÞÑÝëï ÔÐ Roland MT32, ÐÛÕ\n"
@@ -2476,42 +2598,45 @@ msgstr "·ÔÐÕææÐ, Òë áßàÐÑãÕæÕ ÒëÚÐàëáâÞþÒÐæì ßàëÛÐÔã\n"
#: engines/kyra/saveload_eob.cpp:557
#, c-format
-msgid "The following original save game file has been found in your game path:\n"
+msgid ""
+"The following original save game file has been found in your game path:\n"
"\n"
"%s %s\n"
"\n"
"Do you wish to use this save game file with ScummVM?\n"
"\n"
-""
-msgstr "½öÖíÙ×ÓÐÔÐÝë äÐÙÛ ×ÐåÐÒÐÝÝï × ÐàëÓöÝÐÛìÝÐÙ ÓãÛìÝö Ñëþ ×ÝÞÙÔ×ÕÝë þ ÒÐèÐÙ ÓãÛìÝïÒÞÙ ÔëàíÚâÞàëö:\n"
+msgstr ""
+"½öÖíÙ×ÓÐÔÐÝë äÐÙÛ ×ÐåÐÒÐÝÝï × ÐàëÓöÝÐÛìÝÐÙ ÓãÛìÝö Ñëþ ×ÝÞÙÔ×ÕÝë þ ÒÐèÐÙ "
+"ÓãÛìÝïÒÞÙ ÔëàíÚâÞàëö:\n"
"\n"
"%s %s\n"
"\n"
"Æö ÖÐÔÐÕæÕ ÒëÚÐàëáâÞþÒÐæì ÓíâÐÕ ×ÐåÐÒÐÝÝÕ þ ScummVM?\n"
"\n"
-""
#: engines/kyra/saveload_eob.cpp:590
#, c-format
-msgid "A save game file was found in the specified slot %d. Overwrite?\n"
+msgid ""
+"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
-""
-msgstr "à Ð×ÝÐçÐÝëÜ áÛÞæÕ %d ãÖÞ ñáæì ×ÐåÐÒÐÝÝÕ ÓãÛìÝö. ¿ÕàÐ×ÐßöáÐæì?\n"
+msgstr ""
+"à Ð×ÝÐçÐÝëÜ áÛÞæÕ %d ãÖÞ ñáæì ×ÐåÐÒÐÝÝÕ ÓãÛìÝö. ¿ÕàÐ×ÐßöáÐæì?\n"
"\n"
-""
#: engines/kyra/saveload_eob.cpp:623
#, c-format
-msgid "%d original save game files have been successfully imported into\n"
-"ScummVM. If you want to manually import original save game files later you will\n"
-"need to open the ScummVM debug console and use the command 'import_savefile'.\n"
+msgid ""
+"%d original save game files have been successfully imported into\n"
+"ScummVM. If you want to manually import original save game files later you "
+"will\n"
+"need to open the ScummVM debug console and use the command "
+"'import_savefile'.\n"
"\n"
-""
-msgstr "%d ÐàëÓöÝÐÛìÝëå äÐÙÛÐþ ×ÐåÐÒÐÝÝï ÑëÛö ßÐáßïåÞÒÐ öÜßÐàâÐÒÐÝë þ ScummVM.\n"
+msgstr ""
+"%d ÐàëÓöÝÐÛìÝëå äÐÙÛÐþ ×ÐåÐÒÐÝÝï ÑëÛö ßÐáßïåÞÒÐ öÜßÐàâÐÒÐÝë þ ScummVM.\n"
"ºÐÛö Òë ßÐÖÐÔÐÕæÕ öÜßÐàâÐÒÐæì ÐàëÓöÝÐÛìÝëï ×ÐåÐÒÐÝÝö, ÒÐÜ âàíÑÐ ÑãÔ×Õ\n"
"ÐÔÚàëæì ÐÔÛÐÔÐçÝãî ÚÐÝáÞÛì ScummVM ö þÒÕáæö ÚÐÜÐÝÔã 'import_savefile'.\n"
"\n"
-""
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2557,41 +2682,58 @@ msgstr "ÀÐáæïÓÒÐÕ ÒöÔíÐ ßàÐ áâÒÐàíÝÝÕ ÓãÛìÝö âÐÚ, èâÞ ïÝÞ ×ÐÙÜÐÕ þÒÕáì íÚàÐÝ"
#: engines/parallaction/saveload.cpp:133
#, c-format
-msgid "Can't save game in slot %i\n"
+msgid ""
+"Can't save game in slot %i\n"
"\n"
-""
-msgstr "½Õ ÜÐÓã ×ÐåÐÒÐæì ÓãÛìÝî þ ßÐ×öæëî %i\n"
+msgstr ""
+"½Õ ÜÐÓã ×ÐåÐÒÐæì ÓãÛìÝî þ ßÐ×öæëî %i\n"
"\n"
-""
+
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "·ÐÓàã×öæì äÐÙÛ"
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "·ÐÓàãÖÐî ÓãÛìÝî..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "·ÐåÐÒÐæì äÐÙÛ"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "·ÐåÞþÒÐî ÓãÛìÝî..."
#: engines/parallaction/saveload.cpp:272
-msgid "ScummVM found that you have old savefiles for Nippon Safes that should be renamed.\n"
-"The old names are no longer supported, so you will not be able to load your games if you don't convert them.\n"
+msgid ""
+"ScummVM found that you have old savefiles for Nippon Safes that should be "
+"renamed.\n"
+"The old names are no longer supported, so you will not be able to load your "
+"games if you don't convert them.\n"
"\n"
"Press OK to convert them now, otherwise you will be asked next time.\n"
-""
-msgstr "ScummVM ×ÝÐÙèÞþ ã ÒÐá áâÐàëï ×ÐåÐÒÐÝÝö ÓãÛìÝö Nippon Safes, ïÚöï ÝÕÐÑåÞÔÝÐ ßÕàÐÝÐ×ÒÐæì. ÁâÐàëï ÝÐ×Òë ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐîææÐ, ö âÐÜã Òë ÝÕ ×ÜÞÖÐæÕ ×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ÚÐÛö ÝÕ ßÕàÐÝÐ×ÐÒïæÕ öå.\n"
+msgstr ""
+"ScummVM ×ÝÐÙèÞþ ã ÒÐá áâÐàëï ×ÐåÐÒÐÝÝö ÓãÛìÝö Nippon Safes, ïÚöï ÝÕÐÑåÞÔÝÐ "
+"ßÕàÐÝÐ×ÒÐæì. ÁâÐàëï ÝÐ×Òë ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐîææÐ, ö âÐÜã Òë ÝÕ ×ÜÞÖÐæÕ "
+"×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ÚÐÛö ÝÕ ßÕàÐÝÐ×ÐÒïæÕ öå.\n"
"\n"
-"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÝÐ×ÒÐæì öå ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã ÓíâÐÕ Ö ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
-""
+"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÝÐ×ÒÐæì öå ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã ÓíâÐÕ Ö "
+"ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
#: engines/parallaction/saveload.cpp:319
msgid "ScummVM successfully converted all your savefiles."
msgstr "ScummVM ßÐáßïåÞÒÐ ßÕàÐþâÒÐàëþ ãáÕ ÒÐèë ×ÐåÐÒÐÝÝö ÓãÛìÝïþ."
#: engines/parallaction/saveload.cpp:321
-msgid "ScummVM printed some warnings in your console window and can't guarantee all your files have been converted.\n"
+msgid ""
+"ScummVM printed some warnings in your console window and can't guarantee all "
+"your files have been converted.\n"
"\n"
"Please report to the team."
-msgstr "ScummVM ÝÐßöáÐþ ÝÕÚÐÛìÚö ßÐßïàíÔÖÐÝÝïþ ã ÐÚÝÞ ÚÐÝáÞÛö ö ÝÕ ×ÜÞÓ ßÕàÐþâÒÐàëæì ãáÕ äÐÙÛë.\n"
+msgstr ""
+"ScummVM ÝÐßöáÐþ ÝÕÚÐÛìÚö ßÐßïàíÔÖÐÝÝïþ ã ÐÚÝÞ ÚÐÝáÞÛö ö ÝÕ ×ÜÞÓ ßÕàÐþâÒÐàëæì "
+"ãáÕ äÐÙÛë.\n"
"\n"
"ºÐÛö ÛÐáÚÐ, ßÐÒÕÔÐÜöæÕ ßàÐ ÓíâÐ ÚÐÜÐÝÔ×Õ ScummVM."
@@ -2601,7 +2743,7 @@ msgstr "½ïßàÐÒöÛìÝÐÕ öÜï äÐÙÛÐ ×ÐåÐÒÐÝÝï"
#: engines/pegasus/pegasus.cpp:2507
msgid "Up/Zoom In/Move Forward/Open Doors"
-msgstr "ÃÒÕàå/¼ÐèâÐÑ+/½ÐßÕàÐÔ/°ÔçëÝöæì Ô×ÒÕàë"
+msgstr "ÃÒÕàå/¿ÐÒïÛ. ÜÐèâÐÑ/½ÐßÕàÐÔ/°ÔçëÝöæì Ô×ÒÕàë"
#: engines/pegasus/pegasus.cpp:2508
msgid "Down/Zoom Out"
@@ -2645,7 +2787,9 @@ msgstr "½Õ àÐÑöæì ÐßàÐÚáöÜÐæëî ÚÞÛÕàÐþ EGA (ßÞþÝÐÚÐÛïàÞÒëï äÞÝë)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
-msgstr "¿àÐßãáÚÐÕ ßàÐåÞÔ ÐßàÐÚáöÜÐæëö ÚÞÛÕàÐþ EGA, ÓàÐäöÚÐ ÑãÔ×Õ ßÐÚÐ×ÐÝÐ × ãáöÜö ÚÞÛÕàÐÜö"
+msgstr ""
+"¿àÐßãáÚÐÕ ßàÐåÞÔ ÐßàÐÚáöÜÐæëö ÚÞÛÕàÐþ EGA, ÓàÐäöÚÐ ÑãÔ×Õ ßÐÚÐ×ÐÝÐ × ãáöÜö "
+"ÚÞÛÕàÐÜö"
#: engines/sci/detection.cpp:384
msgid "Enable high resolution graphics"
@@ -2668,8 +2812,12 @@ msgid "Use IMF/Yamaha FB-01 for MIDI output"
msgstr "²ëÚÐàëáâÞþÒÐæì IMF/Yamaha FB-01 ÔÛï ÒëÒÐÔã MIDI"
#: engines/sci/detection.cpp:415
-msgid "Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI output"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÓãÚÐÒãî ÚÐàâã IBM Music Feature æö ÜÞÔãÛì áöÝâí×ã Yamaha FB-01 FM ÔÛï MIDI"
+msgid ""
+"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
+"output"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÓãÚÐÒãî ÚÐàâã IBM Music Feature æö ÜÞÔãÛì áöÝâí×ã Yamaha "
+"FB-01 FM ÔÛï MIDI"
#: engines/sci/detection.cpp:425
msgid "Use CD audio"
@@ -2677,23 +2825,30 @@ msgstr "²ëÚÐàëáâÞþÒÐæì CD-ÐþÔëñ"
#: engines/sci/detection.cpp:426
msgid "Use CD audio instead of in-game audio, if available"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÓãÚÐÒëï ÔÐàÞÖÚö × CD ×ÐÜÕáâ Üã×ëÚö × äÐÙÛÐþ ÓãÛìÝö (ÚÐÛö ÔÐáâãßÝÐ)"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÓãÚÐÒëï ÔÐàÞÖÚö × CD ×ÐÜÕáâ Üã×ëÚö × äÐÙÛÐþ ÓãÛìÝö (ÚÐÛö "
+"ÔÐáâãßÝÐ)"
#: engines/sci/detection.cpp:436
msgid "Use Windows cursors"
msgstr "²ëÚÐàëáâÞþÒÐæì ÚãàáÞàë Windows"
#: engines/sci/detection.cpp:437
-msgid "Use the Windows cursors (smaller and monochrome) instead of the DOS ones"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÚãàáÞàë Windows (ÜÕÝèëï ßÐ ßÐÜÕàë ö ÐÔÝÐÚÐÛïàÞÒëï) ×ÐÜÕáâ ÚãàáÞàÐþ DOS"
+msgid ""
+"Use the Windows cursors (smaller and monochrome) instead of the DOS ones"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÚãàáÞàë Windows (ÜÕÝèëï ßÐ ßÐÜÕàë ö ÐÔÝÐÚÐÛïàÞÒëï) ×ÐÜÕáâ "
+"ÚãàáÞàÐþ DOS"
#: engines/sci/detection.cpp:447
msgid "Use silver cursors"
msgstr "²ëÚÐàëáâÞþÒÐæì áàíÑÝëï ÚãàáÞàë"
#: engines/sci/detection.cpp:448
-msgid "Use the alternate set of silver cursors, instead of the normal golden ones"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÐÛìâíàÝÐâëþÝë ÝÐÑÞà áàíÑÝëå ÚãàáÞàÐþ ×ÐÜÕáâ ×ÒëçÐÙÝëå ×ÐÛÐâëå"
+msgid ""
+"Use the alternate set of silver cursors, instead of the normal golden ones"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÐÛìâíàÝÐâëþÝë ÝÐÑÞà áàíÑÝëå ÚãàáÞàÐþ ×ÐÜÕáâ ×ÒëçÐÙÝëå ×ÐÛÐâëå"
#: engines/scumm/dialogs.cpp:176
#, c-format
@@ -2871,7 +3026,7 @@ msgstr "³ãçÝÐáæì Üã×ëÚö ßÐÒïÛöçëæì / ßÐÜÕÝèëæì"
#: engines/scumm/help.cpp:89
msgid "Text speed slower / faster"
-msgstr "ÅãâÚÐáæì âíÚáâã åãâçíÙ / ßÐÒÞÛìÝÕÙ"
+msgstr "ÅãâÚÐáæì âíÚáâã ßÐÒÞÛìÝÕÙ / åãâçíÙ"
#: engines/scumm/help.cpp:90
msgid "Simulate left mouse button"
@@ -3362,37 +3517,111 @@ msgstr "ÅãâÚÐáæì âëâàÐþ: "
#: engines/scumm/scumm.cpp:1832
#, c-format
-msgid "Native MIDI support requires the Roland Upgrade from LucasArts,\n"
+msgid ""
+"Native MIDI support requires the Roland Upgrade from LucasArts,\n"
"but %s is missing. Using AdLib instead."
-msgstr "ÀíÖëÜ \"àÞÔÝÐÓÐ\" MIDI ßÐâàÐÑãÕ ÐÑÝÐþÛÕÝÝÕ Roland Upgrade ÐÔ\n"
+msgstr ""
+"ÀíÖëÜ \"àÞÔÝÐÓÐ\" MIDI ßÐâàÐÑãÕ ÐÑÝÐþÛÕÝÝÕ Roland Upgrade ÐÔ\n"
"LucasArts, ÐÛÕ ÝÕ åÐßÐÕ %s. ¿ÕàÐÚÛîçÐîáï ÝÐ AdLib."
#: engines/scumm/scumm.cpp:2644
-msgid "Usually, Maniac Mansion would start now. But for that to work, the game files for Maniac Mansion have to be in the 'Maniac' directory inside the Tentacle game directory, and the game has to be added to ScummVM."
-msgstr "·ÐàÐ× ßÐÒöÝÝÐ ×ÐßãáæöææÐ ÓãÛìÝï Maniac Mansion. °ÛÕ ÚÐÑ ÓíâÐ ßàÐæÐÒÐÛÐ, äÐÙÛë ÓãÛìÝö Maniac Mansion ßÐÒöÝÝë Ñëæì áÚÐßöïÒÐÝë þ ÔëàíÚâÞàëî 'Maniac' ãÝãâàë ÔëàíÚâÞàëö ÓãÛìÝö Tentacle ö áÐÜÐ ÓãÛìÝï ßÐÒöÝÝÐ Ñëæì ÔÐÔÐÔ×ÕÝÐ þ ScummVM."
+msgid ""
+"Usually, Maniac Mansion would start now. But for that to work, the game "
+"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
+"Tentacle game directory, and the game has to be added to ScummVM."
+msgstr ""
+"·ÐàÐ× ßÐÒöÝÝÐ ×ÐßãáæöææÐ ÓãÛìÝï Maniac Mansion. °ÛÕ ÚÐÑ ÓíâÐ ßàÐæÐÒÐÛÐ, "
+"äÐÙÛë ÓãÛìÝö Maniac Mansion ßÐÒöÝÝë Ñëæì áÚÐßöïÒÐÝë þ ÔëàíÚâÞàëî 'Maniac' "
+"ãÝãâàë ÔëàíÚâÞàëö ÓãÛìÝö Tentacle ö áÐÜÐ ÓãÛìÝï ßÐÒöÝÝÐ Ñëæì ÔÐÔÐÔ×ÕÝÐ þ "
+"ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
-msgid "Could not find the 'Loom' Macintosh executable to read the\n"
+msgid ""
+"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
-msgstr "½Õ ÐâàëÜÐÛÐáï ×ÝÐÙáæö ÒëÚÐÝÐÛìÝë äÐÙÛ 'Loom' Macintosh, ÚÐÑ ßàÐçëâÐæì\n"
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ×ÝÐÙáæö ÒëÚÐÝÐÛìÝë äÐÙÛ 'Loom' Macintosh, ÚÐÑ ßàÐçëâÐæì\n"
"ÔÐÔ×ÕÝëï ßàÐ öÝáâàãÜÕÝâë. ¼ã×ëÚÐ ÑãÔ×Õ ÒëÚÛîçÐÝÐ."
#: engines/scumm/players/player_v5m.cpp:107
-msgid "Could not find the 'Monkey Island' Macintosh executable to read the\n"
+msgid ""
+"Could not find the 'Monkey Island' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
-msgstr "½Õ ÐâàëÜÐÛÐáï ×ÝÐÙáæö ÒëÚÐÝÐÛìÝë äÐÙÛ 'Monkey Island' Macintosh, ÚÐÑ ßàÐçëâÐæì\n"
+msgstr ""
+"½Õ ÐâàëÜÐÛÐáï ×ÝÐÙáæö ÒëÚÐÝÐÛìÝë äÐÙÛ 'Monkey Island' Macintosh, ÚÐÑ "
+"ßàÐçëâÐæì\n"
"ÔÐÔ×ÕÝëï ßàÐ öÝáâàãÜÕÝâë. ¼ã×ëÚÐ ÑãÔ×Õ ÒëÚÛîçÐÝÐ."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã/çëâÐÝÝï ÓãÛìÝö"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"ºÝÞßÚÐ \"ÄÐÙÛë\" þ ÓãÛìÝö ßÐÚÐ×ÒÐÕ ÐàëÓöÝÐÛìÝë ÔëïÛÞÓ ×ÐåÐÒÐÝÝï, Ð ÝÕ ÜÕÝî "
+"ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "¿ÕàÐåÞÔë ßÐÜöÖ áæíÝÐÜö × ßöÚáÕÛö×ÐæëïÙ"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "¿àë ×ÜÕÝÕ áæíÝ ÐÔÑëÒÐÕææÐ ßÕàÐåÞÔ × àÐÝÔÐÜö×ÐÒÐÝëÜö ßöÚáÕÛïÜö"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "½Õ ßÐÚÐ×ÒÐæì åÞâáßÞâë ßàë ÝÐÒïÔ×ÕÝÝö Üëèèã"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"¿ÐÚÐ×ÒÐæì ÝÐ×Òë åÞâáßÞâÐþ âÞÛìÚö ßÐáÛï ÚÛöÚã ßÐ öå ÐÑÞ ßÐáÛï ÝÐæöáÚã ÝÐ "
+"ÚÝÞßÚã Ô×ÕïÝÝï"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "¿ÐÚÐ×ÒÐæì ßÐàâàíâë ÓÕàÞïþ"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "¿ÐÚÐ×ÒÐæì ßÐàâàíâë ÓÕàÞïþ ßÐÔçÐá ÔëïÛÞÓÐþ"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "´ëïÛÞÓö ×Ðï×ÔÖÐîæì"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "´ëïÛÞÓö ÑãÔãæì ×Ðï×ÔÖÐæì, Ð ÝÕ ßÐÚÐ×ÒÐææÐ öÜÓÝÕÝÝÐ"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "¿àÐ×àëáâëï ÒÞÚÝë"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "¿ÐÚÐ×ÒÐæì ÒÞÚÝë × çÐáâÚÞÒÐ ßàÐ×àëáâëÜ äÞÝÐÜ"
+
#: engines/sky/compact.cpp:130
-msgid "Unable to find \"sky.cpt\" file!\n"
+msgid ""
+"Unable to find \"sky.cpt\" file!\n"
"Please download it from www.scummvm.org"
-msgstr "°ÔáãâÝöçÐÕ äÐÙÛ sky.cpt!\n"
+msgstr ""
+"°ÔáãâÝöçÐÕ äÐÙÛ sky.cpt!\n"
"ºÐÛö ÛÐáÚÐ, ×ÐßÐÜßãÙæÕ ïÓÞ × www.scummvm.org"
#: engines/sky/compact.cpp:141
-msgid "The \"sky.cpt\" file has an incorrect size.\n"
+msgid ""
+"The \"sky.cpt\" file has an incorrect size.\n"
"Please (re)download it from www.scummvm.org"
-msgstr "ÄÐÙÛ sky.cpt ÜÐÕ ÝïßàÐÒöÛìÝë ßÐÜÕà.\n"
+msgstr ""
+"ÄÐÙÛ sky.cpt ÜÐÕ ÝïßàÐÒöÛìÝë ßÐÜÕà.\n"
"ºÐÛö ÛÐáÚÐ, ×ÐßÐÜßãÙæÕ ïÓÞ ÝÐÝÞÒÐ × www.scummvm.org"
#: engines/sky/detection.cpp:44
@@ -3410,11 +3639,15 @@ msgstr "·ÐáâÐþÚÐ PSX '%s' ÝÕ ÜÞÖÐ Ñëæì ßàÐÙÓàÐÝÐ þ àíÖëÜÕ × ßÐÛöâàÐÙ"
#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
msgid "DXA cutscenes found but ScummVM has been built without zlib"
-msgstr "·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ DXA, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö zlib"
+msgstr ""
+"·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ DXA, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö zlib"
#: engines/sword1/animation.cpp:561 engines/sword2/animation.cpp:461
-msgid "MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"
-msgstr "·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ MPEG-2, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö MPEG-2"
+msgid ""
+"MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"
+msgstr ""
+"·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ MPEG-2, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö "
+"MPEG-2"
#: engines/sword1/animation.cpp:568 engines/sword2/animation.cpp:470
#, c-format
@@ -3422,25 +3655,30 @@ msgid "Cutscene '%s' not found"
msgstr "·ÐáâÐþÚÐ '%s' ÝÕ ×ÝÞÙÔ×ÕÝÐ"
#: engines/sword1/control.cpp:863
-msgid "ScummVM found that you have old savefiles for Broken Sword 1 that should be converted.\n"
-"The old save game format is no longer supported, so you will not be able to load your games if you don't convert them.\n"
+msgid ""
+"ScummVM found that you have old savefiles for Broken Sword 1 that should be "
+"converted.\n"
+"The old save game format is no longer supported, so you will not be able to "
+"load your games if you don't convert them.\n"
"\n"
-"Press OK to convert them now, otherwise you will be asked again the next time you start the game.\n"
-""
-msgstr "ScummVM ÒëïÒöþ ã ÒÐá ×ÐåÐÒÐÝÝö ÓãÛìÝö Broken Sword 1 ã áâÐàëÜ äÐàÜÐæÕ.\n"
-"ÁâÐàë äÐàÜÐâ ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ, ö, ÚÐÑ ×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ïÝë ßÐÒöÝÝë Ñëæì ßÕàÐÒÕÔ×ÕÝë þ ÝÞÒë äÐàÜÐâ.\n"
+"Press OK to convert them now, otherwise you will be asked again the next "
+"time you start the game.\n"
+msgstr ""
+"ScummVM ÒëïÒöþ ã ÒÐá ×ÐåÐÒÐÝÝö ÓãÛìÝö Broken Sword 1 ã áâÐàëÜ äÐàÜÐæÕ.\n"
+"ÁâÐàë äÐàÜÐâ ÑÞÛìè ÝÕ ßÐÔâàëÜÛöÒÐÕææÐ, ö, ÚÐÑ ×ÐÓàã×öæì ×ÐåÐÒÐÝÝö, ïÝë "
+"ßÐÒöÝÝë Ñëæì ßÕàÐÒÕÔ×ÕÝë þ ÝÞÒë äÐàÜÐâ.\n"
"\n"
-"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÒÕáæö öå ã ÝÞÒë äÐàÜÐâ ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã ÓíâÐ ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ×ÝÞþ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
-""
+"½ÐæöáÝöæÕ ¾º, ÚÐÑ ßÕàÐÒÕáæö öå ã ÝÞÒë äÐàÜÐâ ×ÐàÐ×, ã ÐÔÒÐàÞâÝëÜ ÒëßÐÔÚã "
+"ÓíâÐ ßÐÒÕÔÐÜÛÕÝÝÕ ×'ïÒöææÐ ×ÝÞþ ßàë ÝÐáâãßÝëÜ ×ÐßãáÚã ÓãÛìÝö.\n"
#: engines/sword1/control.cpp:1232
#, c-format
-msgid "Target new save game already exists!\n"
+msgid ""
+"Target new save game already exists!\n"
"Would you like to keep the old save game (%s) or the new one (%s)?\n"
-""
-msgstr "·ÐåÐÒÐÝÝÕ ÓãÛìÝö × âÐÚöÜ öÜÕÜ ãÖÞ öáÝãÕ!\n"
+msgstr ""
+"·ÐåÐÒÐÝÝÕ ÓãÛìÝö × âÐÚöÜ öÜÕÜ ãÖÞ öáÝãÕ!\n"
"²ë ÖÐÔÐÕæÕ ßÐÚöÝãæì áâÐàãî ÝÐ×Òã (%s) æö ×àÐÑöæì ÝÞÒãî (%s)?\n"
-""
#: engines/sword1/control.cpp:1235
msgid "Keep the old one"
@@ -3455,8 +3693,11 @@ msgid "This is the end of the Broken Sword 1 Demo"
msgstr "³íâÐ ×ÐÒïàèíÝÝÕ ÔíÜÐ Broken Sword 1"
#: engines/sword2/animation.cpp:425
-msgid "PSX cutscenes found but ScummVM has been built without RGB color support"
-msgstr "·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ PSX, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö RGB-ÚÞÛÕàÐþ"
+msgid ""
+"PSX cutscenes found but ScummVM has been built without RGB color support"
+msgstr ""
+"·ÝÞÙÔ×ÕÝë ×ÐáâÐþÚö þ äÐàÜÐæÕ PSX, ÐÛÕ ScummVM Ñëþ áÐÑàÐÝë ÑÕ× ßÐÔâàëÜÚö RGB-"
+"ÚÞÛÕàÐþ"
#: engines/sword2/sword2.cpp:79
msgid "Show object labels"
@@ -3467,12 +3708,18 @@ msgid "Show labels for objects on mouse hover"
msgstr "¿ÐÚÐ×ÒÐÕ ÝÐ×Òë ÐÑ'ÕÚâÐþ ßàë ÝÐÒïÔ×ÕÝÝö ÚãàáÞàÐ Üëèë"
#: engines/teenagent/resources.cpp:95
-msgid "You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
-msgstr "à ÒÐá ÐÔáãâÝöçÐÕ äÐÙÛ 'teenagent.dat'. ·ÐßÐÜßãÙæÕ ïÓÞ × ÒíÑ-áÐÙâÐ ScummVM"
+msgid ""
+"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
+msgstr ""
+"à ÒÐá ÐÔáãâÝöçÐÕ äÐÙÛ 'teenagent.dat'. ·ÐßÐÜßãÙæÕ ïÓÞ × ÒíÑ-áÐÙâÐ ScummVM"
#: engines/teenagent/resources.cpp:116
-msgid "The teenagent.dat file is compressed and zlib hasn't been included in this executable. Please decompress it"
-msgstr "ÄÐÙÛ teenagent.dat ×ÖÐâë, ÐÛÕ zlib ÝÕ þÚÛîçÐÝë þ Óíâã ßàÐÓàÐÜã. ºÐÛö ÛÐáÚÐ, àÐáßÐÚãÙæÕ ïÓÞ"
+msgid ""
+"The teenagent.dat file is compressed and zlib hasn't been included in this "
+"executable. Please decompress it"
+msgstr ""
+"ÄÐÙÛ teenagent.dat ×ÖÐâë, ÐÛÕ zlib ÝÕ þÚÛîçÐÝë þ Óíâã ßàÐÓàÐÜã. ºÐÛö ÛÐáÚÐ, "
+"àÐáßÐÚãÙæÕ ïÓÞ"
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
@@ -3484,7 +3731,9 @@ msgstr "¿ÐÚÐ×Ðæì ã ÒÕàåÝöÜ ÛÕÒëÜ ÚãæÕ ÑïÓãçãî ÚÞÛìÚÐáæì ÚÐÔàÐþ ã áÕÚãÝÔã"
#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã ö ×ÐåÐÒÐÝÝï ÓãÛìÝö ×ÐÜÕáâ ×àÞÑÛÕÝëå ã ScummVM"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì ÐàëÓöÝÐÛìÝëï íÚàÐÝë ×Ðßöáã ö ×ÐåÐÒÐÝÝï ÓãÛìÝö ×ÐÜÕáâ "
+"×àÞÑÛÕÝëå ã ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -3516,7 +3765,9 @@ msgstr "²ëÚÐàëáâÞþÒÐæì ÒöÔíÐ MPEG ÒëáÞÚÐÓÐ ÐÔàÞ×ÝÕÝÝï"
#: engines/zvision/detection_tables.h:92
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
-msgstr "²ëÚÐàëáâÞþÒÐæì MPEG-ÒöÔíÐ × DVD-ÒÕàáöö ×ÐÜÕáâ ÒöÔíÐ Ýö×ÚÐÓÐ ÐÔàÞ×ÝÕÝÝï þ äÐàÜÐæÕ AVI"
+msgstr ""
+"²ëÚÐàëáâÞþÒÐæì MPEG-ÒöÔíÐ × DVD-ÒÕàáöö ×ÐÜÕáâ ÒöÔíÐ Ýö×ÚÐÓÐ ÐÔàÞ×ÝÕÝÝï þ "
+"äÐàÜÐæÕ AVI"
#~ msgid "EGA undithering"
#~ msgstr "EGA ÑÕ× àÐáâàã"
@@ -3569,9 +3820,6 @@ msgstr "²ëÚÐàëáâÞþÒÐæì MPEG-ÒöÔíÐ × DVD-ÒÕàáöö ×ÐÜÕáâ ÒöÔíÐ Ýö×ÚÐÓÐ ÐÔàÞ×ÝÕÝÝï þ
#~ msgid "Enable Roland GS Mode"
#~ msgstr "ÃÚÛîçëæì àíÖëÜ Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "½Õ ãÔÐÛÞáì áÞåàÐÝØâì ØÓàã!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "´ÞÑ. ØÓàã"
diff --git a/po/ca_ES.po b/po/ca_ES.po
index 8b9d333d4f..857e7de99e 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.6.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2013-05-05 14:16+0100\n"
"Last-Translator: Jordi Vilalta Prat <jvprat@jvprat.com>\n"
"Language-Team: Catalan <scummvm-devel@lists.sf.net>\n"
@@ -593,16 +593,16 @@ msgid "Search:"
msgstr "Cerca:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Carrega partida:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Carrega"
@@ -770,7 +770,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Modes de tramat especials suportats per alguns jocs"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Mode pantalla completa"
@@ -1375,12 +1375,12 @@ msgstr ""
msgid "PC-9801 (16 Colors)"
msgstr ""
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr ""
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr ""
@@ -1432,11 +1432,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~R~etorna al Llançador"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Desa la partida:"
@@ -1445,11 +1449,15 @@ msgstr "Desa la partida:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Desa"
@@ -1776,19 +1784,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (no escalat)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "S'ha activat la correcció de la relació d'aspecte"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "S'ha desactivat la correcció de la relació d'aspecte"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Filtre de gràfics actiu:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Mode de finestra"
@@ -2354,15 +2362,23 @@ msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Recupera la partida:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Restaura"
@@ -2673,10 +2689,20 @@ msgstr ""
"No s'ha pogut desar a l'espai %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Carrega partida:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Carregant la partida..."
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Desa la partida:"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Desant la partida..."
@@ -3530,6 +3556,60 @@ msgid ""
"instruments from. Music will be disabled."
msgstr ""
+#: engines/sherlock/detection.cpp:71
+#, fuzzy
+msgid "Use original savegame dialog"
+msgstr "Utilitza les pantalles originals de desat/càrrega"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+#, fuzzy
+msgid "Show character portraits"
+msgstr "Commuta el personatge"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
index 988191d535..3a308f977c 100644
--- a/po/cs_CZ.po
+++ b/po/cs_CZ.po
@@ -1,15 +1,15 @@
# Czech translation for ScummVM.
# Copyright (C) 2001-2016 The ScummVM Team
# This file is distributed under the same license as the ScummVM package.
-# Zbyněk Schwarz <zbynek.schwarz@gmail.com>, 2011-2013.
+# Zbynìk Schwarz <zbynek.schwarz@gmail.com>, 2011-2013.
#
msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.7.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2015-12-24 13:37+0100\n"
-"Last-Translator: Zbyněk Schwarz <zbynek.schwarz@gmail.com>\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-03 22:59+0100\n"
+"Last-Translator: Zbynìk Schwarz <zbynek.schwarz@gmail.com>\n"
"Language-Team: \n"
"Language: Cesky\n"
"MIME-Version: 1.0\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Poedit-SourceCharset: iso-8859-2\n"
-"X-Generator: Poedit 1.8.6\n"
+"X-Generator: Poedit 1.8.7\n"
"X-Poedit-Basepath: ..\n"
#: gui/about.cpp:94
@@ -27,32 +27,32 @@ msgstr "(sestaveno %s)"
#: gui/about.cpp:101
msgid "Features compiled in:"
-msgstr "Zakompilované funkce:"
+msgstr "Zakompilované funkce:"
#: gui/about.cpp:110
msgid "Available engines:"
-msgstr "Dostupná jádra:"
+msgstr "Dostupná jádra:"
#: gui/browser.cpp:68 gui/browser_osx.mm:104
msgid "Show hidden files"
-msgstr "Zobrazit skryté soubory"
+msgstr "Zobrazit skryté soubory"
#: gui/browser.cpp:68
msgid "Show files marked with the hidden attribute"
-msgstr "Zobrazit soubory s vlastností skryté"
+msgstr "Zobrazit soubory s vlastností skryté"
#: gui/browser.cpp:72
msgid "Go up"
-msgstr "Jít nahoru"
+msgstr "Jít nahoru"
#: gui/browser.cpp:72 gui/browser.cpp:74
msgid "Go to previous directory level"
-msgstr "Jít na předchozí úroveň adresáře"
+msgstr "Jít na pøedchozí úroveò adresáøe"
#: gui/browser.cpp:74
msgctxt "lowres"
msgid "Go up"
-msgstr "Jít nahoru"
+msgstr "Jít nahoru"
#: gui/browser.cpp:75 gui/chooser.cpp:46 gui/editrecorddialog.cpp:67
#: gui/filebrowser-dialog.cpp:64 gui/fluidsynth-dialog.cpp:152
@@ -67,7 +67,7 @@ msgstr "Jít nahoru"
#: engines/parallaction/saveload.cpp:274 engines/scumm/dialogs.cpp:191
#: engines/sword1/control.cpp:865
msgid "Cancel"
-msgstr "Zrušit"
+msgstr "Zru¹it"
#: gui/browser.cpp:76 gui/browser_osx.mm:103 gui/chooser.cpp:47
#: gui/filebrowser-dialog.cpp:65 gui/themebrowser.cpp:56
@@ -80,11 +80,11 @@ msgstr "Autor:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
-msgstr "Jméno"
+msgstr "Jméno"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr "Poznámky:"
+msgstr "Poznámky:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
@@ -92,15 +92,15 @@ msgstr "Ok"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr "Zvolte soubor pro naÄtení"
+msgstr "Zvolte soubor pro naètení"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr "Zadejte název souboru pro uložení"
+msgstr "Zadejte název souboru pro ulo¾ení"
#: gui/filebrowser-dialog.cpp:132
msgid "Do you really want to overwrite the file?"
-msgstr "Opravdu chcete tento soubor přepsat?"
+msgstr "Opravdu chcete tento soubor pøepsat?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -128,23 +128,23 @@ msgstr "Dozvuk"
#: gui/fluidsynth-dialog.cpp:70 gui/fluidsynth-dialog.cpp:102
msgid "Active"
-msgstr "Aktivní"
+msgstr "Aktivní"
#: gui/fluidsynth-dialog.cpp:72
msgid "Room:"
-msgstr "Místnost:"
+msgstr "Místnost:"
#: gui/fluidsynth-dialog.cpp:79
msgid "Damp:"
-msgstr "Tlumení:"
+msgstr "Tlumení:"
#: gui/fluidsynth-dialog.cpp:86
msgid "Width:"
-msgstr "Šířka:"
+msgstr "©íøka:"
#: gui/fluidsynth-dialog.cpp:93 gui/fluidsynth-dialog.cpp:111
msgid "Level:"
-msgstr "Úroveň:"
+msgstr "Úroveò:"
#: gui/fluidsynth-dialog.cpp:100
msgid "Chorus"
@@ -172,11 +172,11 @@ msgstr "Sinus"
#: gui/fluidsynth-dialog.cpp:136
msgid "Triangle"
-msgstr "Trojúhrlník"
+msgstr "Trojúhrlník"
#: gui/fluidsynth-dialog.cpp:138 gui/options.cpp:1168
msgid "Misc"
-msgstr "Různé"
+msgstr "Rùzné"
#: gui/fluidsynth-dialog.cpp:140
msgid "Interpolation:"
@@ -184,19 +184,19 @@ msgstr "Interpolace:"
#: gui/fluidsynth-dialog.cpp:143
msgid "None (fastest)"
-msgstr "Žádná (Nejrychlejší)"
+msgstr "®ádná (Nejrychlej¹í)"
#: gui/fluidsynth-dialog.cpp:144
msgid "Linear"
-msgstr "Lineární"
+msgstr "Lineární"
#: gui/fluidsynth-dialog.cpp:145
msgid "Fourth-order"
-msgstr "Interpolace Ätvrtého řádu"
+msgstr "Interpolace ètvrtého øádu"
#: gui/fluidsynth-dialog.cpp:146
msgid "Seventh-order"
-msgstr "Interpolace sedmého řádu"
+msgstr "Interpolace sedmého øádu"
#: gui/fluidsynth-dialog.cpp:150
msgid "Reset"
@@ -204,7 +204,7 @@ msgstr "Resetovat"
#: gui/fluidsynth-dialog.cpp:150
msgid "Reset all FluidSynth settings to their default values."
-msgstr "Resetovat veškerá nastavení FludSynth n ajejich výchozí hodnoty."
+msgstr "Resetovat ve¹kerá nastavení FludSynth n ajejich výchozí hodnoty."
#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:42 gui/launcher.cpp:352
#: gui/launcher.cpp:1050 gui/launcher.cpp:1054 gui/massadd.cpp:92
@@ -229,7 +229,7 @@ msgstr "OK"
msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
msgstr ""
-"Opravdu chcete resetovat veškerá nastavení FluidSynth na jejich výchozí "
+"Opravdu chcete resetovat ve¹kerá nastavení FluidSynth na jejich výchozí "
"hodnoty?"
#: gui/gui-manager.cpp:119 backends/keymapper/remap-dialog.cpp:53
@@ -237,23 +237,23 @@ msgstr ""
#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:192
#: engines/scumm/help.cpp:210
msgid "Close"
-msgstr "Zavřít"
+msgstr "Zavøít"
#: gui/gui-manager.cpp:122
msgid "Mouse click"
-msgstr "Kliknutí myší"
+msgstr "Kliknutí my¹í"
#: gui/gui-manager.cpp:126 base/main.cpp:322
msgid "Display keyboard"
-msgstr "Zobrazit klávesnici"
+msgstr "Zobrazit klávesnici"
#: gui/gui-manager.cpp:130 base/main.cpp:326
msgid "Remap keys"
-msgstr "Přemapovat klávesy"
+msgstr "Pøemapovat klávesy"
#: gui/gui-manager.cpp:133 base/main.cpp:329 engines/scumm/help.cpp:87
msgid "Toggle fullscreen"
-msgstr "Přepnout celou obrazovku"
+msgstr "Pøepnout celou obrazovku"
#: gui/KeysDialog.cpp:41
msgid "Map"
@@ -261,29 +261,29 @@ msgstr "Mapovat"
#: gui/KeysDialog.cpp:49
msgid "Select an action and click 'Map'"
-msgstr "Zvolte Äinnost a kliknÄ›te 'Mapovat'"
+msgstr "Zvolte èinnost a kliknìte 'Mapovat'"
#: gui/KeysDialog.cpp:80 gui/KeysDialog.cpp:102 gui/KeysDialog.cpp:141
#, c-format
msgid "Associated key : %s"
-msgstr "Přiřazená klávesa: %s"
+msgstr "Pøiøazená klávesa: %s"
#: gui/KeysDialog.cpp:82 gui/KeysDialog.cpp:104 gui/KeysDialog.cpp:143
#, c-format
msgid "Associated key : none"
-msgstr "Přiřazená klávesa: žádná"
+msgstr "Pøiøazená klávesa: ¾ádná"
#: gui/KeysDialog.cpp:90
msgid "Please select an action"
-msgstr "Prosím vyberte Äinnost"
+msgstr "Prosím vyberte èinnost"
#: gui/KeysDialog.cpp:106
msgid "Press the key to associate"
-msgstr "ZmáÄknÄ›te klávesu pro pÅ™iÅ™azení"
+msgstr "Zmáèknìte klávesu pro pøiøazení"
#: gui/KeysDialog.cpp:145 gui/KeysDialog.h:36
msgid "Choose an action to map"
-msgstr "Zvolte Äinnost k mapování"
+msgstr "Zvolte èinnost k mapování"
#: gui/launcher.cpp:193
msgid "Game"
@@ -298,8 +298,8 @@ msgid ""
"Short game identifier used for referring to saved games and running the game "
"from the command line"
msgstr ""
-"Krátký identifikátor her, používaný jako odkaz k uloženým hrám a "
-"spuštění hry z příkazového řádku"
+"Krátký identifikátor her, pou¾ívaný jako odkaz k ulo¾eným hrám a spu¹tìní "
+"hry z pøíkazového øádku"
#: gui/launcher.cpp:199
msgctxt "lowres"
@@ -308,12 +308,12 @@ msgstr "ID:"
#: gui/launcher.cpp:204 gui/launcher.cpp:206 gui/launcher.cpp:207
msgid "Full title of the game"
-msgstr "Úplný název hry"
+msgstr "Úplný název hry"
#: gui/launcher.cpp:206
msgctxt "lowres"
msgid "Name:"
-msgstr "Jméno:"
+msgstr "Jméno:"
#: gui/launcher.cpp:210
msgid "Language:"
@@ -323,13 +323,13 @@ msgstr "Jazyk:"
msgid ""
"Language of the game. This will not turn your Spanish game version into "
"English"
-msgstr "Jazyk hry. Toto z vaší Španělské verze neudělá Anglickou"
+msgstr "Jazyk hry. Toto z va¹í ©panìlské verze neudìlá Anglickou"
#: gui/launcher.cpp:212 gui/launcher.cpp:226 gui/options.cpp:87
#: gui/options.cpp:735 gui/options.cpp:748 gui/options.cpp:1208
#: audio/null.cpp:41
msgid "<default>"
-msgstr "<výchozí>"
+msgstr "<výchozí>"
#: gui/launcher.cpp:222
msgid "Platform:"
@@ -337,7 +337,7 @@ msgstr "Platforma:"
#: gui/launcher.cpp:222 gui/launcher.cpp:224 gui/launcher.cpp:225
msgid "Platform the game was originally designed for"
-msgstr "Platforma, pro kterou byla hra původně vytvořena"
+msgstr "Platforma, pro kterou byla hra pùvodnì vytvoøena"
#: gui/launcher.cpp:224
msgctxt "lowres"
@@ -346,7 +346,7 @@ msgstr "Platforma:"
#: gui/launcher.cpp:237
msgid "Engine"
-msgstr "Jádro"
+msgstr "Jádro"
#: gui/launcher.cpp:245 gui/options.cpp:1071 gui/options.cpp:1088
msgid "Graphics"
@@ -358,12 +358,12 @@ msgstr "GFX"
#: gui/launcher.cpp:248
msgid "Override global graphic settings"
-msgstr "PotlaÄit globální nastavení obrazu"
+msgstr "Potlaèit globální nastavení obrazu"
#: gui/launcher.cpp:250
msgctxt "lowres"
msgid "Override global graphic settings"
-msgstr "PotlaÄit globální nastavení obrazu"
+msgstr "Potlaèit globální nastavení obrazu"
#: gui/launcher.cpp:257 gui/options.cpp:1094
msgid "Audio"
@@ -371,12 +371,12 @@ msgstr "Zvuk"
#: gui/launcher.cpp:260
msgid "Override global audio settings"
-msgstr "PotlaÄit globální nastavení zvuku"
+msgstr "Potlaèit globální nastavení zvuku"
#: gui/launcher.cpp:262
msgctxt "lowres"
msgid "Override global audio settings"
-msgstr "PotlaÄit globální nastavení zvuku"
+msgstr "Potlaèit globální nastavení zvuku"
#: gui/launcher.cpp:271 gui/options.cpp:1099
msgid "Volume"
@@ -389,12 +389,12 @@ msgstr "Hlasitost"
#: gui/launcher.cpp:276
msgid "Override global volume settings"
-msgstr "PotlaÄit globální nastavení hlasitosti"
+msgstr "Potlaèit globální nastavení hlasitosti"
#: gui/launcher.cpp:278
msgctxt "lowres"
msgid "Override global volume settings"
-msgstr "PotlaÄit globální nastavení hlasitosti"
+msgstr "Potlaèit globální nastavení hlasitosti"
#: gui/launcher.cpp:286 gui/options.cpp:1109
msgid "MIDI"
@@ -402,12 +402,12 @@ msgstr "MIDI"
#: gui/launcher.cpp:289
msgid "Override global MIDI settings"
-msgstr "PotlaÄit globální nastavení MIDI"
+msgstr "Potlaèit globální nastavení MIDI"
#: gui/launcher.cpp:291
msgctxt "lowres"
msgid "Override global MIDI settings"
-msgstr "PotlaÄit globální nastavení MIDI"
+msgstr "Potlaèit globální nastavení MIDI"
#: gui/launcher.cpp:300 gui/options.cpp:1115
msgid "MT-32"
@@ -415,12 +415,12 @@ msgstr "MT-32"
#: gui/launcher.cpp:303
msgid "Override global MT-32 settings"
-msgstr "PotlaÄit globální nastavení MT-32"
+msgstr "Potlaèit globální nastavení MT-32"
#: gui/launcher.cpp:305
msgctxt "lowres"
msgid "Override global MT-32 settings"
-msgstr "PotlaÄit globální nastavení MT-32"
+msgstr "Potlaèit globální nastavení MT-32"
#: gui/launcher.cpp:314 gui/options.cpp:1122
msgid "Paths"
@@ -442,30 +442,30 @@ msgstr "Cesta Hry:"
#: gui/launcher.cpp:330 gui/options.cpp:1148
msgid "Extra Path:"
-msgstr "DodateÄná Cesta:"
+msgstr "Dodateèná Cesta:"
#: gui/launcher.cpp:330 gui/launcher.cpp:332 gui/launcher.cpp:333
msgid "Specifies path to additional data used by the game"
-msgstr "Stanoví cestu pro dodateÄná data použitá ve hÅ™e"
+msgstr "Stanoví cestu pro dodateèná data pou¾itá ve høe"
#: gui/launcher.cpp:332 gui/options.cpp:1150
msgctxt "lowres"
msgid "Extra Path:"
-msgstr "DodateÄná Cesta:"
+msgstr "Dodateèná Cesta:"
#: gui/launcher.cpp:339 gui/options.cpp:1132
msgid "Save Path:"
-msgstr "Cesta pro uložení:"
+msgstr "Cesta pro ulo¾ení:"
#: gui/launcher.cpp:339 gui/launcher.cpp:341 gui/launcher.cpp:342
#: gui/options.cpp:1132 gui/options.cpp:1134 gui/options.cpp:1135
msgid "Specifies where your saved games are put"
-msgstr "Stanovuje, kam jsou umístěny vaše uložené hry"
+msgstr "Stanovuje, kam jsou umístìny va¹e ulo¾ené hry"
#: gui/launcher.cpp:341 gui/options.cpp:1134
msgctxt "lowres"
msgid "Save Path:"
-msgstr "Cesta pro uložení:"
+msgstr "Cesta pro ulo¾ení:"
#: gui/launcher.cpp:360 gui/launcher.cpp:459 gui/launcher.cpp:517
#: gui/launcher.cpp:571 gui/options.cpp:1143 gui/options.cpp:1151
@@ -475,13 +475,13 @@ msgstr "Cesta pro uložení:"
#: gui/options.cpp:1440
msgctxt "path"
msgid "None"
-msgstr "Žádné"
+msgstr "®ádné"
#: gui/launcher.cpp:365 gui/launcher.cpp:465 gui/launcher.cpp:575
#: gui/options.cpp:1269 gui/options.cpp:1313 gui/options.cpp:1431
#: backends/platform/wii/options.cpp:56
msgid "Default"
-msgstr "Výchozí"
+msgstr "Výchozí"
#: gui/launcher.cpp:510 gui/options.cpp:1434
msgid "Select SoundFont"
@@ -489,27 +489,27 @@ msgstr "Vybrat SoundFont"
#: gui/launcher.cpp:529 gui/launcher.cpp:682
msgid "Select directory with game data"
-msgstr "Vyberte adresář s daty hry"
+msgstr "Vyberte adresáø s daty hry"
#: gui/launcher.cpp:547
msgid "Select additional game directory"
-msgstr "Vyberte dodateÄný adresář hry"
+msgstr "Vyberte dodateèný adresáø hry"
#: gui/launcher.cpp:559 gui/options.cpp:1377
msgid "Select directory for saved games"
-msgstr "Vyberte adresář pro uložené hry"
+msgstr "Vyberte adresáø pro ulo¾ené hry"
#: gui/launcher.cpp:586
msgid "This game ID is already taken. Please choose another one."
-msgstr "Toto ID hry je už zabrané. Vyberte si, prosím, jiné."
+msgstr "Toto ID hry je u¾ zabrané. Vyberte si, prosím, jiné."
#: gui/launcher.cpp:626 engines/dialogs.cpp:111
msgid "~Q~uit"
-msgstr "~U~konÄit"
+msgstr "~U~konèit"
#: gui/launcher.cpp:626 backends/platform/sdl/macosx/appmenu_osx.mm:106
msgid "Quit ScummVM"
-msgstr "UkonÄit ScummVM"
+msgstr "Ukonèit ScummVM"
#: gui/launcher.cpp:627
msgid "A~b~out..."
@@ -525,7 +525,7 @@ msgstr "~V~olby..."
#: gui/launcher.cpp:628
msgid "Change global ScummVM options"
-msgstr "Změnit globální volby ScummVM"
+msgstr "Zmìnit globální volby ScummVM"
#: gui/launcher.cpp:630
msgid "~S~tart"
@@ -537,19 +537,19 @@ msgstr "Spustit zvolenou hru"
#: gui/launcher.cpp:633
msgid "~L~oad..."
-msgstr "~N~ahrát..."
+msgstr "~N~ahrát..."
#: gui/launcher.cpp:633
msgid "Load saved game for selected game"
-msgstr "Nahrát uloženou pozici pro zvolenou hru"
+msgstr "Nahrát ulo¾enou pozici pro zvolenou hru"
#: gui/launcher.cpp:638
msgid "~A~dd Game..."
-msgstr "~P~řidat hru..."
+msgstr "~P~øidat hru..."
#: gui/launcher.cpp:638 gui/launcher.cpp:645
msgid "Hold Shift for Mass Add"
-msgstr "Podržte Shift pro Hromadné Přidání"
+msgstr "Podr¾te Shift pro Hromadné Pøidání"
#: gui/launcher.cpp:640
msgid "~E~dit Game..."
@@ -557,7 +557,7 @@ msgstr "~U~pravit Hru..."
#: gui/launcher.cpp:640 gui/launcher.cpp:647
msgid "Change game options"
-msgstr "Změnit volby hry"
+msgstr "Zmìnit volby hry"
#: gui/launcher.cpp:642
msgid "~R~emove Game"
@@ -565,12 +565,12 @@ msgstr "~O~dstranit Hru"
#: gui/launcher.cpp:642 gui/launcher.cpp:649
msgid "Remove game from the list. The game data files stay intact"
-msgstr "Odstranit hru ze seznamu. Herní data zůstanou zachována"
+msgstr "Odstranit hru ze seznamu. Herní data zùstanou zachována"
#: gui/launcher.cpp:645
msgctxt "lowres"
msgid "~A~dd Game..."
-msgstr "~P~řidat hru..."
+msgstr "~P~øidat hru..."
#: gui/launcher.cpp:647
msgctxt "lowres"
@@ -591,35 +591,35 @@ msgid "Search:"
msgstr "Hledat:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
-msgstr "Nahrát hru:"
+msgstr "Nahrát hru:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
-msgstr "Nahrát"
+msgstr "Nahrát"
#: gui/launcher.cpp:794
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
msgstr ""
-"Opravdu chcete spustit hromadnou detekci her? Toto by mohlo potenciálně "
-"přidat velkou spoustu her. "
+"Opravdu chcete spustit hromadnou detekci her? Toto by mohlo potenciálnì "
+"pøidat velkou spoustu her. "
#: gui/launcher.cpp:843
msgid "ScummVM couldn't open the specified directory!"
-msgstr "ScummVM nemohl tento adresář otevřít!"
+msgstr "ScummVM nemohl tento adresáø otevøít!"
#: gui/launcher.cpp:855
msgid "ScummVM could not find any game in the specified directory!"
-msgstr "ScummVM nemohl v zadaném adresáři najít žádnou hru!"
+msgstr "ScummVM nemohl v zadaném adresáøi najít ¾ádnou hru!"
#: gui/launcher.cpp:869
msgid "Pick the game:"
@@ -627,50 +627,50 @@ msgstr "Vybrat hru:"
#: gui/launcher.cpp:943
msgid "Do you really want to remove this game configuration?"
-msgstr "Opravdu chcete odstranit nastavení této hry?"
+msgstr "Opravdu chcete odstranit nastavení této hry?"
#: gui/launcher.cpp:1001
msgid "Do you want to load saved game?"
-msgstr "Chcete naÄíst uloženou pozici?"
+msgstr "Chcete naèíst ulo¾enou pozici?"
#: gui/launcher.cpp:1050
msgid "This game does not support loading games from the launcher."
-msgstr "Tato hra nepodporuje spouÅ¡tÄ›ní her ze spouÅ¡tÄ›Äe"
+msgstr "Tato hra nepodporuje spou¹tìní her ze spou¹tìèe"
#: gui/launcher.cpp:1054
msgid "ScummVM could not find any engine capable of running the selected game!"
-msgstr "ScummVM nemohl najít žádné jádro schopné vybranou hru spustit!"
+msgstr "ScummVM nemohl najít ¾ádné jádro schopné vybranou hru spustit!"
#: gui/launcher.cpp:1161
msgid "Mass Add..."
-msgstr "Hromadné Přidání..."
+msgstr "Hromadné Pøidání..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr "Nahrát..."
+msgstr "Nahrát..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
-msgstr "... průběh ..."
+msgstr "... prùbìh ..."
#: gui/massadd.cpp:259
msgid "Scan complete!"
-msgstr "Hledání dokonÄeno!"
+msgstr "Hledání dokonèeno!"
#: gui/massadd.cpp:262
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
-msgstr "Objeveno %d nových her, ignorováno %d dříve přidaných her."
+msgstr "Objeveno %d nových her, ignorováno %d døíve pøidaných her."
#: gui/massadd.cpp:266
#, c-format
msgid "Scanned %d directories ..."
-msgstr "Prohledáno %d adresářů..."
+msgstr "Prohledáno %d adresáøù..."
#: gui/massadd.cpp:269
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
-msgstr "Objeveno %d nových her, ignorováno %d dříve přidaných her ..."
+msgstr "Objeveno %d nových her, ignorováno %d døíve pøidaných her ..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
@@ -678,15 +678,15 @@ msgstr "Zastavit"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr "Upravit popis záznamu"
+msgstr "Upravit popis záznamu"
#: gui/onscreendialog.cpp:108
msgid "Switch to Game"
-msgstr "Přepnout do hry"
+msgstr "Pøepnout do hry"
#: gui/onscreendialog.cpp:110
msgid "Fast replay"
-msgstr "Rychlé přehrávání"
+msgstr "Rychlé pøehrávání"
#: gui/options.cpp:85
msgid "Never"
@@ -694,19 +694,19 @@ msgstr "Nikdy"
#: gui/options.cpp:85
msgid "every 5 mins"
-msgstr "Každých 5 min"
+msgstr "Ka¾dých 5 min"
#: gui/options.cpp:85
msgid "every 10 mins"
-msgstr "Každých 10 min"
+msgstr "Ka¾dých 10 min"
#: gui/options.cpp:85
msgid "every 15 mins"
-msgstr "Každých 15 min"
+msgstr "Ka¾dých 15 min"
#: gui/options.cpp:85
msgid "every 30 mins"
-msgstr "Každých 30 min"
+msgstr "Ka¾dých 30 min"
#: gui/options.cpp:87
msgid "8 kHz"
@@ -732,110 +732,110 @@ msgstr "48 kHz"
#: gui/options.cpp:649 gui/options.cpp:857
msgctxt "soundfont"
msgid "None"
-msgstr "Žádné"
+msgstr "®ádné"
#: gui/options.cpp:389
msgid "Failed to apply some of the graphic options changes:"
-msgstr "Nelze použít některé změny možností grafiky:"
+msgstr "Nelze pou¾ít nìkteré zmìny mo¾ností grafiky:"
#: gui/options.cpp:401
msgid "the video mode could not be changed."
-msgstr "režim obrazu nemohl být změněn."
+msgstr "re¾im obrazu nemohl být zmìnìn."
#: gui/options.cpp:407
msgid "the fullscreen setting could not be changed"
-msgstr "nastavení celé obrazovky nemohlo být změněno"
+msgstr "nastavení celé obrazovky nemohlo být zmìnìno"
#: gui/options.cpp:413
msgid "the aspect ratio setting could not be changed"
-msgstr "nastavení poměru stran nemohlo být změněno"
+msgstr "nastavení pomìru stran nemohlo být zmìnìno"
#: gui/options.cpp:732
msgid "Graphics mode:"
-msgstr "Režim obrazu:"
+msgstr "Re¾im obrazu:"
#: gui/options.cpp:746
msgid "Render mode:"
-msgstr "Režim vykreslení:"
+msgstr "Re¾im vykreslení:"
#: gui/options.cpp:746 gui/options.cpp:747
msgid "Special dithering modes supported by some games"
-msgstr "Speciální režimy chvění podporované některými hrami"
+msgstr "Speciální re¾imy chvìní podporované nìkterými hrami"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
-msgstr "Režim celé obrazovky"
+msgstr "Re¾im celé obrazovky"
#: gui/options.cpp:761
msgid "Aspect ratio correction"
-msgstr "Korekce poměru stran"
+msgstr "Korekce pomìru stran"
#: gui/options.cpp:761
msgid "Correct aspect ratio for 320x200 games"
-msgstr "Korigovat poměr stran pro hry 320x200"
+msgstr "Korigovat pomìr stran pro hry 320x200"
#: gui/options.cpp:769
msgid "Preferred Device:"
-msgstr "Prioritní Zařízení:"
+msgstr "Prioritní Zaøízení:"
#: gui/options.cpp:769
msgid "Music Device:"
-msgstr "Hudební zařízení"
+msgstr "Hudební zaøízení"
#: gui/options.cpp:769 gui/options.cpp:771
msgid "Specifies preferred sound device or sound card emulator"
-msgstr "Stanoví prioritní zvukové zařízení nebo emulátor zvukové karty"
+msgstr "Stanoví prioritní zvukové zaøízení nebo emulátor zvukové karty"
#: gui/options.cpp:769 gui/options.cpp:771 gui/options.cpp:772
msgid "Specifies output sound device or sound card emulator"
-msgstr "Stanoví výstupní zvukové zařízení nebo emulátor zvukové karty"
+msgstr "Stanoví výstupní zvukové zaøízení nebo emulátor zvukové karty"
#: gui/options.cpp:771
msgctxt "lowres"
msgid "Preferred Dev.:"
-msgstr "Prioritní Zař.:"
+msgstr "Prioritní Zaø.:"
#: gui/options.cpp:771
msgctxt "lowres"
msgid "Music Device:"
-msgstr "Hudební zařízení"
+msgstr "Hudební zaøízení"
#: gui/options.cpp:798
msgid "AdLib emulator:"
-msgstr "AdLib emulátor"
+msgstr "AdLib emulátor"
#: gui/options.cpp:798 gui/options.cpp:799
msgid "AdLib is used for music in many games"
-msgstr "AdLib se používá pro hudbu v mnoha hrách"
+msgstr "AdLib se pou¾ívá pro hudbu v mnoha hrách"
#: gui/options.cpp:809
msgid "Output rate:"
-msgstr "Výstup. frekvence:"
+msgstr "Výstup. frekvence:"
#: gui/options.cpp:809 gui/options.cpp:810
msgid ""
"Higher value specifies better sound quality but may be not supported by your "
"soundcard"
msgstr ""
-"Vyšší hodnota způsobí lepší kvalitu zvuku, ale nemusí být podporována "
-"Vaši zvukovou kartou"
+"Vy¹¹í hodnota zpùsobí lep¹í kvalitu zvuku, ale nemusí být podporována Va¹i "
+"zvukovou kartou"
#: gui/options.cpp:820
msgid "GM Device:"
-msgstr "GM Zařízení:"
+msgstr "GM Zaøízení:"
#: gui/options.cpp:820
msgid "Specifies default sound device for General MIDI output"
-msgstr "Stanoví výchozí zvukové zařízení pro výstup General MIDI"
+msgstr "Stanoví výchozí zvukové zaøízení pro výstup General MIDI"
#: gui/options.cpp:831
msgid "Don't use General MIDI music"
-msgstr "Nepoužívat hudbu General MIDI"
+msgstr "Nepou¾ívat hudbu General MIDI"
#: gui/options.cpp:842 gui/options.cpp:908
msgid "Use first available device"
-msgstr "Použít první dostupné zařízení"
+msgstr "Pou¾ít první dostupné zaøízení"
#: gui/options.cpp:854
msgid "SoundFont:"
@@ -844,7 +844,7 @@ msgstr "SoundFont:"
#: gui/options.cpp:854 gui/options.cpp:856 gui/options.cpp:857
msgid "SoundFont is supported by some audio cards, FluidSynth and Timidity"
msgstr ""
-"SoundFont je podporován některými zvukovými kartami, FluidSynth a Timidity"
+"SoundFont je podporován nìkterými zvukovými kartami, FluidSynth a Timidity"
#: gui/options.cpp:856
msgctxt "lowres"
@@ -853,70 +853,69 @@ msgstr "SoundFont:"
#: gui/options.cpp:862
msgid "Mixed AdLib/MIDI mode"
-msgstr "Smíšený režim AdLib/MIDI"
+msgstr "Smí¹ený re¾im AdLib/MIDI"
#: gui/options.cpp:862
msgid "Use both MIDI and AdLib sound generation"
-msgstr "Použít obě zvukové generace MIDI a AdLib"
+msgstr "Pou¾ít obì zvukové generace MIDI a AdLib"
#: gui/options.cpp:865
msgid "MIDI gain:"
-msgstr "Zesílení MIDI:"
+msgstr "Zesílení MIDI:"
#: gui/options.cpp:872
msgid "FluidSynth Settings"
-msgstr "Nastavení FluidSynth"
+msgstr "Nastavení FluidSynth"
#: gui/options.cpp:879
msgid "MT-32 Device:"
-msgstr "Zařízení MT-32:"
+msgstr "Zaøízení MT-32:"
#: gui/options.cpp:879
msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
msgstr ""
-"Stanoví výchozí zvukové výstupní zařízení pro Roland MT-32/LAPC1/CM32l/"
-"CM64"
+"Stanoví výchozí zvukové výstupní zaøízení pro Roland MT-32/LAPC1/CM32l/CM64"
#: gui/options.cpp:884
msgid "True Roland MT-32 (disable GM emulation)"
-msgstr "Opravdový Roland MT-32 (vypne GM emulaci)"
+msgstr "Opravdový Roland MT-32 (vypne GM emulaci)"
#: gui/options.cpp:884 gui/options.cpp:886
msgid ""
"Check if you want to use your real hardware Roland-compatible sound device "
"connected to your computer"
msgstr ""
-"Zaškrtněte, pokud chcete použít pravé hardwarové zařízení kompatibilní s "
-"Roland, pÅ™ipojené k vaÅ¡emu poÄítaÄi"
+"Za¹krtnìte, pokud chcete pou¾ít pravé hardwarové zaøízení kompatibilní s "
+"Roland, pøipojené k va¹emu poèítaèi"
#: gui/options.cpp:886
msgctxt "lowres"
msgid "True Roland MT-32 (no GM emulation)"
-msgstr "Opravdový Roland MT-32 (žádná GM emulace)"
+msgstr "Opravdový Roland MT-32 (¾ádná GM emulace)"
#: gui/options.cpp:889
msgid "Roland GS Device (enable MT-32 mappings)"
-msgstr "Zařízení Roland GS (zapne mapování MT-32)"
+msgstr "Zaøízení Roland GS (zapne mapování MT-32)"
#: gui/options.cpp:889
msgid ""
"Check if you want to enable patch mappings to emulate an MT-32 on a Roland "
"GS device"
msgstr ""
-"Zaškrtněte, pokud chcete povolit záplaty mapování umožňující emulovat "
-"MT-32 na zařízení Roland GS"
+"Za¹krtnìte, pokud chcete povolit záplaty mapování umo¾òující emulovat MT-32 "
+"na zaøízení Roland GS"
#: gui/options.cpp:898
msgid "Don't use Roland MT-32 music"
-msgstr "Nepoužívat hudbu Roland MT-32"
+msgstr "Nepou¾ívat hudbu Roland MT-32"
#: gui/options.cpp:925
msgid "Text and Speech:"
-msgstr "Text a ŘeÄ"
+msgstr "Text a Øeè"
#: gui/options.cpp:929 gui/options.cpp:939
msgid "Speech"
-msgstr "ŘeÄ"
+msgstr "Øeè"
#: gui/options.cpp:930 gui/options.cpp:940
msgid "Subtitles"
@@ -928,16 +927,16 @@ msgstr "Oba"
#: gui/options.cpp:933
msgid "Subtitle speed:"
-msgstr "Rychlost titulků:"
+msgstr "Rychlost titulkù:"
#: gui/options.cpp:935
msgctxt "lowres"
msgid "Text and Speech:"
-msgstr "Text a ŘeÄ:"
+msgstr "Text a Øeè:"
#: gui/options.cpp:939
msgid "Spch"
-msgstr "ŘeÄ"
+msgstr "Øeè"
#: gui/options.cpp:940
msgid "Subs"
@@ -950,12 +949,12 @@ msgstr "Oba"
#: gui/options.cpp:941
msgid "Show subtitles and play speech"
-msgstr "Zobrazit titulky a pÅ™ehrávat Å™eÄ"
+msgstr "Zobrazit titulky a pøehrávat øeè"
#: gui/options.cpp:943
msgctxt "lowres"
msgid "Subtitle speed:"
-msgstr "Rychlost titulků"
+msgstr "Rychlost titulkù"
#: gui/options.cpp:959
msgid "Music volume:"
@@ -968,29 +967,29 @@ msgstr "Hlasitost hudby"
#: gui/options.cpp:968
msgid "Mute All"
-msgstr "Ztlumit VÅ¡e"
+msgstr "Ztlumit V¹e"
#: gui/options.cpp:971
msgid "SFX volume:"
-msgstr "Hlasitost zvuků"
+msgstr "Hlasitost zvukù"
#: gui/options.cpp:971 gui/options.cpp:973 gui/options.cpp:974
msgid "Special sound effects volume"
-msgstr "Hlasitost speciálních zvukových efektů"
+msgstr "Hlasitost speciálních zvukových efektù"
#: gui/options.cpp:973
msgctxt "lowres"
msgid "SFX volume:"
-msgstr "Hlasitost zvuků"
+msgstr "Hlasitost zvukù"
#: gui/options.cpp:981
msgid "Speech volume:"
-msgstr "Hlasitost Å™eÄi"
+msgstr "Hlasitost øeèi"
#: gui/options.cpp:983
msgctxt "lowres"
msgid "Speech volume:"
-msgstr "Hlasitost Å™eÄi"
+msgstr "Hlasitost øeèi"
#: gui/options.cpp:1140
msgid "Theme Path:"
@@ -1003,22 +1002,21 @@ msgstr "Cesta ke Vzhledu:"
#: gui/options.cpp:1148 gui/options.cpp:1150 gui/options.cpp:1151
msgid "Specifies path to additional data used by all games or ScummVM"
-msgstr ""
-"Stanoví cestu k dodateÄným datům používaná vÅ¡emi hrami nebo ScummVM"
+msgstr "Stanoví cestu k dodateèným datùm pou¾ívaná v¹emi hrami nebo ScummVM"
#: gui/options.cpp:1157
msgid "Plugins Path:"
-msgstr "Cesta k Pluginům:"
+msgstr "Cesta k Pluginùm:"
#: gui/options.cpp:1159
msgctxt "lowres"
msgid "Plugins Path:"
-msgstr "Cesta k Pluginům:"
+msgstr "Cesta k Pluginùm:"
#: gui/options.cpp:1170
msgctxt "lowres"
msgid "Misc"
-msgstr "Různé"
+msgstr "Rùzné"
#: gui/options.cpp:1172
msgid "Theme:"
@@ -1026,20 +1024,20 @@ msgstr "Vzhled:"
#: gui/options.cpp:1176
msgid "GUI Renderer:"
-msgstr "GUI VykreslovaÄ:"
+msgstr "GUI Vykreslovaè:"
#: gui/options.cpp:1188
msgid "Autosave:"
-msgstr "Autoukládání:"
+msgstr "Autoukládání:"
#: gui/options.cpp:1190
msgctxt "lowres"
msgid "Autosave:"
-msgstr "Autoukládání:"
+msgstr "Autoukládání:"
#: gui/options.cpp:1198
msgid "Keys"
-msgstr "Klávesy"
+msgstr "Klávesy"
#: gui/options.cpp:1205
msgid "GUI Language:"
@@ -1051,40 +1049,40 @@ msgstr "Jazyk GUI ScummVM"
#: gui/options.cpp:1364
msgid "You have to restart ScummVM before your changes will take effect."
-msgstr "Pro použití těchto nastavení musíte restartovat ScummVM."
+msgstr "Pro pou¾ití tìchto nastavení musíte restartovat ScummVM."
#: gui/options.cpp:1384
msgid "The chosen directory cannot be written to. Please select another one."
-msgstr "Do zvoleného adresáře nelze zapisovat. Vyberte, prosím, jiný."
+msgstr "Do zvoleného adresáøe nelze zapisovat. Vyberte, prosím, jiný."
#: gui/options.cpp:1393
msgid "Select directory for GUI themes"
-msgstr "Vyberte adresář pro vhledy GUI"
+msgstr "Vyberte adresáø pro vhledy GUI"
#: gui/options.cpp:1403
msgid "Select directory for extra files"
-msgstr "Vyberte adresář pro dodateÄné soubory"
+msgstr "Vyberte adresáø pro dodateèné soubory"
#: gui/options.cpp:1414
msgid "Select directory for plugins"
-msgstr "Vyberte adresář pro zásuvné moduly"
+msgstr "Vyberte adresáø pro zásuvné moduly"
#: gui/options.cpp:1467
msgid ""
"The theme you selected does not support your current language. If you want "
"to use this theme you need to switch to another language first."
msgstr ""
-"Vzhled, který jste zvolili, nepodporuje Váš souÄasný jazyk. Pokud chcete "
-"tento vzhled použít, musíte nejdříve přepnout na jiný jazyk."
+"Vzhled, který jste zvolili, nepodporuje Vá¹ souèasný jazyk. Pokud chcete "
+"tento vzhled pou¾ít, musíte nejdøíve pøepnout na jiný jazyk."
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr "# další"
+msgstr "# dal¹í"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr "přidat"
+msgstr "pøidat"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
msgid "Delete char"
@@ -1097,21 +1095,21 @@ msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr "* Prediktivní"
+msgstr "* Prediktivní"
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Èísla"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr "Nahrávat nebo přehrát hru"
+msgstr "Nahrávat nebo pøehrát hru"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1120,11 +1118,11 @@ msgstr "Smazat"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr "Nahrát"
+msgstr "Nahrát"
#: gui/recorderdialog.cpp:72
msgid "Playback"
-msgstr "Přehrát"
+msgstr "Pøehrát"
#: gui/recorderdialog.cpp:74
msgid "Edit"
@@ -1138,15 +1136,15 @@ msgstr "Autor:"
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr "Poznámky:"
+msgstr "Poznámky:"
#: gui/recorderdialog.cpp:155
msgid "Do you really want to delete this record?"
-msgstr "Opravdu chcete tento záznam smazat?"
+msgstr "Opravdu chcete tento záznam smazat?"
#: gui/recorderdialog.cpp:174
msgid "Unknown Author"
-msgstr "Neznámý autor"
+msgstr "Neznámý autor"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1154,23 +1152,23 @@ msgstr "Seznam"
#: gui/saveload-dialog.cpp:168
msgid "Grid view"
-msgstr "Mřížka"
+msgstr "Møí¾ka"
#: gui/saveload-dialog.cpp:211 gui/saveload-dialog.cpp:360
msgid "No date saved"
-msgstr "Neuložena žádná data"
+msgstr "Neulo¾ena ¾ádná data"
#: gui/saveload-dialog.cpp:212 gui/saveload-dialog.cpp:361
msgid "No time saved"
-msgstr "Žádný uložený Äas"
+msgstr "®ádný ulo¾ený èas"
#: gui/saveload-dialog.cpp:213 gui/saveload-dialog.cpp:362
msgid "No playtime saved"
-msgstr "Žádná uložená doba hraní"
+msgstr "®ádná ulo¾ená doba hraní"
#: gui/saveload-dialog.cpp:275
msgid "Do you really want to delete this saved game?"
-msgstr "Opravdu chcete tuto uloženou hru vymazat"
+msgstr "Opravdu chcete tuto ulo¾enou hru vymazat"
#: gui/saveload-dialog.cpp:385 gui/saveload-dialog.cpp:884
msgid "Date: "
@@ -1178,35 +1176,35 @@ msgstr "Datum:"
#: gui/saveload-dialog.cpp:389 gui/saveload-dialog.cpp:890
msgid "Time: "
-msgstr "ÄŒas:"
+msgstr "Èas:"
#: gui/saveload-dialog.cpp:395 gui/saveload-dialog.cpp:898
msgid "Playtime: "
-msgstr "Doba hraní:"
+msgstr "Doba hraní:"
#: gui/saveload-dialog.cpp:408 gui/saveload-dialog.cpp:496
msgid "Untitled savestate"
-msgstr "Bezejmenný uložený stav"
+msgstr "Bezejmenný ulo¾ený stav"
#: gui/saveload-dialog.cpp:548
msgid "Next"
-msgstr "Další"
+msgstr "Dal¹í"
#: gui/saveload-dialog.cpp:551
msgid "Prev"
-msgstr "Předchozí"
+msgstr "Pøedchozí"
#: gui/saveload-dialog.cpp:748
msgid "New Save"
-msgstr "Nová uložená pozice"
+msgstr "Nová ulo¾ená pozice"
#: gui/saveload-dialog.cpp:748
msgid "Create a new save game"
-msgstr "Vytvořit novou uloženou hru."
+msgstr "Vytvoøit novou ulo¾enou hru."
#: gui/saveload-dialog.cpp:877
msgid "Name: "
-msgstr "Název:"
+msgstr "Název:"
#: gui/saveload-dialog.cpp:949
#, c-format
@@ -1219,37 +1217,37 @@ msgstr "Vyberte Vzhled"
#: gui/ThemeEngine.cpp:347
msgid "Disabled GFX"
-msgstr "GFX zakázáno"
+msgstr "GFX zakázáno"
#: gui/ThemeEngine.cpp:347
msgctxt "lowres"
msgid "Disabled GFX"
-msgstr "GFX zakázáno"
+msgstr "GFX zakázáno"
#: gui/ThemeEngine.cpp:348
msgid "Standard Renderer"
-msgstr "Standardní VykreslovaÄ"
+msgstr "Standardní Vykreslovaè"
#: gui/ThemeEngine.cpp:348 engines/scumm/dialogs.cpp:663
msgid "Standard"
-msgstr "Standardní"
+msgstr "Standardní"
#: gui/ThemeEngine.cpp:350
msgid "Antialiased Renderer"
-msgstr "VykreslovaÄ s vyhlazenými hranami"
+msgstr "Vykreslovaè s vyhlazenými hranami"
#: gui/ThemeEngine.cpp:350
msgid "Antialiased"
-msgstr "S vyhlazenými hranami"
+msgstr "S vyhlazenými hranami"
#: gui/widget.cpp:323 gui/widget.cpp:325 gui/widget.cpp:331 gui/widget.cpp:333
msgid "Clear value"
-msgstr "VyÄistit hodnotu"
+msgstr "Vyèistit hodnotu"
#: base/main.cpp:237
#, c-format
msgid "Engine does not support debug level '%s'"
-msgstr "Jádro nepodporuje úroveň ladění '%s'"
+msgstr "Jádro nepodporuje úroveò ladìní '%s'"
#: base/main.cpp:309
msgid "Menu"
@@ -1259,7 +1257,7 @@ msgstr "Menu"
#: backends/platform/wince/CEActionsPocket.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:46
msgid "Skip"
-msgstr "PÅ™eskoÄit"
+msgstr "Pøeskoèit"
#: base/main.cpp:315 backends/platform/symbian/src/SymbianActions.cpp:50
#: backends/platform/wince/CEActionsPocket.cpp:42
@@ -1268,19 +1266,19 @@ msgstr "Pauza"
#: base/main.cpp:318
msgid "Skip line"
-msgstr "PÅ™eskoÄit řádek"
+msgstr "Pøeskoèit øádek"
#: base/main.cpp:510
msgid "Error running game:"
-msgstr "Chyba při spuštění hry:"
+msgstr "Chyba pøi spu¹tìní hry:"
#: base/main.cpp:557
msgid "Could not find any engine capable of running the selected game"
-msgstr "Nelze nalézt žádné jádro schopné vybranou hru spustit"
+msgstr "Nelze nalézt ¾ádné jádro schopné vybranou hru spustit"
#: common/error.cpp:38
msgid "No error"
-msgstr "Žádná chyba"
+msgstr "®ádná chyba"
#: common/error.cpp:40
msgid "Game data not found"
@@ -1288,19 +1286,19 @@ msgstr "Data hry nenalezena"
#: common/error.cpp:42
msgid "Game id not supported"
-msgstr "Id hry není podporováno"
+msgstr "Id hry není podporováno"
#: common/error.cpp:44
msgid "Unsupported color mode"
-msgstr "Nepodporovaný barevný režim"
+msgstr "Nepodporovaný barevný re¾im"
#: common/error.cpp:47
msgid "Read permission denied"
-msgstr "OprávnÄ›ní ke Ätení zamítnuto"
+msgstr "Oprávnìní ke ètení zamítnuto"
#: common/error.cpp:49
msgid "Write permission denied"
-msgstr "Oprávnění k zápisu zamítnuto"
+msgstr "Oprávnìní k zápisu zamítnuto"
#: common/error.cpp:52
msgid "Path does not exist"
@@ -1308,91 +1306,91 @@ msgstr "Cesta neexistuje"
#: common/error.cpp:54
msgid "Path not a directory"
-msgstr "Cesta není adresář"
+msgstr "Cesta není adresáø"
#: common/error.cpp:56
msgid "Path not a file"
-msgstr "Cesta není soubor"
+msgstr "Cesta není soubor"
#: common/error.cpp:59
msgid "Cannot create file"
-msgstr "Nelze vytvořit soubor"
+msgstr "Nelze vytvoøit soubor"
#: common/error.cpp:61
msgid "Reading data failed"
-msgstr "Čtení dat selhalo"
+msgstr "Ètení dat selhalo"
#: common/error.cpp:63
msgid "Writing data failed"
-msgstr "Zápis dat selhal"
+msgstr "Zápis dat selhal"
#: common/error.cpp:66
msgid "Could not find suitable engine plugin"
-msgstr "Nelze nalézt vhodný zás. modul jádra"
+msgstr "Nelze nalézt vhodný zás. modul jádra"
#: common/error.cpp:68
msgid "Engine plugin does not support save states"
-msgstr "Zás. modul jádra nepodporuje uložené stavy"
+msgstr "Zás. modul jádra nepodporuje ulo¾ené stavy"
#: common/error.cpp:71
msgid "User canceled"
-msgstr "Zrušeno uživatelem"
+msgstr "Zru¹eno u¾ivatelem"
#: common/error.cpp:75
msgid "Unknown error"
-msgstr "Neznámá chyba"
+msgstr "Neznámá chyba"
#. I18N: Hercules is graphics card name
#: common/rendermode.cpp:35
msgid "Hercules Green"
-msgstr "Hercules Zelená"
+msgstr "Hercules Zelená"
#: common/rendermode.cpp:36
msgid "Hercules Amber"
-msgstr "Hercules Jantarová"
+msgstr "Hercules Jantarová"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 barev)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 barev)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
-msgstr "Hercules Zelená"
+msgstr "Hercules Zelená"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
-msgstr "Hercules Jantarová"
+msgstr "Hercules Jantarová"
#: engines/advancedDetector.cpp:317
#, c-format
msgid "The game in '%s' seems to be unknown."
-msgstr "Hra v '%s' se zdá být neznámá."
+msgstr "Hra v '%s' se zdá být neznámá."
#: engines/advancedDetector.cpp:318
msgid "Please, report the following data to the ScummVM team along with name"
-msgstr "Prosím nahlaste následující data týmu ScummVM spolu se jménem"
+msgstr "Prosím nahlaste následující data týmu ScummVM spolu se jménem"
#: engines/advancedDetector.cpp:320
msgid "of the game you tried to add and its version/language/etc.:"
-msgstr "hry, kterou jste se pokusili přidat a její verzi/jazyk/atd.:"
+msgstr "hry, kterou jste se pokusili pøidat a její verzi/jazyk/atd.:"
#: engines/dialogs.cpp:85
msgid "~R~esume"
-msgstr "~P~okraÄovat"
+msgstr "~P~okraèovat"
#: engines/dialogs.cpp:87
msgid "~L~oad"
-msgstr "~N~ahrát"
+msgstr "~N~ahrát"
#: engines/dialogs.cpp:91
msgid "~S~ave"
-msgstr "~U~ložit"
+msgstr "~U~lo¾it"
#: engines/dialogs.cpp:95
msgid "~O~ptions"
@@ -1400,7 +1398,7 @@ msgstr "~V~olby"
#: engines/dialogs.cpp:100
msgid "~H~elp"
-msgstr "~N~ápověda"
+msgstr "~N~ápovìda"
#: engines/dialogs.cpp:102
msgid "~A~bout"
@@ -1408,33 +1406,41 @@ msgstr "~O~ programu"
#: engines/dialogs.cpp:105 engines/dialogs.cpp:181
msgid "~R~eturn to Launcher"
-msgstr "~N~ávrat do SpouÅ¡tÄ›Äe"
+msgstr "~N~ávrat do Spou¹tìèe"
#: engines/dialogs.cpp:107 engines/dialogs.cpp:183
msgctxt "lowres"
msgid "~R~eturn to Launcher"
-msgstr "~N~ávrat do SpouÅ¡tÄ›Äe"
+msgstr "~N~ávrat do Spou¹tìèe"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
-msgstr "Uložit hru:"
+msgstr "Ulo¾it hru:"
#: engines/dialogs.cpp:116 backends/platform/symbian/src/SymbianActions.cpp:44
#: backends/platform/wince/CEActionsPocket.cpp:43
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
-msgstr "Uložit"
+msgstr "Ulo¾it"
#: engines/dialogs.cpp:145
msgid ""
@@ -1442,9 +1448,9 @@ msgid ""
"the README for basic information, and for instructions on how to obtain "
"further assistance."
msgstr ""
-"Je nám líto, ale toto jádro v souÄasnosti nepodporuje herní nápovÄ›du. "
-"Prosím prohlédněte si README pro základní informace a pro instrukce jak zí"
-"skat další pomoc."
+"Je nám líto, ale toto jádro v souèasnosti nepodporuje herní nápovìdu. Prosím "
+"prohlédnìte si README pro základní informace a pro instrukce jak získat "
+"dal¹í pomoc."
#: engines/dialogs.cpp:234 engines/pegasus/pegasus.cpp:393
#, c-format
@@ -1452,8 +1458,8 @@ msgid ""
"Gamestate save failed (%s)! Please consult the README for basic information, "
"and for instructions on how to obtain further assistance."
msgstr ""
-"Uložení stavu hry selhalo (%s)! Prosím pÅ™eÄtÄ›te si dokumentaci pro "
-"základní informace a pokyny k získání další podpory."
+"Ulo¾ení stavu hry selhalo (%s)! Prosím pøeètìte si dokumentaci pro základní "
+"informace a pokyny k získání dal¹í podpory."
#: engines/dialogs.cpp:307 engines/mohawk/dialogs.cpp:109
#: engines/mohawk/dialogs.cpp:170 engines/tsage/dialogs.cpp:106
@@ -1463,27 +1469,27 @@ msgstr "~O~K"
#: engines/dialogs.cpp:308 engines/mohawk/dialogs.cpp:110
#: engines/mohawk/dialogs.cpp:171 engines/tsage/dialogs.cpp:107
msgid "~C~ancel"
-msgstr "~Z~rušit"
+msgstr "~Z~ru¹it"
#: engines/dialogs.cpp:311
msgid "~K~eys"
-msgstr "~K~lávesy"
+msgstr "~K~lávesy"
#: engines/engine.cpp:339
msgid "Could not initialize color format."
-msgstr "Nelze zavést barevný formát."
+msgstr "Nelze zavést barevný formát."
#: engines/engine.cpp:347
msgid "Could not switch to video mode: '"
-msgstr "Nelze přepnout na režim obrazu: '"
+msgstr "Nelze pøepnout na re¾im obrazu: '"
#: engines/engine.cpp:356
msgid "Could not apply aspect ratio setting."
-msgstr "Nelze použít nastavení poměru stran."
+msgstr "Nelze pou¾ít nastavení pomìru stran."
#: engines/engine.cpp:361
msgid "Could not apply fullscreen setting."
-msgstr "Nelze použít nastavení celé obrazovky."
+msgstr "Nelze pou¾ít nastavení celé obrazovky."
#: engines/engine.cpp:461
msgid ""
@@ -1493,11 +1499,11 @@ msgid ""
"the data files to your hard disk instead.\n"
"See the README file for details."
msgstr ""
-"Vypadá to, že tuto hru hrajete přímo z\n"
-" CD. Je známo, že toto způsobuje problémy\n"
-" a je tedy doporuÄeno, aÅ¥ místo toho zkopírujete\n"
-"datové soubory na Váš pevný disk.\n"
-"Pro podrobnosti si pÅ™eÄtÄ›te README."
+"Vypadá to, ¾e tuto hru hrajete pøímo z\n"
+" CD. Je známo, ¾e toto zpùsobuje problémy\n"
+" a je tedy doporuèeno, a» místo toho zkopírujete\n"
+"datové soubory na Vá¹ pevný disk.\n"
+"Pro podrobnosti si pøeètìte README."
#: engines/engine.cpp:472
msgid ""
@@ -1507,11 +1513,11 @@ msgid ""
"order to listen to the game's music.\n"
"See the README file for details."
msgstr ""
-"Tato hra má na svém disku zvukové stopy. Tyto\n"
-"stopy musí být z disku zkopírovány použitím\n"
-"vhodného nástroje pro extrakci zvuku z CD,\n"
-"abyste mohli poslouchat hudbu ve hře.\n"
-"Pro podrobnosti si pÅ™eÄtÄ›te README."
+"Tato hra má na svém disku zvukové stopy. Tyto\n"
+"stopy musí být z disku zkopírovány pou¾itím\n"
+"vhodného nástroje pro extrakci zvuku z CD,\n"
+"abyste mohli poslouchat hudbu ve høe.\n"
+"Pro podrobnosti si pøeètìte README."
#: engines/engine.cpp:530
#, c-format
@@ -1519,8 +1525,8 @@ msgid ""
"Gamestate load failed (%s)! Please consult the README for basic information, "
"and for instructions on how to obtain further assistance."
msgstr ""
-"NaÄtení stavu hry selhalo (%s)! Prosím pÅ™eÄtÄ›te si dokumentaci pro základní "
-"informace a pokyny k získání další podpory."
+"Naètení stavu hry selhalo (%s)! Prosím pøeètìte si dokumentaci pro základní "
+"informace a pokyny k získání dal¹í podpory."
#: engines/engine.cpp:543
msgid ""
@@ -1528,29 +1534,29 @@ msgid ""
"ScummVM. As such, it is likely to be unstable, and any saves you make might "
"not work in future versions of ScummVM."
msgstr ""
-"VAROVÃNÃ: Hra, kterou se chystáte spustit, není jeÅ¡tÄ› plnÄ› podporována "
-"ScummVM. Proto je možné, že bude nestabilní a jakékoli uložené hry "
-"nemusí fungovat v budoucích verzích ScummVM."
+"VAROVÁNÍ: Hra, kterou se chystáte spustit, není je¹tì plnì podporována "
+"ScummVM. Proto je mo¾né, ¾e bude nestabilní a jakékoli ulo¾ené hry nemusí "
+"fungovat v budoucích verzích ScummVM."
#: engines/engine.cpp:546
msgid "Start anyway"
-msgstr "Přesto spustit"
+msgstr "Pøesto spustit"
#: audio/adlib.cpp:2291
msgid "AdLib Emulator"
-msgstr "AdLib Emulátor"
+msgstr "AdLib Emulátor"
#: audio/fmopl.cpp:62
msgid "MAME OPL emulator"
-msgstr "MAME OPL Emulátor"
+msgstr "MAME OPL Emulátor"
#: audio/fmopl.cpp:64
msgid "DOSBox OPL emulator"
-msgstr "DOSBox OPL Emulátor"
+msgstr "DOSBox OPL Emulátor"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr "ALSA Přímá FM"
+msgstr "ALSA Pøímá FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1558,13 +1564,13 @@ msgid ""
"The selected audio device '%s' was not found (e.g. might be turned off or "
"disconnected)."
msgstr ""
-"Zvolené zvukové zařízení '%s' nebylo nalezeno (např. může být vypnuto "
-"nebo odpojeno)."
+"Zvolené zvukové zaøízení '%s' nebylo nalezeno (napø. mù¾e být vypnuto nebo "
+"odpojeno)."
#: audio/mididrv.cpp:209 audio/mididrv.cpp:221 audio/mididrv.cpp:257
#: audio/mididrv.cpp:272
msgid "Attempting to fall back to the next available device..."
-msgstr "Pokus o navrácení na nejbližší dostupné zařízení..."
+msgstr "Pokus o navrácení na nejbli¾¹í dostupné zaøízení..."
#: audio/mididrv.cpp:221
#, c-format
@@ -1572,8 +1578,8 @@ msgid ""
"The selected audio device '%s' cannot be used. See log file for more "
"information."
msgstr ""
-"Zvolené zvukové zařízení '%s' nelze použít. Podívejte se na záznam pro ví"
-"ce informací."
+"Zvolené zvukové zaøízení '%s' nelze pou¾ít. Podívejte se na záznam pro více "
+"informací."
#: audio/mididrv.cpp:257
#, c-format
@@ -1581,7 +1587,7 @@ msgid ""
"The preferred audio device '%s' was not found (e.g. might be turned off or "
"disconnected)."
msgstr ""
-"Upřednostňované zvukové zařízení '%s' nebylo nalezeno (např. může být "
+"Upøednostòované zvukové zaøízení '%s' nebylo nalezeno (napø. mù¾e být "
"vypnuto nebo odpojeno)."
#: audio/mididrv.cpp:272
@@ -1590,12 +1596,12 @@ msgid ""
"The preferred audio device '%s' cannot be used. See log file for more "
"information."
msgstr ""
-"Upřednostňované zvukové zařízení '%s' nelze použít. Podívejte se na "
-"záznam pro více informací."
+"Upøednostòované zvukové zaøízení '%s' nelze pou¾ít. Podívejte se na záznam "
+"pro více informací."
#: audio/mods/paula.cpp:196
msgid "Amiga Audio Emulator"
-msgstr "Emulátor zvuku Amiga"
+msgstr "Emulátor zvuku Amiga"
#: audio/null.h:44
msgid "No music"
@@ -1603,53 +1609,51 @@ msgstr "Bez hudby"
#: audio/softsynth/appleiigs.cpp:33
msgid "Apple II GS Emulator (NOT IMPLEMENTED)"
-msgstr "Apple II GS Emulátor (NENà ZAVEDEN)"
+msgstr "Apple II GS Emulátor (NENÍ ZAVEDEN)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Emulátor hudebního systému Creative"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "FM Towns Emulátor"
+msgstr "Zvuk FM-Towns"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Zvuk"
+msgstr "Zvuk PC-98"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
-msgstr "Zavádím MT-32 Emulátor"
+msgstr "Zavádím MT-32 Emulátor"
#: audio/softsynth/mt32.cpp:426
msgid "MT-32 Emulator"
-msgstr "MT-32 Emulátor"
+msgstr "MT-32 Emulátor"
#: audio/softsynth/pcspk.cpp:139
msgid "PC Speaker Emulator"
-msgstr "PC Speaker Emulátor"
+msgstr "PC Speaker Emulátor"
#: audio/softsynth/pcspk.cpp:158
msgid "IBM PCjr Emulator"
-msgstr "IBM PCjr Emulátor"
+msgstr "IBM PCjr Emulátor"
#: audio/softsynth/sid.cpp:1430
msgid "C64 Audio Emulator"
-msgstr "Emulátor zvuku C64"
+msgstr "Emulátor zvuku C64"
#: backends/events/default/default-events.cpp:196
msgid "Do you really want to return to the Launcher?"
-msgstr "Opravdu se chcete vrátit do SpouÅ¡tÄ›Äe?"
+msgstr "Opravdu se chcete vrátit do Spou¹tìèe?"
#: backends/events/default/default-events.cpp:196
msgid "Launcher"
-msgstr "SpouÅ¡tÄ›Ä"
+msgstr "Spou¹tìè"
#: backends/events/default/default-events.cpp:218
msgid "Do you really want to quit?"
-msgstr "Opravdu chcete skonÄit?"
+msgstr "Opravdu chcete skonèit?"
#: backends/events/default/default-events.cpp:218
#: backends/platform/symbian/src/SymbianActions.cpp:52
@@ -1658,88 +1662,87 @@ msgstr "Opravdu chcete skonÄit?"
#: engines/scumm/dialogs.cpp:192 engines/scumm/help.cpp:83
#: engines/scumm/help.cpp:85
msgid "Quit"
-msgstr "UkonÄit"
+msgstr "Ukonèit"
#: backends/events/gph/gph-events.cpp:385
#: backends/events/gph/gph-events.cpp:428
#: backends/events/openpandora/op-events.cpp:168
msgid "Touchscreen 'Tap Mode' - Left Click"
-msgstr "'Režim Ťuknutí' Dotykové Obrazovky - Levé Kliknutí"
+msgstr "'Re¾im «uknutí' Dotykové Obrazovky - Levé Kliknutí"
#: backends/events/gph/gph-events.cpp:387
#: backends/events/gph/gph-events.cpp:430
#: backends/events/openpandora/op-events.cpp:170
msgid "Touchscreen 'Tap Mode' - Right Click"
-msgstr "'Režim Ťuknutí' Dotykové Obrazovky - Pravé Kliknutí"
+msgstr "'Re¾im «uknutí' Dotykové Obrazovky - Pravé Kliknutí"
#: backends/events/gph/gph-events.cpp:389
#: backends/events/gph/gph-events.cpp:432
#: backends/events/openpandora/op-events.cpp:172
msgid "Touchscreen 'Tap Mode' - Hover (No Click)"
-msgstr "'Režim Ťuknutí' Dotykové Obrazovky - Najetí (Bez Kliknutí)"
+msgstr "'Re¾im «uknutí' Dotykové Obrazovky - Najetí (Bez Kliknutí)"
#: backends/events/gph/gph-events.cpp:409
msgid "Maximum Volume"
-msgstr "Maximální Hlasitost"
+msgstr "Maximální Hlasitost"
#: backends/events/gph/gph-events.cpp:411
msgid "Increasing Volume"
-msgstr "Zvyšuji Hlasitost"
+msgstr "Zvy¹uji Hlasitost"
#: backends/events/gph/gph-events.cpp:417
msgid "Minimal Volume"
-msgstr "Minimální Hlasitost"
+msgstr "Minimální Hlasitost"
#: backends/events/gph/gph-events.cpp:419
msgid "Decreasing Volume"
-msgstr "Snižuji Hlasitost"
+msgstr "Sni¾uji Hlasitost"
#: backends/events/maemosdl/maemosdl-events.cpp:180
msgid "Clicking Enabled"
-msgstr "Kliknutí Povoleno"
+msgstr "Kliknutí Povoleno"
#: backends/events/maemosdl/maemosdl-events.cpp:180
msgid "Clicking Disabled"
-msgstr "Kliknutí Zakázáno"
+msgstr "Kliknutí Zakázáno"
#: backends/events/openpandora/op-events.cpp:174
msgid "Touchscreen 'Tap Mode' - Hover (DPad Clicks)"
-msgstr "'Režim Ťuknutí' Dotykové Obrazovky - Najetí (Dpad kliká)"
+msgstr "'Re¾im «uknutí' Dotykové Obrazovky - Najetí (Dpad kliká)"
#: backends/events/symbiansdl/symbiansdl-events.cpp:186
msgid "Do you want to quit ?"
-msgstr "Chcete ukonÄit ?"
+msgstr "Chcete ukonèit ?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Touchpad režim vypnut"
+msgstr "Re¾im trackpadu je nyní"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "ZAPNUT"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "VYPNUT"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Pro zapnutí pøejeïte dvìma prsty doprava."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Re¾im automatického ta¾ení je nyní"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Pro zapnutí pøejeïte tøemi prsty doprava."
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1747,54 +1750,54 @@ msgstr "OpenGL"
#: backends/graphics/opengl/opengl-graphics.cpp:120
msgid "OpenGL (No filtering)"
-msgstr "OpenGL (bez filtrování)"
+msgstr "OpenGL (bez filtrování)"
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:47
#: backends/graphics/wincesdl/wincesdl-graphics.cpp:88
#: backends/graphics/wincesdl/wincesdl-graphics.cpp:95
msgid "Normal (no scaling)"
-msgstr "Normální (bez změny velikosti)"
+msgstr "Normální (bez zmìny velikosti)"
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:66
msgctxt "lowres"
msgid "Normal (no scaling)"
-msgstr "Normální (bez změny velikosti)"
+msgstr "Normální (bez zmìny velikosti)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
-msgstr "Povolena korekce poměru stran"
+msgstr "Povolena korekce pomìru stran"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
-msgstr "Zakázána korekce poměru stran"
+msgstr "Zakázána korekce pomìru stran"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
-msgstr "Aktivní grafický filtr:"
+msgstr "Aktivní grafický filtr:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
-msgstr "Režim do okna"
+msgstr "Re¾im do okna"
#: backends/keymapper/remap-dialog.cpp:48
msgid "Keymap:"
-msgstr "Mapa Kláves:"
+msgstr "Mapa Kláves:"
#: backends/keymapper/remap-dialog.cpp:67
msgid " (Effective)"
-msgstr " (Aktivní)"
+msgstr " (Aktivní)"
#: backends/keymapper/remap-dialog.cpp:107
msgid " (Active)"
-msgstr "(Aktivní)"
+msgstr "(Aktivní)"
#: backends/keymapper/remap-dialog.cpp:107
msgid " (Blocked)"
-msgstr " (Blokováno)"
+msgstr " (Blokováno)"
#: backends/keymapper/remap-dialog.cpp:120
msgid " (Global)"
-msgstr "(Globální)"
+msgstr "(Globální)"
#: backends/keymapper/remap-dialog.cpp:128
msgid " (Game)"
@@ -1807,43 +1810,43 @@ msgstr "Windows MIDI"
#: backends/platform/ds/arm9/source/dsoptions.cpp:56
#: engines/scumm/dialogs.cpp:291
msgid "~C~lose"
-msgstr "~Z~avřít"
+msgstr "~Z~avøít"
#: backends/platform/ds/arm9/source/dsoptions.cpp:57
msgid "ScummVM Main Menu"
-msgstr "Hlavní Menu ScummVM"
+msgstr "Hlavní Menu ScummVM"
#: backends/platform/ds/arm9/source/dsoptions.cpp:63
msgid "~L~eft handed mode"
-msgstr "~R~ežim pro leváky"
+msgstr "~R~e¾im pro leváky"
#: backends/platform/ds/arm9/source/dsoptions.cpp:64
msgid "~I~ndy fight controls"
-msgstr "~O~vládání Indyho boje"
+msgstr "~O~vládání Indyho boje"
#: backends/platform/ds/arm9/source/dsoptions.cpp:65
msgid "Show mouse cursor"
-msgstr "Zobrazit kurzor myši"
+msgstr "Zobrazit kurzor my¹i"
#: backends/platform/ds/arm9/source/dsoptions.cpp:66
msgid "Snap to edges"
-msgstr "Přichytit k okrajům"
+msgstr "Pøichytit k okrajùm"
#: backends/platform/ds/arm9/source/dsoptions.cpp:68
msgid "Touch X Offset"
-msgstr "Dotykové vyrovnáni na ose X"
+msgstr "Dotykové vyrovnáni na ose X"
#: backends/platform/ds/arm9/source/dsoptions.cpp:75
msgid "Touch Y Offset"
-msgstr "Dotykové vyrovnáni na ose Y"
+msgstr "Dotykové vyrovnáni na ose Y"
#: backends/platform/ds/arm9/source/dsoptions.cpp:87
msgid "Use laptop trackpad-style cursor control"
-msgstr "Použít styl kontroly kurzoru jako u ovládací podušky laptopu"
+msgstr "Pou¾ít styl kontroly kurzoru jako u ovládací podu¹ky laptopu"
#: backends/platform/ds/arm9/source/dsoptions.cpp:88
msgid "Tap for left click, double tap right click"
-msgstr "Ťukněte pro levé kliknutí, dvakrát pro pravé kliknutí"
+msgstr "«uknìte pro levé kliknutí, dvakrát pro pravé kliknutí"
#: backends/platform/ds/arm9/source/dsoptions.cpp:90
msgid "Sensitivity"
@@ -1851,23 +1854,23 @@ msgstr "Citlivost"
#: backends/platform/ds/arm9/source/dsoptions.cpp:99
msgid "Initial top screen scale:"
-msgstr "PoÄáteÄní zmÄ›na velikosti horní obrazovky:"
+msgstr "Poèáteèní zmìna velikosti horní obrazovky:"
#: backends/platform/ds/arm9/source/dsoptions.cpp:105
msgid "Main screen scaling:"
-msgstr "Změna velikosti hlavní obrazovky:"
+msgstr "Zmìna velikosti hlavní obrazovky:"
#: backends/platform/ds/arm9/source/dsoptions.cpp:107
msgid "Hardware scale (fast, but low quality)"
-msgstr "Hardwarová změna velikosti (rychlé, ale nízká kvalita)"
+msgstr "Hardwarová zmìna velikosti (rychlé, ale nízká kvalita)"
#: backends/platform/ds/arm9/source/dsoptions.cpp:108
msgid "Software scale (good quality, but slower)"
-msgstr "Softwarová změna velikosti (dobrá kvalita, ale pomalejší)"
+msgstr "Softwarová zmìna velikosti (dobrá kvalita, ale pomalej¹í)"
#: backends/platform/ds/arm9/source/dsoptions.cpp:109
msgid "Unscaled (you must scroll left and right)"
-msgstr "Beze změny velikosti (musíte posunovat doleva a doprava)"
+msgstr "Beze zmìny velikosti (musíte posunovat doleva a doprava)"
#: backends/platform/ds/arm9/source/dsoptions.cpp:111
msgid "Brightness:"
@@ -1875,39 +1878,39 @@ msgstr "Jas:"
#: backends/platform/ds/arm9/source/dsoptions.cpp:121
msgid "High quality audio (slower) (reboot)"
-msgstr "Vysoká kvalita zvuku (pomalejší) (restart) "
+msgstr "Vysoká kvalita zvuku (pomalej¹í) (restart) "
#: backends/platform/ds/arm9/source/dsoptions.cpp:122
msgid "Disable power off"
-msgstr "Zakázat vypnutí"
+msgstr "Zakázat vypnutí"
#: backends/platform/ios7/ios7_osys_events.cpp:309
#: backends/platform/ios7/ios7_osys_events.cpp:519
#: backends/platform/iphone/osys_events.cpp:300
msgid "Mouse-click-and-drag mode enabled."
-msgstr "Režim přetáhnutí myši zapnut."
+msgstr "Re¾im pøetáhnutí my¹i zapnut."
#: backends/platform/ios7/ios7_osys_events.cpp:311
#: backends/platform/ios7/ios7_osys_events.cpp:521
#: backends/platform/iphone/osys_events.cpp:302
msgid "Mouse-click-and-drag mode disabled."
-msgstr "Režim přetáhnutí myši vypnut."
+msgstr "Re¾im pøetáhnutí my¹i vypnut."
#: backends/platform/ios7/ios7_osys_events.cpp:322
#: backends/platform/ios7/ios7_osys_events.cpp:540
#: backends/platform/iphone/osys_events.cpp:313
msgid "Touchpad mode enabled."
-msgstr "Touchpad režim zapnut"
+msgstr "Touchpad re¾im zapnut"
#: backends/platform/ios7/ios7_osys_events.cpp:324
#: backends/platform/ios7/ios7_osys_events.cpp:542
#: backends/platform/iphone/osys_events.cpp:315
msgid "Touchpad mode disabled."
-msgstr "Touchpad režim vypnut"
+msgstr "Touchpad re¾im vypnut"
#: backends/platform/maemo/maemo.cpp:208
msgid "Click Mode"
-msgstr "Režim kliknutí"
+msgstr "Re¾im kliknutí"
#: backends/platform/maemo/maemo.cpp:214
#: backends/platform/symbian/src/SymbianActions.cpp:42
@@ -1915,30 +1918,30 @@ msgstr "Režim kliknutí"
#: backends/platform/wince/CEActionsPocket.cpp:60
#: backends/platform/wince/CEActionsSmartphone.cpp:43
msgid "Left Click"
-msgstr "Levé Kliknutí"
+msgstr "Levé Kliknutí"
#: backends/platform/maemo/maemo.cpp:217
msgid "Middle Click"
-msgstr "Kliknutí prostÅ™edním tlaÄítkem"
+msgstr "Kliknutí prostøedním tlaèítkem"
#: backends/platform/maemo/maemo.cpp:220
#: backends/platform/symbian/src/SymbianActions.cpp:43
#: backends/platform/tizen/form.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:44
msgid "Right Click"
-msgstr "Pravé kliknutí"
+msgstr "Pravé kliknutí"
#: backends/platform/sdl/macosx/appmenu_osx.mm:88
msgid "Hide ScummVM"
-msgstr "Skrýt ScummVM"
+msgstr "Skrýt ScummVM"
#: backends/platform/sdl/macosx/appmenu_osx.mm:93
msgid "Hide Others"
-msgstr "Skrýt Ostatní"
+msgstr "Skrýt Ostatní"
#: backends/platform/sdl/macosx/appmenu_osx.mm:98
msgid "Show All"
-msgstr "Zobrazit VÅ¡e"
+msgstr "Zobrazit V¹e"
#: backends/platform/sdl/macosx/appmenu_osx.mm:120
#: backends/platform/sdl/macosx/appmenu_osx.mm:131
@@ -1957,7 +1960,7 @@ msgstr "Nahoru"
#: backends/platform/symbian/src/SymbianActions.cpp:39
#: backends/platform/wince/CEActionsSmartphone.cpp:40
msgid "Down"
-msgstr "Dolů"
+msgstr "Dolù"
#: backends/platform/symbian/src/SymbianActions.cpp:40
#: backends/platform/wince/CEActionsSmartphone.cpp:41
@@ -1982,35 +1985,35 @@ msgstr "Multi Funkce"
#: backends/platform/symbian/src/SymbianActions.cpp:48
msgid "Swap character"
-msgstr "Zaměnit znaky"
+msgstr "Zamìnit znaky"
#: backends/platform/symbian/src/SymbianActions.cpp:49
msgid "Skip text"
-msgstr "PÅ™eskoÄit text"
+msgstr "Pøeskoèit text"
#: backends/platform/symbian/src/SymbianActions.cpp:51
msgid "Fast mode"
-msgstr "Rychlý režim"
+msgstr "Rychlý re¾im"
#: backends/platform/symbian/src/SymbianActions.cpp:53
msgid "Debugger"
-msgstr "Ladící program"
+msgstr "Ladící program"
#: backends/platform/symbian/src/SymbianActions.cpp:54
msgid "Global menu"
-msgstr "Globální menu"
+msgstr "Globální menu"
#: backends/platform/symbian/src/SymbianActions.cpp:55
msgid "Virtual keyboard"
-msgstr "Virtuální klávesnice"
+msgstr "Virtuální klávesnice"
#: backends/platform/symbian/src/SymbianActions.cpp:56
msgid "Key mapper"
-msgstr "MapovaÄ kláves"
+msgstr "Mapovaè kláves"
#: backends/platform/tizen/form.cpp:263
msgid "Right Click Once"
-msgstr "Pravé kliknutí jednou"
+msgstr "Pravé kliknutí jednou"
#: backends/platform/tizen/form.cpp:271
msgid "Move Only"
@@ -2018,7 +2021,7 @@ msgstr "Pouze Pohyb"
#: backends/platform/tizen/form.cpp:294
msgid "Escape Key"
-msgstr "Klávesa Escape"
+msgstr "Klávesa Escape"
#: backends/platform/tizen/form.cpp:299
msgid "Game Menu"
@@ -2026,32 +2029,31 @@ msgstr "Menu Hry"
#: backends/platform/tizen/form.cpp:304
msgid "Show Keypad"
-msgstr "Zobrazit Klávesnici"
+msgstr "Zobrazit Klávesnici"
#: backends/platform/tizen/form.cpp:309
msgid "Control Mouse"
-msgstr "Ovládání Myši"
+msgstr "Ovládání My¹i"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Data ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Zdroje ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SD Karta ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Média ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Sdílení:"
+msgstr "[ Sdílené ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2059,19 +2061,19 @@ msgstr "Video"
#: backends/platform/wii/options.cpp:54
msgid "Current video mode:"
-msgstr "SouÄasný režim obrazu:"
+msgstr "Souèasný re¾im obrazu:"
#: backends/platform/wii/options.cpp:56
msgid "Double-strike"
-msgstr "Dvojité přeškrtnutí"
+msgstr "Dvojité pøe¹krtnutí"
#: backends/platform/wii/options.cpp:60
msgid "Horizontal underscan:"
-msgstr "Horizontální zmenšení"
+msgstr "Horizontální zmen¹ení"
#: backends/platform/wii/options.cpp:66
msgid "Vertical underscan:"
-msgstr "Vertikální zmenšení"
+msgstr "Vertikální zmen¹ení"
#: backends/platform/wii/options.cpp:71
msgid "Input"
@@ -2083,7 +2085,7 @@ msgstr "Citlivost GC Padu"
#: backends/platform/wii/options.cpp:80
msgid "GC Pad acceleration:"
-msgstr "Zrychlení GC Padu"
+msgstr "Zrychlení GC Padu"
#: backends/platform/wii/options.cpp:86
msgid "DVD"
@@ -2095,11 +2097,11 @@ msgstr "Stav:"
#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
msgid "Unknown"
-msgstr "Neznámé"
+msgstr "Neznámé"
#: backends/platform/wii/options.cpp:93
msgid "Mount DVD"
-msgstr "Připojit DVD"
+msgstr "Pøipojit DVD"
#: backends/platform/wii/options.cpp:94
msgid "Unmount DVD"
@@ -2115,11 +2117,11 @@ msgstr "Server:"
#: backends/platform/wii/options.cpp:110
msgid "Share:"
-msgstr "Sdílení:"
+msgstr "Sdílení:"
#: backends/platform/wii/options.cpp:114
msgid "Username:"
-msgstr "Uživatelské jméno"
+msgstr "U¾ivatelské jméno"
#: backends/platform/wii/options.cpp:118
msgid "Password:"
@@ -2127,11 +2129,11 @@ msgstr "Heslo"
#: backends/platform/wii/options.cpp:121
msgid "Init network"
-msgstr "Spustit síť"
+msgstr "Spustit sí»"
#: backends/platform/wii/options.cpp:123
msgid "Mount SMB"
-msgstr "Připojit SMB"
+msgstr "Pøipojit SMB"
#: backends/platform/wii/options.cpp:124
msgid "Unmount SMB"
@@ -2139,56 +2141,56 @@ msgstr "Odpojit SMB"
#: backends/platform/wii/options.cpp:143
msgid "DVD Mounted successfully"
-msgstr "DVD úspěšně připojeno"
+msgstr "DVD úspì¹nì pøipojeno"
#: backends/platform/wii/options.cpp:146
msgid "Error while mounting the DVD"
-msgstr "Chyba při připojování DVD"
+msgstr "Chyba pøi pøipojování DVD"
#: backends/platform/wii/options.cpp:148
msgid "DVD not mounted"
-msgstr "DVD nepřipojeno"
+msgstr "DVD nepøipojeno"
#: backends/platform/wii/options.cpp:161
msgid "Network up, share mounted"
-msgstr "Síť je zapnuta, sdílení připojeno"
+msgstr "Sí» je zapnuta, sdílení pøipojeno"
#: backends/platform/wii/options.cpp:163
msgid "Network up"
-msgstr "Síť je zapnuta"
+msgstr "Sí» je zapnuta"
#: backends/platform/wii/options.cpp:166
msgid ", error while mounting the share"
-msgstr ", chyba při připojování sdílení"
+msgstr ", chyba pøi pøipojování sdílení"
#: backends/platform/wii/options.cpp:168
msgid ", share not mounted"
-msgstr ", sdílení není připojeno"
+msgstr ", sdílení není pøipojeno"
#: backends/platform/wii/options.cpp:174
msgid "Network down"
-msgstr "Síť je nedostupná"
+msgstr "Sí» je nedostupná"
#: backends/platform/wii/options.cpp:178
msgid "Initializing network"
-msgstr "Zavádím síť"
+msgstr "Zavádím sí»"
#: backends/platform/wii/options.cpp:182
msgid "Timeout while initializing network"
-msgstr "Při zavádění sítě vypršel limit"
+msgstr "Pøi zavádìní sítì vypr¹el limit"
#: backends/platform/wii/options.cpp:186
#, c-format
msgid "Network not initialized (%d)"
-msgstr "Síť není zavedena (%d)"
+msgstr "Sí» není zavedena (%d)"
#: backends/platform/wince/CEActionsPocket.cpp:46
msgid "Hide Toolbar"
-msgstr "Skrýt Panel nástrojů"
+msgstr "Skrýt Panel nástrojù"
#: backends/platform/wince/CEActionsPocket.cpp:47
msgid "Show Keyboard"
-msgstr "Zobrazit klávesnici"
+msgstr "Zobrazit klávesnici"
#: backends/platform/wince/CEActionsPocket.cpp:48
msgid "Sound on/off"
@@ -2196,66 +2198,66 @@ msgstr "Zvuk zapnout/vypnout"
#: backends/platform/wince/CEActionsPocket.cpp:49
msgid "Right click"
-msgstr "Pravé kliknutí"
+msgstr "Pravé kliknutí"
#: backends/platform/wince/CEActionsPocket.cpp:50
msgid "Show/Hide Cursor"
-msgstr "Ukázat/Skrýt Kurzor"
+msgstr "Ukázat/Skrýt Kurzor"
#: backends/platform/wince/CEActionsPocket.cpp:51
msgid "Free look"
-msgstr "Rozhlížení pomocí myši"
+msgstr "Rozhlí¾ení pomocí my¹i"
#: backends/platform/wince/CEActionsPocket.cpp:52
msgid "Zoom up"
-msgstr "Přiblížení nahoru"
+msgstr "Pøiblí¾ení nahoru"
#: backends/platform/wince/CEActionsPocket.cpp:53
msgid "Zoom down"
-msgstr "Přiblížení dolů"
+msgstr "Pøiblí¾ení dolù"
#: backends/platform/wince/CEActionsPocket.cpp:55
#: backends/platform/wince/CEActionsSmartphone.cpp:49
msgid "Bind Keys"
-msgstr "Přiřadit klávesy"
+msgstr "Pøiøadit klávesy"
#: backends/platform/wince/CEActionsPocket.cpp:56
msgid "Cursor Up"
-msgstr "Å ipka Nahoru"
+msgstr "©ipka Nahoru"
#: backends/platform/wince/CEActionsPocket.cpp:57
msgid "Cursor Down"
-msgstr "Šipka Dolů"
+msgstr "©ipka Dolù"
#: backends/platform/wince/CEActionsPocket.cpp:58
msgid "Cursor Left"
-msgstr "Å ipka Doleva"
+msgstr "©ipka Doleva"
#: backends/platform/wince/CEActionsPocket.cpp:59
msgid "Cursor Right"
-msgstr "Å ipka Doprava"
+msgstr "©ipka Doprava"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
msgid "Do you want to load or save the game?"
-msgstr "Chcete hru nahrát nebo uložit?"
+msgstr "Chcete hru nahrát nebo ulo¾it?"
#: backends/platform/wince/CEActionsPocket.cpp:326
#: backends/platform/wince/CEActionsSmartphone.cpp:287
msgid " Are you sure you want to quit ? "
-msgstr " Jste si jisti, že chcete odejít ? "
+msgstr " Jste si jisti, ¾e chcete odejít ? "
#: backends/platform/wince/CEActionsSmartphone.cpp:50
msgid "Keyboard"
-msgstr "Klávesnice"
+msgstr "Klávesnice"
#: backends/platform/wince/CEActionsSmartphone.cpp:51
msgid "Rotate"
-msgstr "OtáÄet"
+msgstr "Otáèet"
#: backends/platform/wince/CELauncherDialog.cpp:56
msgid "Using SDL driver "
-msgstr "Používá ovladaÄ SDL"
+msgstr "Pou¾ívá ovladaè SDL"
#: backends/platform/wince/CELauncherDialog.cpp:60
msgid "Display "
@@ -2263,42 +2265,42 @@ msgstr "Displej"
#: backends/platform/wince/CELauncherDialog.cpp:83
msgid "Do you want to perform an automatic scan ?"
-msgstr "Chcete provést automatické hledání ?"
+msgstr "Chcete provést automatické hledání ?"
#: backends/platform/wince/wince-sdl.cpp:516
msgid "Map right click action"
-msgstr "Mapovat Äinnost pravé kliknutí"
+msgstr "Mapovat èinnost pravé kliknutí"
#: backends/platform/wince/wince-sdl.cpp:520
msgid "You must map a key to the 'Right Click' action to play this game"
msgstr ""
-"Musíte namapovat klávesu pro Äinnost 'Pravé Kliknutí', abyste tuto hru "
-"mohli hrát"
+"Musíte namapovat klávesu pro èinnost 'Pravé Kliknutí', abyste tuto hru mohli "
+"hrát"
#: backends/platform/wince/wince-sdl.cpp:529
msgid "Map hide toolbar action"
-msgstr "Mapovat Äinnost skrýt panel nástrojů"
+msgstr "Mapovat èinnost skrýt panel nástrojù"
#: backends/platform/wince/wince-sdl.cpp:533
msgid "You must map a key to the 'Hide toolbar' action to play this game"
msgstr ""
-"Musíte namapovat klávesu pro Äinnost 'Skrýt Panel nástrojů', abyste tuto "
-"hru mohli hrát"
+"Musíte namapovat klávesu pro èinnost 'Skrýt Panel nástrojù', abyste tuto hru "
+"mohli hrát"
#: backends/platform/wince/wince-sdl.cpp:542
msgid "Map Zoom Up action (optional)"
-msgstr "Namapovat Äinnost PÅ™iblížit Nahoru (nepovinné)"
+msgstr "Namapovat èinnost Pøiblí¾it Nahoru (nepovinné)"
#: backends/platform/wince/wince-sdl.cpp:545
msgid "Map Zoom Down action (optional)"
-msgstr "Namapovat Äinnost PÅ™iblížit Dolů (nepovinné)"
+msgstr "Namapovat èinnost Pøiblí¾it Dolù (nepovinné)"
#: backends/platform/wince/wince-sdl.cpp:553
msgid ""
"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
msgstr ""
-"Nezapomeňte namapovat klávesu k Äinnosti 'Skrýt Panel Nástrojů, abyste "
-"viděli celý inventář"
+"Nezapomeòte namapovat klávesu k èinnosti 'Skrýt Panel Nástrojù, abyste "
+"vidìli celý inventáø"
#: backends/updates/macosx/macosx-updates.mm:67
msgid "Check for Updates..."
@@ -2309,47 +2311,55 @@ msgstr "Zkontrolovat Aktualizace..."
#: engines/neverhood/detection.cpp:160 engines/sci/detection.cpp:404
#: engines/toltecs/detection.cpp:200 engines/zvision/detection_tables.h:51
msgid "Use original save/load screens"
-msgstr "Použít původní obrazovky naÄtení/uložení"
+msgstr "Pou¾ít pùvodní obrazovky naètení/ulo¾ení"
#: engines/agi/detection.cpp:148 engines/cine/detection.cpp:71
#: engines/drascula/detection.cpp:303 engines/dreamweb/detection.cpp:48
#: engines/neverhood/detection.cpp:161 engines/sci/detection.cpp:405
#: engines/toltecs/detection.cpp:201
msgid "Use the original save/load screens, instead of the ScummVM ones"
-msgstr "Použít původní obrazovky naÄtení/uložení místo ze ScummVM"
+msgstr "Pou¾ít pùvodní obrazovky naètení/ulo¾ení místo ze ScummVM"
#: engines/agi/detection.cpp:157
msgid "Use an alternative palette"
-msgstr "Použít jinou paletu"
+msgstr "Pou¾ít jinou paletu"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
-"Použít alternativní paletu, běžné pro hry Amiga. Toto byl původní starý "
+"Pou¾ít alternativní paletu, bì¾né pro hry Amiga. Toto byl pùvodní starý "
"standard"
#: engines/agi/detection.cpp:167
msgid "Mouse support"
-msgstr "Podpora myši"
+msgstr "Podpora my¹i"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-"Povolí podporu myši. Umožní použít myš pro pohyb a pro ovládání herní"
-"ch nabídek."
+"Povolí podporu my¹i. Umo¾ní pou¾ít my¹ pro pohyb a pro ovládání herních "
+"nabídek."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Obnovit hru"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Obnovit"
@@ -2360,7 +2370,7 @@ msgid ""
"\n"
"%s"
msgstr ""
-"Nahrání stavu hry selhalo ze souboru:\n"
+"Nahrání stavu hry selhalo ze souboru:\n"
"\n"
"%s"
@@ -2371,7 +2381,7 @@ msgid ""
"\n"
"%s"
msgstr ""
-"Uložení stavu hry selhalo do souboru:\n"
+"Ulo¾ení stavu hry selhalo do souboru:\n"
"\n"
"%s"
@@ -2382,7 +2392,7 @@ msgid ""
"\n"
"%s"
msgstr ""
-"Stav hry úspěšně uložen do:\n"
+"Stav hry úspì¹nì ulo¾en do:\n"
"\n"
"%s"
@@ -2393,11 +2403,11 @@ msgstr "Soubor videa '%s' nenalezen'"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
msgid "Color Blind Mode"
-msgstr "Režim pro barvoslepé"
+msgstr "Re¾im pro barvoslepé"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr "Standardně zapínat režim pro barvoslepé"
+msgstr "Standardnì zapínat re¾im pro barvoslepé"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2409,31 +2419,31 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
-"ScummVM zjistil, že máte staré uložené pozice pro Drascula, které by "
-"měly být převedeny.\n"
-"Starý formát uložených her již není podporován, takže pokud je "
-"nepÅ™evedete, nebudete moci vaÅ¡e hry naÄíst.\n"
+"ScummVM zjistil, ¾e máte staré ulo¾ené pozice pro Drascula, které by mìly "
+"být pøevedeny.\n"
+"Starý formát ulo¾ených her ji¾ není podporován, tak¾e pokud je nepøevedete, "
+"nebudete moci va¹e hry naèíst.\n"
"\n"
-"StisknÄ›te OK, abyste je pÅ™evedli teÄ, jinak budete požádáni znovu, pÅ™i "
-"spuštění této hry.\n"
+"Stisknìte OK, abyste je pøevedli teï, jinak budete po¾ádáni znovu, pøi "
+"spu¹tìní této hry.\n"
#: engines/dreamweb/detection.cpp:57
msgid "Use bright palette mode"
-msgstr "Použít režim jasné palety"
+msgstr "Pou¾ít re¾im jasné palety"
#: engines/dreamweb/detection.cpp:58
msgid "Display graphics using the game's bright palette"
-msgstr "Zobrazit grafiku pomocí jasné palety hry"
+msgstr "Zobrazit grafiku pomocí jasné palety hry"
#: engines/gob/inter_playtoons.cpp:256 engines/gob/inter_v2.cpp:1470
#: engines/gob/inter_geisha.cpp:232 engines/tinsel/saveload.cpp:532
msgid "Failed to load game state from file."
-msgstr "Nelze naÄíst stav hry ze souboru."
+msgstr "Nelze naèíst stav hry ze souboru."
#: engines/gob/inter_v2.cpp:1540 engines/gob/inter_geisha.cpp:263
#: engines/tinsel/saveload.cpp:545
msgid "Failed to save game state to file."
-msgstr "Nelze uložit stav hry do souboru."
+msgstr "Nelze ulo¾it stav hry do souboru."
#: engines/gob/inter_v5.cpp:107
msgid "Failed to delete file."
@@ -2441,23 +2451,23 @@ msgstr "Nelze smazat soubor."
#: engines/groovie/detection.cpp:312
msgid "Fast movie speed"
-msgstr "Zvýšená rychlost videa"
+msgstr "Zvý¹ená rychlost videa"
#: engines/groovie/detection.cpp:313
msgid "Play movies at an increased speed"
-msgstr "Přehrát videa se zvýšenou rychlostí"
+msgstr "Pøehrát videa se zvý¹enou rychlostí"
#: engines/groovie/script.cpp:408
msgid "Failed to save game"
-msgstr "Nelze uložit hru."
+msgstr "Nelze ulo¾it hru."
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr "Povolit násilné scény"
+msgstr "Povolit násilné scény"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr "Povolit násilné scény, jsou-li dostupné"
+msgstr "Povolit násilné scény, jsou-li dostupné"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2472,66 +2482,66 @@ msgstr "Povolit publikum ve studiu"
#. I18N: This option allows the user to skip text and cutscenes.
#: engines/kyra/detection.cpp:73
msgid "Skip support"
-msgstr "Podpora pÅ™eskoÄení"
+msgstr "Podpora pøeskoèení"
#: engines/kyra/detection.cpp:74
msgid "Allow text and cutscenes to be skipped"
-msgstr "Umožnit, aby text a videa mohly být pÅ™eskoÄeny"
+msgstr "Umo¾nit, aby text a videa mohly být pøeskoèeny"
#. I18N: Helium mode makes people sound like they've inhaled Helium.
#: engines/kyra/detection.cpp:84
msgid "Helium mode"
-msgstr "Héliový režim"
+msgstr "Héliový re¾im"
#: engines/kyra/detection.cpp:85
msgid "Enable helium mode"
-msgstr "Zapnout héliový režim"
+msgstr "Zapnout héliový re¾im"
#. I18N: When enabled, this option makes scrolling smoother when
#. changing from one screen to another.
#: engines/kyra/detection.cpp:99
msgid "Smooth scrolling"
-msgstr "Plynulé posunování"
+msgstr "Plynulé posunování"
#: engines/kyra/detection.cpp:100
msgid "Enable smooth scrolling when walking"
-msgstr "Povolit plynulé posunování při chůzi"
+msgstr "Povolit plynulé posunování pøi chùzi"
#. I18N: When enabled, this option changes the cursor when it floats to the
#. edge of the screen to a directional arrow. The player can then click to
#. walk towards that direction.
#: engines/kyra/detection.cpp:112
msgid "Floating cursors"
-msgstr "Plovoucí kurzory"
+msgstr "Plovoucí kurzory"
#: engines/kyra/detection.cpp:113
msgid "Enable floating cursors"
-msgstr "Povolit plovoucí kurzory"
+msgstr "Povolit plovoucí kurzory"
#. I18N: HP stands for Hit Points
#: engines/kyra/detection.cpp:127
msgid "HP bar graphs"
-msgstr "Sloupcový indikátor zdraví"
+msgstr "Sloupcový indikátor zdraví"
#: engines/kyra/detection.cpp:128
msgid "Enable hit point bar graphs"
-msgstr "Povolit sloupcový indikátor zdraví"
+msgstr "Povolit sloupcový indikátor zdraví"
#: engines/kyra/lol.cpp:478
msgid "Attack 1"
-msgstr "Útok 1"
+msgstr "Útok 1"
#: engines/kyra/lol.cpp:479
msgid "Attack 2"
-msgstr "Útok 2"
+msgstr "Útok 2"
#: engines/kyra/lol.cpp:480
msgid "Attack 3"
-msgstr "Útok 3"
+msgstr "Útok 3"
#: engines/kyra/lol.cpp:481
msgid "Move Forward"
-msgstr "Vpřed"
+msgstr "Vpøed"
#: engines/kyra/lol.cpp:482
msgid "Move Back"
@@ -2539,23 +2549,23 @@ msgstr "Vzad"
#: engines/kyra/lol.cpp:483
msgid "Slide Left"
-msgstr "Přesunout se Doleva"
+msgstr "Pøesunout se Doleva"
#: engines/kyra/lol.cpp:484
msgid "Slide Right"
-msgstr "Přesunout se Doprava"
+msgstr "Pøesunout se Doprava"
#: engines/kyra/lol.cpp:485 engines/pegasus/pegasus.cpp:2509
msgid "Turn Left"
-msgstr "OtoÄit se doleva"
+msgstr "Otoèit se doleva"
#: engines/kyra/lol.cpp:486 engines/pegasus/pegasus.cpp:2510
msgid "Turn Right"
-msgstr "OtoÄit se doprava"
+msgstr "Otoèit se doprava"
#: engines/kyra/lol.cpp:487
msgid "Rest"
-msgstr "OdpoÄinout si"
+msgstr "Odpoèinout si"
#: engines/kyra/lol.cpp:488
msgid "Options"
@@ -2573,11 +2583,11 @@ msgid ""
"General MIDI ones. It is still possible that\n"
"some tracks sound incorrect."
msgstr ""
-"Zdá se, že používáte zařízení General MIDI,\n"
-"ale vaše hra podporuje pouze Roland MT32 MIDI.\n"
-"Snažíme se mapovat nástroje Roland MT32 na\n"
-"ty od General MIDI. Je stále možné, že\n"
-"některé stopy nebudou znít správně."
+"Zdá se, ¾e pou¾íváte zaøízení General MIDI,\n"
+"ale va¹e hra podporuje pouze Roland MT32 MIDI.\n"
+"Sna¾íme se mapovat nástroje Roland MT32 na\n"
+"ty od General MIDI. Je stále mo¾né, ¾e\n"
+"nìkteré stopy nebudou znít správnì."
#: engines/kyra/saveload_eob.cpp:557
#, c-format
@@ -2589,11 +2599,11 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
-"V cestě vaší hry byl nalezen následující soubor s uloženou hrou:\n"
+"V cestì va¹í hry byl nalezen následující soubor s ulo¾enou hrou:\n"
"\n"
"%s %s\n"
"\n"
-"Chcete tento soubor použít v ScummVM?\n"
+"Chcete tento soubor pou¾ít v ScummVM?\n"
"\n"
#: engines/kyra/saveload_eob.cpp:590
@@ -2602,7 +2612,7 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
-"V urÄené pozici %d byl nalezen soubor s uloženou hrou. PÅ™epsat?\n"
+"V urèené pozici %d byl nalezen soubor s ulo¾enou hrou. Pøepsat?\n"
"\n"
#: engines/kyra/saveload_eob.cpp:623
@@ -2615,24 +2625,24 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
-"%d původních souborů s uloženou hrou bylo úspěšně importováno do\n"
-"ScummVM. Pokud chcete pozdÄ›ji toto uÄinit znovu ruÄnÄ›, je tÅ™eba otevřít\n"
-"ladící konzoli ScummVM a použít příkaz 'import_savefile'.\n"
+"%d pùvodních souborù s ulo¾enou hrou bylo úspì¹nì importováno do\n"
+"ScummVM. Pokud chcete pozdìji toto uèinit znovu ruènì, je tøeba otevøít\n"
+"ladící konzoli ScummVM a pou¾ít pøíkaz 'import_savefile'.\n"
"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
msgid "~Z~ip Mode Activated"
-msgstr "~R~ežim Svištění Aktivován"
+msgstr "~R~e¾im Svi¹tìní Aktivován"
#: engines/mohawk/dialogs.cpp:93
msgid "~T~ransitions Enabled"
-msgstr "~P~řechody zapnuty"
+msgstr "~P~øechody zapnuty"
#. I18N: Drop book page
#: engines/mohawk/dialogs.cpp:95
msgid "~D~rop Page"
-msgstr "~Z~ahodit Stránku"
+msgstr "~Z~ahodit Stránku"
#: engines/mohawk/dialogs.cpp:99
msgid "~S~how Map"
@@ -2640,7 +2650,7 @@ msgstr "~Z~obrazit Mapu"
#: engines/mohawk/dialogs.cpp:105
msgid "~M~ain Menu"
-msgstr "~H~lavní Menu"
+msgstr "~H~lavní Menu"
#: engines/mohawk/dialogs.cpp:168
msgid "~W~ater Effect Enabled"
@@ -2648,19 +2658,19 @@ msgstr "~E~fekt Vody Zapnut"
#: engines/neverhood/detection.cpp:167
msgid "Skip the Hall of Records storyboard scenes"
-msgstr "PÅ™eskoÄit scény v Síni záznamů"
+msgstr "Pøeskoèit scény v Síni záznamù"
#: engines/neverhood/detection.cpp:168
msgid "Allows the player to skip past the Hall of Records storyboard scenes"
-msgstr "Umožňuje hráÄi pÅ™eskoÄit scény v Síni záznamů"
+msgstr "Umo¾òuje hráèi pøeskoèit scény v Síni záznamù"
#: engines/neverhood/detection.cpp:174
msgid "Scale the making of videos to full screen"
-msgstr "Zvětšit filmy o výrobě na celou obrazovku"
+msgstr "Zvìt¹it filmy o výrobì na celou obrazovku"
#: engines/neverhood/detection.cpp:175
msgid "Scale the making of videos, so that they use the whole screen"
-msgstr "Zvětšit filmy o výrobě tak, aby využivaly celou obrazovku"
+msgstr "Zvìt¹it filmy o výrobì tak, aby vyu¾ivaly celou obrazovku"
#: engines/parallaction/saveload.cpp:133
#, c-format
@@ -2668,16 +2678,26 @@ msgid ""
"Can't save game in slot %i\n"
"\n"
msgstr ""
-"Nelze uložit hru do pozice %i\n"
+"Nelze ulo¾it hru do pozice %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Nahrát hru:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
-msgstr "Nahrávání hry..."
+msgstr "Nahrávání hry..."
+
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Ukládání hry selhalo!"
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
-msgstr "Ukládání hry..."
+msgstr "Ukládání hry..."
#: engines/parallaction/saveload.cpp:272
msgid ""
@@ -2688,16 +2708,16 @@ msgid ""
"\n"
"Press OK to convert them now, otherwise you will be asked next time.\n"
msgstr ""
-"ScummVM zjistil, že máte staré uložené pozice pro Nippon Safes, které "
-"by měly být přejmenovány.\n"
-"Staré názvy již nejsou podporovány, takže pokud je nepřevedete, "
-"nebudete moci vaÅ¡e hry naÄíst.\n"
+"ScummVM zjistil, ¾e máte staré ulo¾ené pozice pro Nippon Safes, které by "
+"mìly být pøejmenovány.\n"
+"Staré názvy ji¾ nejsou podporovány, tak¾e pokud je nepøevedete, nebudete "
+"moci va¹e hry naèíst.\n"
"\n"
-"StisknÄ›te OK, abyste je pÅ™evedli teÄ, jinak budete požádáni příštÄ›.\n"
+"Stisknìte OK, abyste je pøevedli teï, jinak budete po¾ádáni pøí¹tì.\n"
#: engines/parallaction/saveload.cpp:319
msgid "ScummVM successfully converted all your savefiles."
-msgstr "ScummVM úspěšně převedl všechny vaše uložené pozice. "
+msgstr "ScummVM úspì¹nì pøevedl v¹echny va¹e ulo¾ené pozice. "
#: engines/parallaction/saveload.cpp:321
msgid ""
@@ -2706,211 +2726,208 @@ msgid ""
"\n"
"Please report to the team."
msgstr ""
-"ScummVM vytiskl některá varování ve vašem okně konzole a nemůže "
-"zaruÄit, že vÅ¡echny vaÅ¡e soubory byly pÅ™evedeny.\n"
+"ScummVM vytiskl nìkterá varování ve va¹em oknì konzole a nemù¾e zaruèit, ¾e "
+"v¹echny va¹e soubory byly pøevedeny.\n"
"\n"
-"Prosím nahlaste to týmu"
+"Prosím nahlaste to týmu"
#: engines/pegasus/pegasus.cpp:714
msgid "Invalid save file name"
-msgstr "Neplatný název souboru"
+msgstr "Neplatný název souboru"
#: engines/pegasus/pegasus.cpp:2507
msgid "Up/Zoom In/Move Forward/Open Doors"
-msgstr "Nahoru/Přiblížit/Pohyb dopředu/Otevřít dveře"
+msgstr "Nahoru/Pøiblí¾it/Pohyb dopøedu/Otevøít dveøe"
#: engines/pegasus/pegasus.cpp:2508
msgid "Down/Zoom Out"
-msgstr "Dolů/Oddálení"
+msgstr "Dolù/Oddálení"
#: engines/pegasus/pegasus.cpp:2511
msgid "Display/Hide Inventory Tray"
-msgstr "Zobrazit/Skrýt podnos inventáře"
+msgstr "Zobrazit/Skrýt podnos inventáøe"
#: engines/pegasus/pegasus.cpp:2512
msgid "Display/Hide Biochip Tray"
-msgstr "Zobrazit/Skrýt podnos bioÄipu"
+msgstr "Zobrazit/Skrýt podnos bioèipu"
#: engines/pegasus/pegasus.cpp:2513
msgid "Action/Select"
-msgstr "ÄŒinnost/Vybrat"
+msgstr "Èinnost/Vybrat"
#: engines/pegasus/pegasus.cpp:2514
msgid "Toggle Center Data Display"
-msgstr "Přepnout centrální datovou obrazovku"
+msgstr "Pøepnout centrální datovou obrazovku"
#: engines/pegasus/pegasus.cpp:2515
msgid "Display/Hide Info Screen"
-msgstr "Zobrazit/Skrýto obrazovku informací"
+msgstr "Zobrazit/Skrýto obrazovku informací"
#: engines/pegasus/pegasus.cpp:2516
msgid "Display/Hide Pause Menu"
-msgstr "Zobrazit/Skrýt "
+msgstr "Zobrazit/Skrýt "
#: engines/queen/detection.cpp:56
msgid "Alternative intro"
-msgstr "Alternativní úvod"
+msgstr "Alternativní úvod"
#: engines/queen/detection.cpp:57
msgid "Use an alternative game intro (CD version only)"
-msgstr "Použít jinou verzi úvodu (Pouze verze CD)"
+msgstr "Pou¾ít jinou verzi úvodu (Pouze verze CD)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr "PÅ™ekoÄit průchod rozkladu barev EGA (pozadí v plných barvách)"
+msgstr "Pøekoèit prùchod rozkladu barev EGA (pozadí v plných barvách)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
-"PÅ™eskoÄit průchod rozkladu barev EGA, obraze je zobrazen v plných barvách"
+"Pøeskoèit prùchod rozkladu barev EGA, obraze je zobrazen v plných barvách"
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "Povolit sloupcový indikátor zdraví"
+msgstr "Povolit grafiku ve vysokém rozli¹ení"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "Povolit sloupcový indikátor zdraví"
+msgstr "Povolit grafiku/obsah ve vysokém rozli¹ení"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
-msgstr "Upřednostňovat digitální zvukové efekty"
+msgstr "Upøednostòovat digitální zvukové efekty"
#: engines/sci/detection.cpp:395
msgid "Prefer digital sound effects instead of synthesized ones"
-msgstr "Upřednostňovat digitální zvukové efekty před syntetizovanými"
+msgstr "Upøednostòovat digitální zvukové efekty pøed syntetizovanými"
#: engines/sci/detection.cpp:414
msgid "Use IMF/Yamaha FB-01 for MIDI output"
-msgstr "Použít IMF/Yamaha FB-01 pro výstup MIDI"
+msgstr "Pou¾ít IMF/Yamaha FB-01 pro výstup MIDI"
#: engines/sci/detection.cpp:415
msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
-"Použít kartu IBM Music Feature nebo modul syntetizátoru Yamaha FB-01 FM "
-"pro výstup MIDI"
+"Pou¾ít kartu IBM Music Feature nebo modul syntetizátoru Yamaha FB-01 FM pro "
+"výstup MIDI"
#: engines/sci/detection.cpp:425
msgid "Use CD audio"
-msgstr "Použít zvuky na CD"
+msgstr "Pou¾ít zvuky na CD"
#: engines/sci/detection.cpp:426
msgid "Use CD audio instead of in-game audio, if available"
-msgstr "Použít zvuky na CD místo ve hře, pokud je dostupné"
+msgstr "Pou¾ít zvuky na CD místo ve høe, pokud je dostupné"
#: engines/sci/detection.cpp:436
msgid "Use Windows cursors"
-msgstr "Použít kurzory Windows"
+msgstr "Pou¾ít kurzory Windows"
#: engines/sci/detection.cpp:437
msgid ""
"Use the Windows cursors (smaller and monochrome) instead of the DOS ones"
-msgstr "Použít kurzory Windows (menší a Äernobílé) místo kurzorů z DOS"
+msgstr "Pou¾ít kurzory Windows (men¹í a èernobílé) místo kurzorù z DOS"
#: engines/sci/detection.cpp:447
msgid "Use silver cursors"
-msgstr "Použít stříbrné kurzory"
+msgstr "Pou¾ít støíbrné kurzory"
#: engines/sci/detection.cpp:448
msgid ""
"Use the alternate set of silver cursors, instead of the normal golden ones"
-msgstr ""
-"Použít alternativní sadu stříbrných kurzorů místo standardních zlatých"
+msgstr "Pou¾ít alternativní sadu støíbrných kurzorù místo standardních zlatých"
#: engines/scumm/dialogs.cpp:176
#, c-format
msgid "Insert Disk %c and Press Button to Continue."
-msgstr "Vložte Disk %c a StisknÄ›te TlaÄítko Pro PokraÄování."
+msgstr "Vlo¾te Disk %c a Stisknìte Tlaèítko Pro Pokraèování."
#: engines/scumm/dialogs.cpp:177
#, c-format
msgid "Unable to Find %s, (%c%d) Press Button."
-msgstr "Nelze Najít %s, (%c%d) StisknÄ›te TlaÄítko."
+msgstr "Nelze Najít %s, (%c%d) Stisknìte Tlaèítko."
#: engines/scumm/dialogs.cpp:178
#, c-format
msgid "Error reading disk %c, (%c%d) Press Button."
-msgstr "Chyba pÅ™i Ätení disku %c, (%c%d) StisknÄ›te TlaÄítko."
+msgstr "Chyba pøi ètení disku %c, (%c%d) Stisknìte Tlaèítko."
#: engines/scumm/dialogs.cpp:179
msgid "Game Paused. Press SPACE to Continue."
-msgstr "Hra Pozastavena. StisknÄ›te MEZERNÃK pro pokraÄování."
+msgstr "Hra Pozastavena. Stisknìte MEZERNÍK pro pokraèování."
#. 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'
#: engines/scumm/dialogs.cpp:183
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Jste si jisti, že chcete restartovat? (A/N)A"
+msgstr "Jste si jisti, ¾e chcete restartovat? (A/N)A"
#. 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)Y"
-msgstr "Jste si jisti, že chcete odejít? (A/N)A"
+msgstr "Jste si jisti, ¾e chcete odejít? (A/N)A"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
-msgstr "Hrát"
+msgstr "Hrát"
#: engines/scumm/dialogs.cpp:194
msgid "Insert save/load game disk"
-msgstr "Vložte herní disk pro uložení/naÄtení"
+msgstr "Vlo¾te herní disk pro ulo¾ení/naètení"
#: engines/scumm/dialogs.cpp:195
msgid "You must enter a name"
-msgstr "Musíte zadat jméno"
+msgstr "Musíte zadat jméno"
#: engines/scumm/dialogs.cpp:196
msgid "The game was NOT saved (disk full?)"
-msgstr "Hra NEBYLA uložena (plný disk?)"
+msgstr "Hra NEBYLA ulo¾ena (plný disk?)"
#: engines/scumm/dialogs.cpp:197
msgid "The game was NOT loaded"
-msgstr "Hra NEBYLA naÄtena"
+msgstr "Hra NEBYLA naètena"
#: engines/scumm/dialogs.cpp:198
#, c-format
msgid "Saving '%s'"
-msgstr "Ukládám '%s'"
+msgstr "Ukládám '%s'"
#: engines/scumm/dialogs.cpp:199
#, c-format
msgid "Loading '%s'"
-msgstr "NaÄítám '%s'"
+msgstr "Naèítám '%s'"
#: engines/scumm/dialogs.cpp:200
msgid "Name your SAVE game"
-msgstr "Pojmenujte svoji ULOŽENOU hru"
+msgstr "Pojmenujte svoji ULO®ENOU hru"
#: engines/scumm/dialogs.cpp:201
msgid "Select a game to LOAD"
-msgstr "Vyberte hru k NAÄŒTENÃ"
+msgstr "Vyberte hru k NAÈTENÍ"
#: engines/scumm/dialogs.cpp:202
msgid "Game title)"
-msgstr "Název hry"
+msgstr "Název hry"
#. I18N: Previous page button
#: engines/scumm/dialogs.cpp:288
msgid "~P~revious"
-msgstr "~P~ředchozí"
+msgstr "~P~øedchozí"
#. I18N: Next page button
#: engines/scumm/dialogs.cpp:290
msgid "~N~ext"
-msgstr "~D~alší"
+msgstr "~D~al¹í"
#: engines/scumm/dialogs.cpp:602
msgid "Speech Only"
-msgstr "Pouze ŘeÄ"
+msgstr "Pouze Øeè"
#: engines/scumm/dialogs.cpp:603
msgid "Speech and Subtitles"
-msgstr "ŘeÄ a Titulky"
+msgstr "Øeè a Titulky"
#: engines/scumm/dialogs.cpp:604
msgid "Subtitles Only"
@@ -2919,47 +2936,47 @@ msgstr "Pouze Titulky"
#: engines/scumm/dialogs.cpp:612
msgctxt "lowres"
msgid "Speech & Subs"
-msgstr "ŘeÄ a Titulky"
+msgstr "Øeè a Titulky"
#: engines/scumm/dialogs.cpp:658
msgid "Select a Proficiency Level."
-msgstr "Vyberte úroveň odbornosti."
+msgstr "Vyberte úroveò odbornosti."
#: engines/scumm/dialogs.cpp:660
msgid "Refer to your Loom(TM) manual for help."
-msgstr "Pro nápovÄ›du si pÅ™eÄtÄ›te manuál Loom(TM)."
+msgstr "Pro nápovìdu si pøeètìte manuál Loom(TM)."
#: engines/scumm/dialogs.cpp:664
msgid "Practice"
-msgstr "CviÄení"
+msgstr "Cvièení"
#: engines/scumm/dialogs.cpp:665
msgid "Expert"
-msgstr "PokroÄilý"
+msgstr "Pokroèilý"
#: engines/scumm/help.cpp:74
msgid "Common keyboard commands:"
-msgstr "Běžné klávesové příkazy"
+msgstr "Bì¾né klávesové pøíkazy"
#: engines/scumm/help.cpp:75
msgid "Save / Load dialog"
-msgstr "Dialog Nahrát / Uložit"
+msgstr "Dialog Nahrát / Ulo¾it"
#: engines/scumm/help.cpp:77
msgid "Skip line of text"
-msgstr "PÅ™eskoÄit řádek textu"
+msgstr "Pøeskoèit øádek textu"
#: engines/scumm/help.cpp:78
msgid "Esc"
-msgstr "Mezerník"
+msgstr "Mezerník"
#: engines/scumm/help.cpp:78
msgid "Skip cutscene"
-msgstr "PÅ™eskoÄit video"
+msgstr "Pøeskoèit video"
#: engines/scumm/help.cpp:79
msgid "Space"
-msgstr "Mezerník"
+msgstr "Mezerník"
#: engines/scumm/help.cpp:79
msgid "Pause game"
@@ -2975,7 +2992,7 @@ msgstr "Ctrl"
#: engines/scumm/help.cpp:80
msgid "Load game state 1-10"
-msgstr "Nahrát stav hry 1-10"
+msgstr "Nahrát stav hry 1-10"
#: engines/scumm/help.cpp:81 engines/scumm/help.cpp:85
#: engines/scumm/help.cpp:87 engines/scumm/help.cpp:101
@@ -2985,7 +3002,7 @@ msgstr "Alt"
#: engines/scumm/help.cpp:81
msgid "Save game state 1-10"
-msgstr "Uložit stav hry 1-10"
+msgstr "Ulo¾it stav hry 1-10"
#: engines/scumm/help.cpp:87 engines/scumm/help.cpp:90
msgid "Enter"
@@ -2993,15 +3010,15 @@ msgstr "Enter"
#: engines/scumm/help.cpp:88
msgid "Music volume up / down"
-msgstr "Hlasitost hudby nahoru / dolů"
+msgstr "Hlasitost hudby nahoru / dolù"
#: engines/scumm/help.cpp:89
msgid "Text speed slower / faster"
-msgstr "Zvýšit / Snížit rychlost textu"
+msgstr "Zvý¹it / Sní¾it rychlost textu"
#: engines/scumm/help.cpp:90
msgid "Simulate left mouse button"
-msgstr "Napodobit levé tlaÄítko myÅ¡i"
+msgstr "Napodobit levé tlaèítko my¹i"
#: engines/scumm/help.cpp:91
msgid "Tab"
@@ -3009,116 +3026,116 @@ msgstr "Tab"
#: engines/scumm/help.cpp:91
msgid "Simulate right mouse button"
-msgstr "Napodobit pravé tlaÄítko myÅ¡i"
+msgstr "Napodobit pravé tlaèítko my¹i"
#: engines/scumm/help.cpp:94
msgid "Special keyboard commands:"
-msgstr "Speciální klávesové příkazy"
+msgstr "Speciální klávesové pøíkazy"
#: engines/scumm/help.cpp:95
msgid "Show / Hide console"
-msgstr "Ukázat / Skrýt konzoli"
+msgstr "Ukázat / Skrýt konzoli"
#: engines/scumm/help.cpp:96
msgid "Start the debugger"
-msgstr "Spustit ladící program"
+msgstr "Spustit ladící program"
#: engines/scumm/help.cpp:97
msgid "Show memory consumption"
-msgstr "Zobrazit spotřebu paměti"
+msgstr "Zobrazit spotøebu pamìti"
#: engines/scumm/help.cpp:98
msgid "Run in fast mode (*)"
-msgstr "Spustit v rychlém režimu (*)"
+msgstr "Spustit v rychlém re¾imu (*)"
#: engines/scumm/help.cpp:99
msgid "Run in really fast mode (*)"
-msgstr "Spustit ve velmi rychlém režimu (*)"
+msgstr "Spustit ve velmi rychlém re¾imu (*)"
#: engines/scumm/help.cpp:100
msgid "Toggle mouse capture"
-msgstr "Povolit zachycování myši"
+msgstr "Povolit zachycování my¹i"
#: engines/scumm/help.cpp:101
msgid "Switch between graphics filters"
-msgstr "Přepínat mezi grafickými filtry"
+msgstr "Pøepínat mezi grafickými filtry"
#: engines/scumm/help.cpp:102
msgid "Increase / Decrease scale factor"
-msgstr "Zvětšit / Zmenšit faktor změny velikosti"
+msgstr "Zvìt¹it / Zmen¹it faktor zmìny velikosti"
#: engines/scumm/help.cpp:103
msgid "Toggle aspect-ratio correction"
-msgstr "Povolit korekci poměru stran"
+msgstr "Povolit korekci pomìru stran"
#: engines/scumm/help.cpp:108
msgid "* Note that using ctrl-f and"
-msgstr "Upozorňujeme, že používání ctrl-f a"
+msgstr "Upozoròujeme, ¾e pou¾ívání ctrl-f a"
#: engines/scumm/help.cpp:109
msgid " ctrl-g are not recommended"
-msgstr " ctrl-g není doporuÄeno"
+msgstr " ctrl-g není doporuèeno"
#: engines/scumm/help.cpp:110
msgid " since they may cause crashes"
-msgstr "jelikož můžou způsobit pád"
+msgstr "jeliko¾ mù¾ou zpùsobit pád"
#: engines/scumm/help.cpp:111
msgid " or incorrect game behavior."
-msgstr " nebo nesprávné chování hry."
+msgstr " nebo nesprávné chování hry."
#: engines/scumm/help.cpp:115
msgid "Spinning drafts on the keyboard:"
-msgstr "Pletení náÄrtků na klávesnici:"
+msgstr "Pletení náèrtkù na klávesnici:"
#: engines/scumm/help.cpp:117
msgid "Main game controls:"
-msgstr "Hlavní ovládací prvky:"
+msgstr "Hlavní ovládací prvky:"
#: engines/scumm/help.cpp:122 engines/scumm/help.cpp:137
#: engines/scumm/help.cpp:162
msgid "Push"
-msgstr "TlaÄit"
+msgstr "Tlaèit"
#: engines/scumm/help.cpp:123 engines/scumm/help.cpp:138
#: engines/scumm/help.cpp:163
msgid "Pull"
-msgstr "Táhnout"
+msgstr "Táhnout"
#: engines/scumm/help.cpp:124 engines/scumm/help.cpp:139
#: engines/scumm/help.cpp:164 engines/scumm/help.cpp:198
#: engines/scumm/help.cpp:208
msgid "Give"
-msgstr "Dát"
+msgstr "Dát"
#: engines/scumm/help.cpp:125 engines/scumm/help.cpp:140
#: engines/scumm/help.cpp:165 engines/scumm/help.cpp:191
#: engines/scumm/help.cpp:209
msgid "Open"
-msgstr "Otevřít"
+msgstr "Otevøít"
#: engines/scumm/help.cpp:127
msgid "Go to"
-msgstr "Jít do"
+msgstr "Jít do"
#: engines/scumm/help.cpp:128
msgid "Get"
-msgstr "Vzít"
+msgstr "Vzít"
#: engines/scumm/help.cpp:129 engines/scumm/help.cpp:153
#: engines/scumm/help.cpp:171 engines/scumm/help.cpp:199
#: engines/scumm/help.cpp:214 engines/scumm/help.cpp:225
#: engines/scumm/help.cpp:251
msgid "Use"
-msgstr "Použít"
+msgstr "Pou¾ít"
#: engines/scumm/help.cpp:130 engines/scumm/help.cpp:142
msgid "Read"
-msgstr "PÅ™eÄíst"
+msgstr "Pøeèíst"
#: engines/scumm/help.cpp:131 engines/scumm/help.cpp:148
msgid "New kid"
-msgstr "Nové dítě"
+msgstr "Nové dítì"
#: engines/scumm/help.cpp:132 engines/scumm/help.cpp:154
#: engines/scumm/help.cpp:172
@@ -3133,7 +3150,7 @@ msgstr "Vypnout"
#: engines/scumm/help.cpp:143 engines/scumm/help.cpp:168
#: engines/scumm/help.cpp:195
msgid "Walk to"
-msgstr "Přejít na"
+msgstr "Pøejít na"
#: engines/scumm/help.cpp:144 engines/scumm/help.cpp:169
#: engines/scumm/help.cpp:196 engines/scumm/help.cpp:211
@@ -3151,11 +3168,11 @@ msgstr "Odemknout"
#: engines/scumm/help.cpp:150
msgid "Put on"
-msgstr "Obléct"
+msgstr "Obléct"
#: engines/scumm/help.cpp:151
msgid "Take off"
-msgstr "Svléct"
+msgstr "Svléct"
#: engines/scumm/help.cpp:157
msgid "Fix"
@@ -3163,11 +3180,11 @@ msgstr "Spravit"
#: engines/scumm/help.cpp:159
msgid "Switch"
-msgstr "Přepnout"
+msgstr "Pøepnout"
#: engines/scumm/help.cpp:167 engines/scumm/help.cpp:229
msgid "Look"
-msgstr "Dívat se"
+msgstr "Dívat se"
#: engines/scumm/help.cpp:174 engines/scumm/help.cpp:224
msgid "Talk"
@@ -3184,43 +3201,43 @@ msgstr "Henrymu / Indymu"
#. I18N: These are different musical notes
#: engines/scumm/help.cpp:180
msgid "play C minor on distaff"
-msgstr "zahrát c moll na přeslici"
+msgstr "zahrát c moll na pøeslici"
#: engines/scumm/help.cpp:181
msgid "play D on distaff"
-msgstr "zahrát D na přeslici"
+msgstr "zahrát D na pøeslici"
#: engines/scumm/help.cpp:182
msgid "play E on distaff"
-msgstr "zahrát E na přeslici"
+msgstr "zahrát E na pøeslici"
#: engines/scumm/help.cpp:183
msgid "play F on distaff"
-msgstr "zahrát F na přeslici"
+msgstr "zahrát F na pøeslici"
#: engines/scumm/help.cpp:184
msgid "play G on distaff"
-msgstr "zahrát G na přeslici"
+msgstr "zahrát G na pøeslici"
#: engines/scumm/help.cpp:185
msgid "play A on distaff"
-msgstr "zahrát A na přeslici"
+msgstr "zahrát A na pøeslici"
#: engines/scumm/help.cpp:186
msgid "play B on distaff"
-msgstr "zahrát B na přeslici"
+msgstr "zahrát B na pøeslici"
#: engines/scumm/help.cpp:187
msgid "play C major on distaff"
-msgstr "zahrát C dur na přeslici"
+msgstr "zahrát C dur na pøeslici"
#: engines/scumm/help.cpp:193 engines/scumm/help.cpp:215
msgid "puSh"
-msgstr "tlaÄIt"
+msgstr "tlaèIt"
#: engines/scumm/help.cpp:194 engines/scumm/help.cpp:216
msgid "pull (Yank)"
-msgstr "táhnout (Škubnout)"
+msgstr "táhnout (©kubnout)"
#: engines/scumm/help.cpp:197 engines/scumm/help.cpp:213
#: engines/scumm/help.cpp:249
@@ -3229,7 +3246,7 @@ msgstr "Mluvit s"
#: engines/scumm/help.cpp:200 engines/scumm/help.cpp:212
msgid "Look at"
-msgstr "Dívat se na"
+msgstr "Dívat se na"
#: engines/scumm/help.cpp:201
msgid "turn oN"
@@ -3241,28 +3258,28 @@ msgstr "vypnoUt"
#: engines/scumm/help.cpp:218
msgid "KeyUp"
-msgstr "KlávesaNahoru"
+msgstr "KlávesaNahoru"
#: engines/scumm/help.cpp:218
msgid "Highlight prev dialogue"
-msgstr "Zvýraznit předchozí dialog"
+msgstr "Zvýraznit pøedchozí dialog"
#: engines/scumm/help.cpp:219
msgid "KeyDown"
-msgstr "KlávesaDolů"
+msgstr "KlávesaDolù"
#: engines/scumm/help.cpp:219
msgid "Highlight next dialogue"
-msgstr "Zvýraznit následující dialog"
+msgstr "Zvýraznit následující dialog"
#: engines/scumm/help.cpp:223
msgid "Walk"
-msgstr "Jít"
+msgstr "Jít"
#: engines/scumm/help.cpp:226 engines/scumm/help.cpp:235
#: engines/scumm/help.cpp:242 engines/scumm/help.cpp:250
msgid "Inventory"
-msgstr "Inventář"
+msgstr "Inventáø"
#: engines/scumm/help.cpp:227
msgid "Object"
@@ -3270,11 +3287,11 @@ msgstr "Objekt"
#: engines/scumm/help.cpp:230
msgid "Black and White / Color"
-msgstr "Černobílé / Barva"
+msgstr "Èernobílé / Barva"
#: engines/scumm/help.cpp:233
msgid "Eyes"
-msgstr "OÄi"
+msgstr "Oèi"
#: engines/scumm/help.cpp:234
msgid "Tongue"
@@ -3282,7 +3299,7 @@ msgstr "Jazyk"
#: engines/scumm/help.cpp:236
msgid "Punch"
-msgstr "Udeřit"
+msgstr "Udeøit"
#: engines/scumm/help.cpp:237
msgid "Kick"
@@ -3290,11 +3307,11 @@ msgstr "Kopnout"
#: engines/scumm/help.cpp:240 engines/scumm/help.cpp:248
msgid "Examine"
-msgstr "Prohlédnout"
+msgstr "Prohlédnout"
#: engines/scumm/help.cpp:241
msgid "Regular cursor"
-msgstr "ObyÄejný kurzor"
+msgstr "Obyèejný kurzor"
#. I18N: Comm is a communication device
#: engines/scumm/help.cpp:244
@@ -3303,15 +3320,15 @@ msgstr "Komunikace"
#: engines/scumm/help.cpp:247
msgid "Save / Load / Options"
-msgstr "Uložit / Nahrát / Volby"
+msgstr "Ulo¾it / Nahrát / Volby"
#: engines/scumm/help.cpp:256
msgid "Other game controls:"
-msgstr "Další ovládací prvky hry"
+msgstr "Dal¹í ovládací prvky hry"
#: engines/scumm/help.cpp:258 engines/scumm/help.cpp:268
msgid "Inventory:"
-msgstr "Inventář:"
+msgstr "Inventáø:"
#: engines/scumm/help.cpp:259 engines/scumm/help.cpp:275
msgid "Scroll list up"
@@ -3323,63 +3340,63 @@ msgstr "Posunout seznam dolu"
#: engines/scumm/help.cpp:261 engines/scumm/help.cpp:269
msgid "Upper left item"
-msgstr "Položka vlevo nahoře"
+msgstr "Polo¾ka vlevo nahoøe"
#: engines/scumm/help.cpp:262 engines/scumm/help.cpp:271
msgid "Lower left item"
-msgstr "Položka vlevo dole"
+msgstr "Polo¾ka vlevo dole"
#: engines/scumm/help.cpp:263 engines/scumm/help.cpp:272
msgid "Upper right item"
-msgstr "Položka vpravo nahoře"
+msgstr "Polo¾ka vpravo nahoøe"
#: engines/scumm/help.cpp:264 engines/scumm/help.cpp:274
msgid "Lower right item"
-msgstr "Položka vpravo dole"
+msgstr "Polo¾ka vpravo dole"
#: engines/scumm/help.cpp:270
msgid "Middle left item"
-msgstr "Položka vlevo uprostřed"
+msgstr "Polo¾ka vlevo uprostøed"
#: engines/scumm/help.cpp:273
msgid "Middle right item"
-msgstr "Položka vpravo uprostřed"
+msgstr "Polo¾ka vpravo uprostøed"
#: engines/scumm/help.cpp:280 engines/scumm/help.cpp:285
msgid "Switching characters:"
-msgstr "Měnění postav:"
+msgstr "Mìnìní postav:"
#: engines/scumm/help.cpp:282
msgid "Second kid"
-msgstr "Druhé dítě"
+msgstr "Druhé dítì"
#: engines/scumm/help.cpp:283
msgid "Third kid"
-msgstr "Třetí dítě"
+msgstr "Tøetí dítì"
#: engines/scumm/help.cpp:292
msgid "Toggle Inventory/IQ Points display"
-msgstr "Přepínat zobrazení inventáře/chytrostních bodů"
+msgstr "Pøepínat zobrazení inventáøe/chytrostních bodù"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr "Přepínat bojování pomocí kláves/myši (*)"
+msgstr "Pøepínat bojování pomocí kláves/my¹i (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr "* Bojování pomocí klávesnice je vždy zapnuto,"
+msgstr "* Bojování pomocí klávesnice je v¾dy zapnuto,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr " takže nehledě a to, co říká hra,"
+msgstr " tak¾e nehledì a to, co øíká hra,"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr " toto ve skuteÄnosti ovládá bojování s myší"
+msgstr " toto ve skuteènosti ovládá bojování s my¹í"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
-msgstr "Ovládání boje (num. kláv.)"
+msgstr "Ovládání boje (num. kláv.)"
#: engines/scumm/help.cpp:305 engines/scumm/help.cpp:306
#: engines/scumm/help.cpp:307
@@ -3388,31 +3405,31 @@ msgstr "Ustoupit"
#: engines/scumm/help.cpp:308
msgid "Block high"
-msgstr "Bránit nahoře"
+msgstr "Bránit nahoøe"
#: engines/scumm/help.cpp:309
msgid "Block middle"
-msgstr "Bránit uprostřed"
+msgstr "Bránit uprostøed"
#: engines/scumm/help.cpp:310
msgid "Block low"
-msgstr "Bránit dole"
+msgstr "Bránit dole"
#: engines/scumm/help.cpp:311
msgid "Punch high"
-msgstr "Udeřit nahoru"
+msgstr "Udeøit nahoru"
#: engines/scumm/help.cpp:312
msgid "Punch middle"
-msgstr "Udeřit doprostřed"
+msgstr "Udeøit doprostøed"
#: engines/scumm/help.cpp:313
msgid "Punch low"
-msgstr "Udeřit dolů"
+msgstr "Udeøit dolù"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr "NeÄekaná rána"
+msgstr "Neèekaná rána"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3420,63 +3437,63 @@ msgstr "Tyto jsou pro Indyho nalevo."
#: engines/scumm/help.cpp:319
msgid "When Indy is on the right,"
-msgstr "Když je Indy napravo,"
+msgstr "Kdy¾ je Indy napravo,"
#: engines/scumm/help.cpp:320
msgid "7, 4, and 1 are switched with"
-msgstr "7, 4 a 1 jsou zaměněny s"
+msgstr "7, 4 a 1 jsou zamìnìny s"
#: engines/scumm/help.cpp:321
msgid "9, 6, and 3, respectively."
-msgstr "9, 6 a 3, v tomto pořadí."
+msgstr "9, 6 a 3, v tomto poøadí."
#: engines/scumm/help.cpp:328
msgid "Biplane controls (numpad):"
-msgstr "Kontrola dvojplošníku (numerická klávesnice)"
+msgstr "Kontrola dvojplo¹níku (numerická klávesnice)"
#: engines/scumm/help.cpp:329
msgid "Fly to upper left"
-msgstr "Letět doprava nahoru"
+msgstr "Letìt doprava nahoru"
#: engines/scumm/help.cpp:330
msgid "Fly to left"
-msgstr "Letět doleva"
+msgstr "Letìt doleva"
#: engines/scumm/help.cpp:331
msgid "Fly to lower left"
-msgstr "Letět doleva dolů"
+msgstr "Letìt doleva dolù"
#: engines/scumm/help.cpp:332
msgid "Fly upwards"
-msgstr "Letět nahoru"
+msgstr "Letìt nahoru"
#: engines/scumm/help.cpp:333
msgid "Fly straight"
-msgstr "Letět rovně"
+msgstr "Letìt rovnì"
#: engines/scumm/help.cpp:334
msgid "Fly down"
-msgstr "Letět dolů"
+msgstr "Letìt dolù"
#: engines/scumm/help.cpp:335
msgid "Fly to upper right"
-msgstr "Letět doprava nahoru"
+msgstr "Letìt doprava nahoru"
#: engines/scumm/help.cpp:336
msgid "Fly to right"
-msgstr "Letět doprava"
+msgstr "Letìt doprava"
#: engines/scumm/help.cpp:337
msgid "Fly to lower right"
-msgstr "Letět doprava dolů"
+msgstr "Letìt doprava dolù"
#: engines/scumm/input.cpp:580
msgid "Snap scroll on"
-msgstr "Přichycení při posunování zapnuto"
+msgstr "Pøichycení pøi posunování zapnuto"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr "Přichycení při posunování zapnuto"
+msgstr "Pøichycení pøi posunování zapnuto"
#: engines/scumm/input.cpp:595
msgid "Music volume: "
@@ -3484,7 +3501,7 @@ msgstr "Hlasitost hudby:"
#: engines/scumm/input.cpp:612
msgid "Subtitle speed: "
-msgstr "Rychlost titulkù:"
+msgstr "Rychlost titulkù:"
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3492,8 +3509,8 @@ msgid ""
"Native MIDI support requires the Roland Upgrade from LucasArts,\n"
"but %s is missing. Using AdLib instead."
msgstr ""
-"Přirozená podpora MIDI vyžaduje Aktualizaci Roland od LucasArts,\n"
-"ale %s chybí. Místo toho je použit AdLib."
+"Pøirozená podpora MIDI vy¾aduje Aktualizaci Roland od LucasArts,\n"
+"ale %s chybí. Místo toho je pou¾it AdLib."
#: engines/scumm/scumm.cpp:2644
msgid ""
@@ -3501,54 +3518,108 @@ msgid ""
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"NormálnÄ› by teÄ byl spuÅ¡tÄ›n Maniac Mansion. Ale aby toto mohlo fungovat, "
-"musí být soubory se hrou umístěny do složky 'Maniac' uvnitř složky se "
-"hrou Tentacle a hra musí být přidána do ScummVM."
+"Normálnì by teï byl spu¹tìn Maniac Mansion. Ale aby toto mohlo fungovat, "
+"musí být soubory se hrou umístìny do slo¾ky 'Maniac' uvnitø slo¾ky se hrou "
+"Tentacle a hra musí být pøidána do ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
-"Nelze najít spustitelný soubor 'Loom' pro Macintosh z jehož\n"
-"mají být naÄteny hudební nástroje. Hudba bude zakázána."
+"Nelze najít spustitelný soubor 'Loom' pro Macintosh z jeho¾\n"
+"mají být naèteny hudební nástroje. Hudba bude zakázána."
#: 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 ""
-"Nelze najít spustitelný soubor 'Monkey Island' pro Macintosh z\n"
-"jehož mají být naÄteny hudební nástroje. Hudba bude zakázána."
+"Nelze najít spustitelný soubor 'Monkey Island' pro Macintosh z\n"
+"jeho¾ mají být naèteny hudební nástroje. Hudba bude zakázána."
+
+#: engines/sherlock/detection.cpp:71
+#, fuzzy
+msgid "Use original savegame dialog"
+msgstr "Pou¾ít pùvodní obrazovky naètení/ulo¾ení"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+#, fuzzy
+msgid "Show character portraits"
+msgstr "Zamìnit znaky"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
"Please download it from www.scummvm.org"
msgstr ""
-"Nelze nalézt soubor \"sky.cpt\"!\n"
-"Stáhněte si ho, prosím z www.scummvm.org"
+"Nelze nalézt soubor \"sky.cpt\"!\n"
+"Stáhnìte si ho, prosím z www.scummvm.org"
#: engines/sky/compact.cpp:141
msgid ""
"The \"sky.cpt\" file has an incorrect size.\n"
"Please (re)download it from www.scummvm.org"
msgstr ""
-"Soubor \"sky.cpt\" má nesprávnou velikost.\n"
-"Stáhněte si ho, prosím, (znovu) z www.scummvm.org"
+"Soubor \"sky.cpt\" má nesprávnou velikost.\n"
+"Stáhnìte si ho, prosím, (znovu) z www.scummvm.org"
#: engines/sky/detection.cpp:44
msgid "Floppy intro"
-msgstr "Úvod z diskety"
+msgstr "Úvod z diskety"
#: engines/sky/detection.cpp:45
msgid "Use the floppy version's intro (CD version only)"
-msgstr "Použít verzi úvodu z diskety (Pouze verze CD)"
+msgstr "Pou¾ít verzi úvodu z diskety (Pouze verze CD)"
#: engines/sword1/animation.cpp:524
#, c-format
msgid "PSX stream cutscene '%s' cannot be played in paletted mode"
-msgstr "Proud videa PSX '%s' nemůže být přehrán v režimu palety"
+msgstr "Proud videa PSX '%s' nemù¾e být pøehrán v re¾imu palety"
#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
msgid "DXA cutscenes found but ScummVM has been built without zlib"
@@ -3574,13 +3645,13 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
-"ScummVM zjistil, že máte staré uložené pozice pro Broken Sword 1, "
-"které by měly být převedeny.\n"
-"Starý formát uložených her již není podporován, takže pokud je "
-"nepÅ™evedete, nebudete moci vaÅ¡e hry naÄíst.\n"
+"ScummVM zjistil, ¾e máte staré ulo¾ené pozice pro Broken Sword 1, které by "
+"mìly být pøevedeny.\n"
+"Starý formát ulo¾ených her ji¾ není podporován, tak¾e pokud je nepøevedete, "
+"nebudete moci va¹e hry naèíst.\n"
"\n"
-"StisknÄ›te OK, abyste je pÅ™evedli teÄ, jinak budete požádáni znovu, pÅ™i "
-"spuštění této hry.\n"
+"Stisknìte OK, abyste je pøevedli teï, jinak budete po¾ádáni znovu, pøi "
+"spu¹tìní této hry.\n"
#: engines/sword1/control.cpp:1232
#, c-format
@@ -3588,8 +3659,8 @@ msgid ""
"Target new save game already exists!\n"
"Would you like to keep the old save game (%s) or the new one (%s)?\n"
msgstr ""
-"Nová cílová uložená hra již existuje!\n"
-"Chtěli byste ponechat starou uloženou hru (%s), nebo novou (%s)?\n"
+"Nová cílová ulo¾ená hra ji¾ existuje!\n"
+"Chtìli byste ponechat starou ulo¾enou hru (%s), nebo novou (%s)?\n"
#: engines/sword1/control.cpp:1235
msgid "Keep the old one"
@@ -3610,45 +3681,44 @@ msgstr "Videa PSX nalezena, ale ScummVM byl sestaven bez podpory barev RGB"
#: engines/sword2/sword2.cpp:79
msgid "Show object labels"
-msgstr "Zobrazit jmenovky objektů"
+msgstr "Zobrazit jmenovky objektù"
#: engines/sword2/sword2.cpp:80
msgid "Show labels for objects on mouse hover"
-msgstr "Zobrazit jmenovky objektů při najetí myši"
+msgstr "Zobrazit jmenovky objektù pøi najetí my¹i"
#: engines/teenagent/resources.cpp:95
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
-msgstr ""
-"Chybí vám soubor 'teenagent.dat'. Můžete ho získat ze stránky ScummVM."
+msgstr "Chybí vám soubor 'teenagent.dat'. Mù¾ete ho získat ze stránky ScummVM."
#: engines/teenagent/resources.cpp:116
msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
-"Soubor teenagent.dat je komprimován a zlib není souÄástí spustitelného "
-"souboru. Prosím dekomprimujte ho"
+"Soubor teenagent.dat je komprimován a zlib není souèástí spustitelného "
+"souboru. Prosím dekomprimujte ho"
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr "Zobrazit poÄítadlo FPS"
+msgstr "Zobrazit poèítadlo FPS"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
-msgstr "Zobrazit souÄasný poÄet snímků za sekundu v horním levém rohu"
+msgstr "Zobrazit souèasný poèet snímkù za sekundu v horním levém rohu"
#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Použít původní obrazovky naÄtení/uložení místo rozhraní ScummVM"
+msgstr "Pou¾ít pùvodní obrazovky naètení/ulo¾ení místo rozhraní ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr "Dvojité snímky za sekundu"
+msgstr "Dvojité snímky za sekundu"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr "Zvýšit snímkovou frekvenci z 30 na 60"
+msgstr "Zvý¹it snímkovou frekvenci z 30 na 60"
#: engines/zvision/detection_tables.h:71
msgid "Enable Venus"
@@ -3656,118 +3726,117 @@ msgstr "Povolit Venus"
#: engines/zvision/detection_tables.h:72
msgid "Enable the Venus help system"
-msgstr "Povolit systém nápovědy Venus"
+msgstr "Povolit systém nápovìdy Venus"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr "Zakázat animaci pÅ™i otáÄení"
+msgstr "Zakázat animaci pøi otáèení"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr "Zakázat animaci pÅ™i otáÄení v panoramatickém režimu"
+msgstr "Zakázat animaci pøi otáèení v panoramatickém re¾imu"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr "Použít video MPEG ve vysokém rozlišení"
+msgstr "Pou¾ít video MPEG ve vysokém rozli¹ení"
#: engines/zvision/detection_tables.h:92
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
msgstr ""
-"Použít video MPEG pocházející z DVD verze, namísto videa AVI v nízkém "
-"rozlišení."
+"Pou¾ít video MPEG pocházející z DVD verze, namísto videa AVI v nízkém "
+"rozli¹ení."
#~ msgid "EGA undithering"
-#~ msgstr "Nerozkládání EGA"
+#~ msgstr "Nerozkládání EGA"
#~ msgid "Enable undithering in EGA games"
-#~ msgstr "Povolit nerozkládání v EGA hrách"
+#~ msgstr "Povolit nerozkládání v EGA hrách"
#~ msgid "Are you sure you want to restart? (Y/N)"
-#~ msgstr "Jste si jisti, že chcete restartovat? (A/N)A"
+#~ msgstr "Jste si jisti, ¾e chcete restartovat? (A/N)A"
#~ msgid "Are you sure you want to quit? (Y/N)"
-#~ msgstr "Jste si jisti, že chcete odejít? (A/N)A"
+#~ msgstr "Jste si jisti, ¾e chcete odejít? (A/N)A"
#~ msgid ""
#~ "Usually, Maniac Mansion would start now. But ScummVM doesn't do that yet. "
#~ "To play it, go to 'Add Game' in the ScummVM start menu and select the "
#~ "'Maniac' directory inside the Tentacle game directory."
#~ msgstr ""
-#~ "NormálnÄ› by teÄ Maniac Mansion byl spuÅ¡tÄ›n. Ale ScummVM toto zatím "
-#~ "nedÄ›lá. Abyste toto mohli hrát, pÅ™ejdÄ›te do 'PÅ™idat Hru' v poÄáteÄním "
-#~ "menu ScummVM a vyberte adresář 'Maniac' uvnitř herního adresáře "
-#~ "Tentacle."
+#~ "Normálnì by teï Maniac Mansion byl spu¹tìn. Ale ScummVM toto zatím "
+#~ "nedìlá. Abyste toto mohli hrát, pøejdìte do 'Pøidat Hru' v poèáteèním "
+#~ "menu ScummVM a vyberte adresáø 'Maniac' uvnitø herního adresáøe Tentacle."
#~ msgid "MPEG-2 cutscenes found but ScummVM has been built without MPEG-2"
#~ msgstr "Videa MPEG-2 nalezena, ale ScummVM byl sestaven bez MPEG-2"
#~ msgctxt "lowres"
#~ msgid "Mass Add..."
-#~ msgstr "Hromadné Přidání..."
+#~ msgstr "Hromadné Pøidání..."
#~ msgid ""
#~ "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
#~ msgstr ""
-#~ "Vypne mapování General MIDI pro hry s Roland MT-32 zvukovým doprovodem"
+#~ "Vypne mapování General MIDI pro hry s Roland MT-32 zvukovým doprovodem"
#~ msgid "Standard (16bpp)"
-#~ msgstr "Standardní (16bpp)"
+#~ msgstr "Standardní (16bpp)"
#~ msgid "MPEG2 cutscenes are no longer supported"
-#~ msgstr "Videa MPGE2 již nejsou podporována"
+#~ msgstr "Videa MPGE2 ji¾ nejsou podporována"
#~ msgid "OpenGL Normal"
-#~ msgstr "OpenGL Normální"
+#~ msgstr "OpenGL Normální"
#~ msgid "OpenGL Conserve"
-#~ msgstr "OpenGL Zachovávající"
+#~ msgstr "OpenGL Zachovávající"
#~ msgid "OpenGL Original"
-#~ msgstr "OpenGL Původní"
+#~ msgstr "OpenGL Pùvodní"
#~ msgid "Current display mode"
-#~ msgstr "SouÄasný režim obrazu"
+#~ msgstr "Souèasný re¾im obrazu"
#~ msgid "Current scale"
-#~ msgstr "SouÄasná velikost"
+#~ msgstr "Souèasná velikost"
#~ msgid "Active filter mode: Linear"
-#~ msgstr "Aktivní režim filtru: Lineární"
+#~ msgstr "Aktivní re¾im filtru: Lineární"
#~ msgid "Active filter mode: Nearest"
-#~ msgstr "Aktivní režim filtru: Nejbližší"
+#~ msgstr "Aktivní re¾im filtru: Nejbli¾¹í"
#~ msgid "Enable Roland GS Mode"
-#~ msgstr "Zapnout režim Roland GS"
-
-#~ msgid "Save game failed!"
-#~ msgstr "Ukládání hry selhalo!"
+#~ msgstr "Zapnout re¾im Roland GS"
#~ msgctxt "lowres"
#~ msgid "Add Game..."
-#~ msgstr "Přidat Hru..."
+#~ msgstr "Pøidat Hru..."
#~ msgid "Add Game..."
-#~ msgstr "Přidat Hru..."
+#~ msgstr "Pøidat Hru..."
#~ msgid ""
#~ "Your game version has been detected using filename matching as a variant "
#~ "of %s."
#~ msgstr ""
-#~ "Bylo zjištěno, že Vaše verze hry používá jméno souboru shodující se "
-#~ "s variantou %s."
+#~ "Bylo zji¹tìno, ¾e Va¹e verze hry pou¾ívá jméno souboru shodující se s "
+#~ "variantou %s."
#~ msgid "If this is an original and unmodified version, please report any"
-#~ msgstr "Pokud je toto původní a nezměněná verze, ohlaste prosím jakékoli"
+#~ msgstr "Pokud je toto pùvodní a nezmìnìná verze, ohlaste prosím jakékoli"
#~ msgid "information previously printed by ScummVM to the team."
-#~ msgstr "předešle vypsané informace od ScummVM zpátky týmu."
+#~ msgstr "pøede¹le vypsané informace od ScummVM zpátky týmu."
#~ msgid "Discovered %d new games."
-#~ msgstr "Objeveno %d nových her."
+#~ msgstr "Objeveno %d nových her."
#~ msgid "Command line argument not processed"
-#~ msgstr "Argument příkazové řádky nebyl zpracován"
+#~ msgstr "Argument pøíkazové øádky nebyl zpracován"
+
+#~ msgid "FM Towns Emulator"
+#~ msgstr "FM Towns Emulátor"
#~ msgid "Invalid Path"
-#~ msgstr "Neplatná Cesta"
+#~ msgstr "Neplatná Cesta"
diff --git a/po/da_DA.po b/po/da_DK.po
index 9684b82833..934297bd80 100644
--- a/po/da_DA.po
+++ b/po/da_DK.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-09 17:34+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-25 21:08+0100\n"
"Last-Translator: Steffen Nyeland <steffen@nyeland.dk>\n"
"Language-Team: Steffen Nyeland <steffen@nyeland.dk>\n"
"Language: Dansk\n"
@@ -74,7 +74,7 @@ msgstr "Vælg"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Forfatter:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -82,24 +82,23 @@ msgstr "Navn:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Noter:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "OK"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Vælg fil til indlæsning"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Indtast filnavn til at gemme"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Vil du virkelig slette denne gemmer?"
+msgstr "Vil du virkelig overskrive filen?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -592,16 +591,16 @@ msgid "Search:"
msgstr "Søg:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Indlæs spil:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Indlæs"
@@ -649,7 +648,7 @@ msgstr "Tilføj flere..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr ""
+msgstr "Optag..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
@@ -676,21 +675,19 @@ msgstr "Fundet %d nye spil, ignorer %d tidligere tilføjede spil ..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Stop"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr ""
+msgstr "Ret optag beskrivelse"
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Skift"
+msgstr "Skift til Spil"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Hurtig tilstand"
+msgstr "Hurtig afspil"
#: gui/options.cpp:85
msgid "Never"
@@ -767,7 +764,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Speciel farvereduceringstilstand understøttet a nogle spil"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Fuldskærms tilstand"
@@ -1080,39 +1077,38 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# næste"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr ""
+msgstr "tilføj"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Slet"
+msgstr "Slet tegn"
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr ""
+msgstr "* Præ"
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Num"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr ""
+msgstr "Optag eller Afspil Gameplay"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1121,36 +1117,33 @@ msgstr "Slet"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr ""
+msgstr "Optag"
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Spil"
+msgstr "Afspil"
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Ret"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Forfatter: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Noter: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Vil du virkelig slette denne gemmer?"
+msgstr "Vil du virkelig slette denne optagelse?"
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Ukendt fejl"
+msgstr "Ukendt forfatter"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1357,18 +1350,18 @@ msgstr "Hercules brun"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 Farver)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 Farver)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules grøn"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules brun"
@@ -1420,11 +1413,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~R~etur til oversigt"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Gemmer:"
@@ -1433,11 +1430,15 @@ msgstr "Gemmer:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Gem"
@@ -1556,7 +1557,7 @@ msgstr "DOSBox OPL emulator"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA Direct FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1612,17 +1613,15 @@ msgstr "Apple II GS emulator (IKKE IMPLEMENTERET)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Creative Music System Emulator"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "FM Towns emulator"
+msgstr "FM Towns lyd"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Lyd"
+msgstr "PC-98 lyd"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1717,34 +1716,33 @@ msgstr "Vil du afslutte?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Pegeplade tilstand deaktiveret."
+msgstr "Pegeplade-tilstand er nu"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "TIL"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "FRA"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Før to fingre til højre for at skifte."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Auto-træk tilstand er nu"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Før tre fingre til højre for at skifte."
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1765,19 +1763,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Aktivér billedformat korrektion"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Deaktivér billedformat korrektion"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktive grafik filtre:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Vindue tilstand"
@@ -2039,24 +2037,23 @@ msgstr "Kontrollér mus"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Data ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Ressourcer ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SDKort ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Medie ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Mappe:"
+msgstr "[ Delt ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2323,35 +2320,45 @@ msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr "Brug de originale gem/indlæs skærme, istedet for dem fra ScummVM"
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr "Brug en alternativ spil intro (kun CD version)"
+msgstr "Brug en alternativ palette"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"Brug en alternativ palet, fælles for alle Amiga spil. Dette var den gamle "
+"adfærd"
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Spring over støtte"
+msgstr "Understøt mus"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"Aktivér muse support. Gør det muligt at bruge musen til bevægelse og i spil "
+"menuer."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Gendan spil:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Gendan"
@@ -2394,13 +2401,12 @@ msgid "Cutscene file '%s' not found!"
msgstr "Filmsekvens fil '%s' ikke fundet!"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Klik tilstand"
+msgstr "Farveblind-tilstand"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Aktivér Farveblind tilstand som standard"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2456,11 +2462,11 @@ msgstr "Mislykkedes at gemme spil"
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Splatter-tilstand"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Aktiver Splatter-tilstand når mulig"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2592,6 +2598,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Følgende originale savegame fil er blevet fundet i din spil sti:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Ønsker du at bruge denne savegame fil med ScummVM?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2599,6 +2611,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"En savegame fil blev fundet på den angivne plads %d. Overskriv?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2610,6 +2624,12 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"%d originale savegame filer, er med succes er blevet importeret i\n"
+"ScummVM. Hvis du manuelt vil importere original savegame filer senere, vil "
+"du være\n"
+"nødt til at åbne ScummVM debug konsol og bruge kommandoen "
+"'import_savefile'.\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2664,10 +2684,18 @@ msgstr ""
"Kan ikke gemme spil på plads %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Indlæs fil"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Indlæser spil..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Gem fil"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Gemmer spil..."
@@ -2750,21 +2778,21 @@ msgstr "Brug en alternativ spil intro (kun CD version)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Skip EGA farvereducering (fuldfarvet baggrunde)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
+"Spring farvereducering i EGA spil over, grafikken bliver vist med fulde "
+"farver"
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "Aktivér træfpoint (HP) søjlediagrammer"
+msgstr "Aktivér grafik i høj opløsning"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "Aktivér træfpoint (HP) søjlediagrammer"
+msgstr "Aktivér høj opløsnings grafik/indhold"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2836,15 +2864,13 @@ msgstr "Spil sat på pause. Tryk MELLEMRUM for at fortsætte."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Er du sikker på at du vil genstarte? (J/N) "
+msgstr "Er du sikker på at du vil genstarte? (J/N)J"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
-msgstr "Er du sikker på at du vil afslutte? (J/N) "
+msgstr "Er du sikker på at du vil afslutte? (J/N)J"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
@@ -3352,25 +3378,24 @@ msgid "Third kid"
msgstr "Tredie barn"
#: engines/scumm/help.cpp:292
-#, fuzzy
msgid "Toggle Inventory/IQ Points display"
-msgstr "Skift Center Data Display"
+msgstr "Skift Inventory/IQ Points display "
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Skift Tastatur/Muse Kamp (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "* Tastatur Kamp er altid slået til,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr " så på trods af in-game beskeden, denne"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr " skifter faktisk Muse Kamp Fra/Til"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3407,7 +3432,7 @@ msgstr "Slå lavt"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr ""
+msgstr "Mavepuster"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3466,23 +3491,20 @@ msgid "Fly to lower right"
msgstr "Flyv nederst til højre"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Jævn bevægelse"
+msgstr "Jævn bevægelse til"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr ""
+msgstr "Jævn bevægelse fra"
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "Musik lydstyrke:"
+msgstr "Musik lydstyrke: "
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
-msgstr "Tekst hastighed:"
+msgstr "Tekst hastighed: "
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3494,27 +3516,86 @@ msgstr ""
"men %s mangler. Bruger AdLib i stedet."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Normalt ville Maniac Mansion begynde nu. Men ScummVM kan ikke gøre det "
-"endnu. For at spille det, gå til 'Tilføj spil' i ScummVM start-menuen og "
-"vælg 'Maniac' mappen inde i Tentacle spillets mappe."
+"Normalt ville Maniac Mansion starte nu. Men for at det skal fungere, skal "
+"spil filerne til Maniac Mansion skal være i \"Maniac\" mappen inde i "
+"Tentacle spil biblioteket, og spillet skal tilføjes til ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Kunne ikke finde den 'Loom' Macintosh eksekverbare fil, til\n"
+"at læse instrumenterne fra. Musik bliver deaktiveret."
#: 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 ""
+"Kunne ikke finde den 'Monkey Island' Macintosh eksekverbare fil, til\n"
+"at læse instrumenterne fra. Musik bliver deaktiveret."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Brug original gem/indlæs dialog"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Knappen Files i spillet viser original gem/indlæs dialog snarere end ScummVM "
+"menuen"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pixelleret scene overgange"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Ved sceneskift, bruges en tilfældig pixelleret overgang"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Vis ikke hotspots, når du flytter musen"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Vis kun hotspot navne efter du rent faktisk klikker på et hotspot eller en "
+"handlingsknap"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Vis person portrætter"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Vis portrætter for personer når de taler"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Skub dialoger til syne"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Skub dialoger til syne, i stedet for blot at vise dem straks"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Gennemsigtige vinduer"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Vis vinduer med delvis gennemsigtig baggrund"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3629,52 +3710,49 @@ msgstr ""
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Vis FPS-tæller"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
-msgstr ""
+msgstr "Vis det nuværende antal billeder per sekund i øverste venstre hjørne"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Brug de originale gem/indlæs skærme, istedet for dem fra ScummVM"
+msgstr ""
+"Brug de originale gem/indlæs skærme, i stedet for dem fra ScummVM "
+"brugerfladen"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Dobbelt FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Øger billedhastighed fra 30 til 60 FPS"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Aktivér helium tilstand"
+msgstr "Aktivér Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Aktivér helium tilstand"
+msgstr "Aktivér Venus hjælpe systemmet"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Deaktiver animation, mens du drejer"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Deaktiver animation mens du drejer i panorama-tilstand"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Brug høj opløsning MPEG-video"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
-msgstr ""
-"Brug det alternative sæt af sølv markører, i stedet for de normale gyldne"
+msgstr "Brug MPEG-video fra DVD-versionen, i stedet for lavere opløsning AVI"
#~ msgid "EGA undithering"
#~ msgstr "EGA farveforøgelse"
@@ -3723,10 +3801,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Aktivér Roland GS tilstand"
-#, fuzzy
-#~ msgid "Save game failed!"
-#~ msgstr "Gemmer:"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Tilføj spil..."
diff --git a/po/de_DE.po b/po/de_DE.po
index 06c04917b6..dbfeba57d5 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -1,15 +1,15 @@
# German translation for ScummVM.
# Copyright (C) 2010-2016 The ScummVM Team
# This file is distributed under the same license as the ScummVM package.
-# Simon Sawatzki <SimSaw@gmx.de>, Lothar Serra Mari <scummvm@rootfather.de>, 2015.
+# Simon Sawatzki <SimSaw@gmx.de>, Lothar Serra Mari <scummvm@rootfather.de>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-01-28 19:00+0100\n"
-"Last-Translator: Lothar Serra Mari <scummvm@rootfather.de>\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-22 20:53+0100\n"
+"Last-Translator: Simon Sawatzki <SimSaw@gmx.de>\n"
"Language-Team: Simon Sawatzki <SimSaw@gmx.de>, Lothar Serra Mari "
"<scummvm@rootfather.de>\n"
"Language: Deutsch\n"
@@ -595,16 +595,16 @@ msgid "Search:"
msgstr "Suchen:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Spiel laden:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Laden"
@@ -770,7 +770,7 @@ msgstr ""
"Spezielle Farbmischungsmethoden werden von manchen Spielen unterstützt."
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Vollbildmodus"
@@ -1373,12 +1373,12 @@ msgstr "PC-9821 (256 Farben)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 Farben)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Grün"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Bernst."
@@ -1433,11 +1433,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Zur Spiele~l~iste"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Speichern:"
@@ -1446,11 +1450,15 @@ msgstr "Speichern:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Speichern"
@@ -1778,19 +1786,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal ohn.Skalieren"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Seitenverhältniskorrektur an"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Seitenverhältniskorrektur aus"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktiver Grafikfilter:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Fenstermodus"
@@ -2359,15 +2367,23 @@ msgstr ""
"Aktiviere Maus-Unterstützung. Erlaubt die Verwendung der Maus zur Bewegung "
"und in Menüs innerhalb des Spiels."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Spiel laden:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Laden"
@@ -2698,10 +2714,18 @@ msgstr ""
"Kann Spiel nicht speichern auf Speicherplatz %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Datei laden"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Spiel wird geladen..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Datei speichern"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Spiel wird gespeichert..."
@@ -3553,6 +3577,58 @@ msgstr ""
"Macintosh-Programmdatei für Instrumente in \"Monkey Island\" nicht\n"
"gefunden. Musik wird abgeschaltet."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Originale Spielstand-Menüs verwenden"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr "Dateien-Schaltfläche im Spiel zeigt originales Spielstand-Menü statt dem von ScummVM."
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Verpixelte Szenenübergänge"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Bei Szenenwechseln wird ein zufälliger Pixelübergang verwendet."
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Bei Mausbewegung keine Klickpunkte anzeigen"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr "Zeigt Klickpunktnamen nur nach Klick auf selbigen oder auf einen Aktionspunkt."
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Figurenportraits zeigen"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Zeigt Portraits der Figuren bei Gesprächen."
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Menüs in Blickfeld gleiten lassen"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Lässt Menüs in Blickfeld gleiten anstatt sie einfach sofort anzuzeigen."
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Transparente Fenster"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Zeigt Fenster mit teilweise transparentem Hintergrund"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3771,9 +3847,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Roland-GS-Modus"
-#~ msgid "Save game failed!"
-#~ msgstr "Konnte Spielstand nicht speichern!"
-
#~ msgid ""
#~ "Your game version has been detected using filename matching as a variant "
#~ "of %s."
diff --git a/po/es_ES.po b/po/es_ES.po
index 8af41273d2..1593d4f815 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.4.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-06 20:39+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-24 18:01+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: Espanol\n"
@@ -73,7 +73,7 @@ msgstr "Aceptar"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Autor:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -81,24 +81,23 @@ msgstr "Nombre:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Notas:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "Aceptar"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Elegir el archivo para cargar"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Escribir el nombre del archivo"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "¿Seguro que quieres borrar esta partida?"
+msgstr "¿Seguro que quieres sobrescribir esta partida?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -591,16 +590,16 @@ msgid "Search:"
msgstr "Buscar:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Cargar juego:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Cargar"
@@ -648,7 +647,7 @@ msgstr "Añadir varios..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr ""
+msgstr "Grabar..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
@@ -675,21 +674,19 @@ msgstr "%d juegos nuevos encontrados. %d juegos ignorados (ya añadidos)..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Detener"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr ""
+msgstr "Editar la descripción de la grabación"
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Cambiar"
+msgstr "Volver al juego"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Modo rápido"
+msgstr "Repetición rápida"
#: gui/options.cpp:85
msgid "Never"
@@ -763,10 +760,10 @@ msgstr "Renderizado:"
#: gui/options.cpp:746 gui/options.cpp:747
msgid "Special dithering modes supported by some games"
-msgstr "Modos especiales de expansión compatibles con algunos juegos"
+msgstr "Modos especiales de difuminado compatibles con algunos juegos"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Pantalla completa"
@@ -1087,39 +1084,38 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# siguiente"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr ""
+msgstr "añadir"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Borrar"
+msgstr "Borrar personaje"
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr ""
+msgstr "* Pre"
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Num"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr ""
+msgstr "Grabar o reproducir vídeos"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1128,36 +1124,33 @@ msgstr "Borrar"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr ""
+msgstr "Grabar"
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Jugar"
+msgstr "Reproducción"
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Editar"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Autor:"
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Notas:"
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "¿Seguro que quieres borrar esta partida?"
+msgstr "¿Seguro que quieres borrar esta grabación?"
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Error desconocido"
+msgstr "Autor desconocido"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1364,18 +1357,18 @@ msgstr "Hercules ámbar"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 colores)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 colores)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules verde"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ámbar"
@@ -1426,11 +1419,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~V~olver al lanzador"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Guardar partida"
@@ -1439,11 +1436,15 @@ msgstr "Guardar partida"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Guardar"
@@ -1563,7 +1564,7 @@ msgstr "Emulador OPL de DOSBox"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA Direct FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1620,16 +1621,15 @@ msgstr "Emulador de Apple II GS (NO IMPLEMENTADO)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Emulador de Creative Music System"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
msgid "FM-Towns Audio"
-msgstr ""
+msgstr "FM-Towns Audio"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Sonido"
+msgstr "PC-98 Audio"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1724,34 +1724,33 @@ msgstr "¿Quieres salir?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Modo Touchpad desactivado."
+msgstr "El modo trackpad está"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "activado"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "desactivado"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Desliza dos dedos hacia la derecha para cambiar de modo."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "El modo de arrastre automático está"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Desliza tres dedos hacia la derecha para cambiar de modo."
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1772,19 +1771,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Activar la corrección de aspecto"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Desactivar la corrección de aspecto"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Filtro de gráficos activo:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Modo ventana"
@@ -2046,24 +2045,23 @@ msgstr "Control del ratón"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Datos ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Recursos ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ Tarjeta SD ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Media ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Disco compartido:"
+msgstr "[ Compartido ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2331,36 +2329,45 @@ msgstr ""
"Utilizar las pantallas de guardar/cargar originales, en vez de las de ScummVM"
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr ""
-"Usa una introducción alternativa para el juego (solo para la versión CD)"
+msgstr "Usar paleta alternativa"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"Usar una paleta alternativa, común para todos los juegos de Amiga. Esta es "
+"la opción que se usaba antes."
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Permitir omisiones"
+msgstr "Compatibilidad de ratón"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"Activa el ratón. Permite usar el ratón para moverse en el juego y en los "
+"menús."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Cargar partida:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Cargar"
@@ -2403,13 +2410,12 @@ msgid "Cutscene file '%s' not found!"
msgstr "No se ha encontrado el vídeo '%s'"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Modo clic"
+msgstr "Modo para daltónicos"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Activar por defecto el modo para daltónicos"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2465,11 +2471,11 @@ msgstr "Fallo al guardar la partida"
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Modo sangriento"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Activar el modo sangriento si está disponible"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2601,6 +2607,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Se ha encontrado esta partida guardada en el directorio del juego:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Do you wish to use this save game file with ScummVM?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2608,6 +2620,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"Ya hay una partida guardada en la ranura %d. ¿Quieres sobrescribirla?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2619,6 +2633,11 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"Se han importado %d partidas guardadas originales.\n"
+"Si más adelante quieres importar manualmente más partidas guardadas\n"
+"originales, tendrás que abrir la consola de ScummVM y usar el comando "
+"'import_savefile'.\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2672,10 +2691,18 @@ msgstr ""
"No se puede guardar en la ranura %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Cargar partida"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Cargando partida..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Guardar partida"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Guardando partida..."
@@ -2760,21 +2787,21 @@ msgstr ""
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Omitir difuminado EGA (colores completos)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
+"Omitir pasada de difuminado en los juegos EGA. Los gráficos se muestran con "
+"los colores completos"
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "Activar las barras de energía"
+msgstr "Activar gráficos de alta resolución"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "Activar las barras de energía"
+msgstr "Activar gráficos/contenido de alta resolución"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2847,13 +2874,11 @@ msgstr "Juego pausado. Pulsa Espacio para continuar."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
msgstr "¿Seguro que quieres reiniciar? (S/N)S"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
msgstr "¿Seguro que quieres salir? (S/N)S"
@@ -3363,25 +3388,24 @@ msgid "Third kid"
msgstr "Tercer chaval"
#: engines/scumm/help.cpp:292
-#, fuzzy
msgid "Toggle Inventory/IQ Points display"
-msgstr "Activar/Desactivar pantalla de datos"
+msgstr "Alternar entre el inventario y la pantalla de puntuación"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Alternar entre modo de lucha con teclado o con ratón (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "* El modo de lucha con teclado siempre está activo,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr " así que, independientemente de lo que diga el juego,"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr " esta opción activa/desactiva el modo de lucha con ratón"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3418,7 +3442,7 @@ msgstr "Puñetazo bajo"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr ""
+msgstr "Puñetazo a traición"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3477,21 +3501,18 @@ msgid "Fly to lower right"
msgstr "Volar abajo y a la derecha"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Desplazamiento suave"
+msgstr "Desplazamiento mediante toques"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr ""
+msgstr "Desplazamiento normal"
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "Música:"
+msgstr "Volumen de la música:"
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
msgstr "Vel. de subtítulos:"
@@ -3505,27 +3526,88 @@ msgstr ""
"pero %s no está disponible. Se usará AdLib."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Maniac Mansion debería arrancar en este momento, pero ScummVM aún no lo "
-"permite. Para jugar, ve a 'Añadir juego' en el menú de inicio de ScummVM y "
-"selecciona el directorio 'Maniac', dentro del directorio de DOTT."
+"Maniac Mansion debería arrancar en este momento, pero para que esto sea "
+"posible debes mover los archivos de Maniac Mansion al directorio 'Maniac', "
+"dentro del directorio de DOTT, y añadir el juego a ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"No se ha podido encontrar el ejecutable de Macintosh de 'Loom'\n"
+"para reproducir los instrumentos. Se ha desactivado la música."
#: 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 ""
+"No se ha podido encontrar el ejecutable de Macintosh de 'Monkey Island'\n"
+"para reproducir los instrumentos. Se ha desactivado la música."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Usar menús originales al guardar/cargar"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Se usan los menús originales para guardar y cargar partida en vez de los "
+"menús de ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Transiciones pixeladas"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Al cambiar de escena, se utiliza una transición aleatoria de píxeles"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "No mostrar los puntos interactivos al mover el ratón"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"El nombre de los puntos interactivos solo aparece al hacer clic en uno de "
+"ellos o en un botón de acción."
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Mostrar retratos"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Mostrar retratos de los personajes durante las conversaciones"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Utilizar una transición al mostrar los diálogos"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+"Los diálogos se muestran con una transición, en vez de aparecer "
+"inmediatamente"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Ventanas transparentes"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Mostrar las ventanas con un fondo parcialmente transparente"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3646,53 +3728,50 @@ msgstr ""
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Mostrar contador de FPS"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
+"El número de fotogramas por segundo aparece en la esquina superior izquierda"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
msgstr ""
-"Utilizar las pantallas de guardar/cargar originales, en vez de las de ScummVM"
+"Utilizar los menús originales para guardar/cargar, en vez de los de ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Duplicar FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Aumenta el número de fotogramas por segundo de 30 a 60"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Activar el modo helio"
+msgstr "Activar Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Activar el modo helio"
+msgstr "Activar el modo de ayuda Venus"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Desactivar animación al girar"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Desactivar la animación al girar en el modo panorama"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Usar vídeos MPEG de alta resolución"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
msgstr ""
-"Usar los cursores plateados alternativos, en vez de los dorados normales"
+"Usar los vídeos MPEG de la versión DVD, en vez de los AVI de baja resolución"
#~ msgid "EGA undithering"
#~ msgstr "Difuminado EGA"
@@ -3742,6 +3821,3 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Activar modo Roland GS"
-
-#~ msgid "Save game failed!"
-#~ msgstr "No se ha podido guardar la partida."
diff --git a/po/eu.po b/po/eu.po
index 0dbc77490b..a8dfe66cb1 100644
--- a/po/eu.po
+++ b/po/eu.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.5.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2011-12-15 14:53+0100\n"
"Last-Translator: Mikel Iturbe Urretxa <mikel@hamahiru.org>\n"
"Language-Team: Librezale <librezale@librezale.org>\n"
@@ -30,13 +30,12 @@ msgid "Available engines:"
msgstr "Motore erabilgarriak:"
#: gui/browser.cpp:68 gui/browser_osx.mm:104
-#, fuzzy
msgid "Show hidden files"
-msgstr "Kontsola erakutsi / ezkutatu"
+msgstr "Erakutsi fitxategi ezkutuak"
#: gui/browser.cpp:68
msgid "Show files marked with the hidden attribute"
-msgstr ""
+msgstr "Erakutsi ezkutu modura markaturiko fitxategiak"
#: gui/browser.cpp:72
msgid "Go up"
@@ -73,7 +72,7 @@ msgstr "Aukeratu"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Egilea:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -81,24 +80,23 @@ msgstr "Izena:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Oharrak:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "Ados"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Aukeratu kargatzeko fitxategia"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Sartu gordetzeko fitxategi-izena"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Ezabatu partida gorde hau?"
+msgstr "Gainidatzi fitxategia?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -121,59 +119,56 @@ msgid "No"
msgstr "Ez"
#: gui/fluidsynth-dialog.cpp:68
-#, fuzzy
msgid "Reverb"
-msgstr "Inoiz ez"
+msgstr "Erreberberazioa"
#: gui/fluidsynth-dialog.cpp:70 gui/fluidsynth-dialog.cpp:102
-#, fuzzy
msgid "Active"
-msgstr "(Aktiboa)"
+msgstr "Aktiboa"
#: gui/fluidsynth-dialog.cpp:72
msgid "Room:"
-msgstr ""
+msgstr "Gela:"
#: gui/fluidsynth-dialog.cpp:79
msgid "Damp:"
-msgstr ""
+msgstr "Moteltzea:"
#: gui/fluidsynth-dialog.cpp:86
msgid "Width:"
-msgstr ""
+msgstr "Zabalera:"
#: gui/fluidsynth-dialog.cpp:93 gui/fluidsynth-dialog.cpp:111
msgid "Level:"
-msgstr ""
+msgstr "Maila:"
#: gui/fluidsynth-dialog.cpp:100
msgid "Chorus"
-msgstr ""
+msgstr "Koroa"
#: gui/fluidsynth-dialog.cpp:104
msgid "N:"
-msgstr ""
+msgstr "N:"
#: gui/fluidsynth-dialog.cpp:118
-#, fuzzy
msgid "Speed:"
-msgstr "Ahotsa"
+msgstr "Abiadura:"
#: gui/fluidsynth-dialog.cpp:125
msgid "Depth:"
-msgstr ""
+msgstr "Sakonera:"
#: gui/fluidsynth-dialog.cpp:132
msgid "Type:"
-msgstr ""
+msgstr "Mota:"
#: gui/fluidsynth-dialog.cpp:135
msgid "Sine"
-msgstr ""
+msgstr "Sinua"
#: gui/fluidsynth-dialog.cpp:136
msgid "Triangle"
-msgstr ""
+msgstr "Triangelua"
#: gui/fluidsynth-dialog.cpp:138 gui/options.cpp:1168
msgid "Misc"
@@ -181,31 +176,31 @@ msgstr "Beste"
#: gui/fluidsynth-dialog.cpp:140
msgid "Interpolation:"
-msgstr ""
+msgstr "Interpolazioa:"
#: gui/fluidsynth-dialog.cpp:143
msgid "None (fastest)"
-msgstr ""
+msgstr "Bat ere ez (azkarrena)"
#: gui/fluidsynth-dialog.cpp:144
msgid "Linear"
-msgstr ""
+msgstr "Lineala"
#: gui/fluidsynth-dialog.cpp:145
msgid "Fourth-order"
-msgstr ""
+msgstr "Laugarren ordena"
#: gui/fluidsynth-dialog.cpp:146
msgid "Seventh-order"
-msgstr ""
+msgstr "Zazpigarren ordena"
#: gui/fluidsynth-dialog.cpp:150
msgid "Reset"
-msgstr ""
+msgstr "Berrezarri"
#: gui/fluidsynth-dialog.cpp:150
msgid "Reset all FluidSynth settings to their default values."
-msgstr ""
+msgstr "Berrazarri FluidSynth-en ezarpen guztiak bere balio lehenetsietara"
#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:42 gui/launcher.cpp:352
#: gui/launcher.cpp:1050 gui/launcher.cpp:1054 gui/massadd.cpp:92
@@ -227,10 +222,9 @@ msgid "OK"
msgstr "Ados"
#: gui/fluidsynth-dialog.cpp:217
-#, fuzzy
msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
-msgstr "Ziur zaude abiarazlera itzuli nahi duzula?"
+msgstr "FluidSynth-en ezarpen guztiak berrezarri balio lehenetsietara?"
#: gui/gui-manager.cpp:119 backends/keymapper/remap-dialog.cpp:53
#: engines/scumm/help.cpp:126 engines/scumm/help.cpp:141
@@ -245,11 +239,11 @@ msgstr "Sagu-klika"
#: gui/gui-manager.cpp:126 base/main.cpp:322
msgid "Display keyboard"
-msgstr "Teklatua erakutsi"
+msgstr "Erakutsi teklatua"
#: gui/gui-manager.cpp:130 base/main.cpp:326
msgid "Remap keys"
-msgstr "Teklak esleitu"
+msgstr "Esleitu teklak"
#: gui/gui-manager.cpp:133 base/main.cpp:329 engines/scumm/help.cpp:87
msgid "Toggle fullscreen"
@@ -346,9 +340,8 @@ msgid "Platform:"
msgstr "Plataforma:"
#: gui/launcher.cpp:237
-#, fuzzy
msgid "Engine"
-msgstr "Aztertu"
+msgstr "Motorea"
#: gui/launcher.cpp:245 gui/options.cpp:1071 gui/options.cpp:1088
msgid "Graphics"
@@ -593,16 +586,16 @@ msgid "Search:"
msgstr "Bilatu:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Jokoa kargatu:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Kargatu"
@@ -632,9 +625,8 @@ msgid "Do you really want to remove this game configuration?"
msgstr "Benetan ezabatu nahi duzu joko-konfigurazio hau?"
#: gui/launcher.cpp:1001
-#, fuzzy
msgid "Do you want to load saved game?"
-msgstr "Jokoa kargatu edo gorde nahi duzu?"
+msgstr "Gordetako jokoa kargatu?"
#: gui/launcher.cpp:1050
msgid "This game does not support loading games from the launcher."
@@ -648,11 +640,11 @@ msgstr ""
#: gui/launcher.cpp:1161
msgid "Mass Add..."
-msgstr "Hainbat gehitu..."
+msgstr "Gehitu hainbat..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr ""
+msgstr "Grabatu..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
@@ -681,21 +673,19 @@ msgstr ""
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Gelditu"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr ""
+msgstr "Editatu grabazioaren desribapena"
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Aldatu"
+msgstr "Aldatu jokora"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Modu bizkorra"
+msgstr "Errepikappen bizkorra"
#: gui/options.cpp:85
msgid "Never"
@@ -772,7 +762,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Joko batzuk onarturiko lausotze-modu bereziak"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Pantaila osoa"
@@ -875,7 +865,7 @@ msgstr "MIDI irabazia:"
#: gui/options.cpp:872
msgid "FluidSynth Settings"
-msgstr ""
+msgstr "FluidSynth Ezarpenak"
#: gui/options.cpp:879
msgid "MT-32 Device:"
@@ -905,15 +895,16 @@ msgid "True Roland MT-32 (no GM emulation)"
msgstr "Benetako Roland MT-32 (GM emulazio gabe)"
#: gui/options.cpp:889
-#, fuzzy
msgid "Roland GS Device (enable MT-32 mappings)"
-msgstr "Benetako Roland MT-32 (GM emulazio gabe)"
+msgstr "Roland GS Gailua (gaitu MT-32 bihurketak)"
#: gui/options.cpp:889
msgid ""
"Check if you want to enable patch mappings to emulate an MT-32 on a Roland "
"GS device"
msgstr ""
+"Markatu Roland GS gailu batean MT-32 bat emulatzea ahalbidetzen "
+"dutenbihurketak gaitzeko"
#: gui/options.cpp:898
msgid "Don't use Roland MT-32 music"
@@ -1089,39 +1080,38 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# hurrengoa"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr ""
+msgstr "gehitu"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Ezabatu"
+msgstr "Ezabatu karakterea"
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr ""
+msgstr "* Pre"
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Zenb"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr ""
+msgstr "Grabatu edo erreproduzitu jokoko akzioa"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1130,44 +1120,41 @@ msgstr "Ezabatu"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr ""
+msgstr "Grabatu"
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Jolastu"
+msgstr "Erreproduzitu"
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Editatu"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Egilea: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Oharrak: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Ezabatu partida gorde hau?"
+msgstr "Ezabatu grabazio hau?"
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Errore ezezaguna"
+msgstr "Egile ezezaguna"
#: gui/saveload-dialog.cpp:167
msgid "List view"
-msgstr ""
+msgstr "Zerrenda ikuspegia"
#: gui/saveload-dialog.cpp:168
msgid "Grid view"
-msgstr ""
+msgstr "Sareta ikuspegia "
#: gui/saveload-dialog.cpp:211 gui/saveload-dialog.cpp:360
msgid "No date saved"
@@ -1191,43 +1178,40 @@ msgstr "Data:"
#: gui/saveload-dialog.cpp:389 gui/saveload-dialog.cpp:890
msgid "Time: "
-msgstr "Ordua"
+msgstr "Ordua: "
#: gui/saveload-dialog.cpp:395 gui/saveload-dialog.cpp:898
msgid "Playtime: "
-msgstr "Denbora:"
+msgstr "Denbora: "
#: gui/saveload-dialog.cpp:408 gui/saveload-dialog.cpp:496
msgid "Untitled savestate"
-msgstr "Titulurik gabeko partida"
+msgstr "Titulurik gabeko joko gordea"
#: gui/saveload-dialog.cpp:548
msgid "Next"
-msgstr ""
+msgstr "Aurr."
#: gui/saveload-dialog.cpp:551
msgid "Prev"
-msgstr ""
+msgstr "Hurr."
#: gui/saveload-dialog.cpp:748
-#, fuzzy
msgid "New Save"
msgstr "Gorde"
#: gui/saveload-dialog.cpp:748
-#, fuzzy
msgid "Create a new save game"
-msgstr "Ezin izan da jokoa gorde"
+msgstr "Sortu joko gorde berria"
#: gui/saveload-dialog.cpp:877
-#, fuzzy
msgid "Name: "
-msgstr "Izena:"
+msgstr "Izena: "
#: gui/saveload-dialog.cpp:949
#, c-format
msgid "Enter a description for slot %d:"
-msgstr ""
+msgstr "Sartu deskribapena %d zirrikiturako: "
#: gui/themebrowser.cpp:45
msgid "Select a Theme"
@@ -1243,23 +1227,20 @@ msgid "Disabled GFX"
msgstr "GFX desgaituta"
#: gui/ThemeEngine.cpp:348
-#, fuzzy
msgid "Standard Renderer"
-msgstr "Estandarra (16bpp)"
+msgstr "Errendatzaile estandarra"
#: gui/ThemeEngine.cpp:348 engines/scumm/dialogs.cpp:663
msgid "Standard"
msgstr "Estandarra"
#: gui/ThemeEngine.cpp:350
-#, fuzzy
msgid "Antialiased Renderer"
-msgstr "Lausotua (16bpp)"
+msgstr "Errendatzaile lausotua"
#: gui/ThemeEngine.cpp:350
-#, fuzzy
msgid "Antialiased"
-msgstr "Lausotua (16bpp)"
+msgstr "Lausotua"
#: gui/widget.cpp:323 gui/widget.cpp:325 gui/widget.cpp:331 gui/widget.cpp:333
msgid "Clear value"
@@ -1372,18 +1353,18 @@ msgstr "Herkules anbar-kolorekoa"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 Kolore)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 kolore)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Herkules berdea"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Herkules anbar-kolorekoa"
@@ -1434,11 +1415,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "It~z~uli abiarazlera"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Gorde jokoa:"
@@ -1447,11 +1432,15 @@ msgstr "Gorde jokoa:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Gorde"
@@ -1568,7 +1557,7 @@ msgstr "DOSBox OPL emuladorea"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA FM zuzena"
#: audio/mididrv.cpp:209
#, c-format
@@ -1625,16 +1614,15 @@ msgstr "Apple II GS emuladorea (INPLEMENTATU GABE)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Creative musika sistema emuladorea"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
msgid "FM-Towns Audio"
-msgstr ""
+msgstr "FM-Towns soinua"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Soinua"
+msgstr "PC-98 Soinua"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1720,53 +1708,50 @@ msgid "Clicking Disabled"
msgstr "Klikatzea desgaituta"
#: backends/events/openpandora/op-events.cpp:174
-#, fuzzy
msgid "Touchscreen 'Tap Mode' - Hover (DPad Clicks)"
-msgstr "Ukimen-pantailako 'kolpetxo modua' - Flotatu (klikik ez)"
+msgstr "Ukimen-pantailako 'kolpetxo modua' - Flotatu (DPad klikak)"
#: backends/events/symbiansdl/symbiansdl-events.cpp:186
msgid "Do you want to quit ?"
-msgstr "Irten nahi al duzu?"
+msgstr "Benetan irten?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Touchpad modua desgaituta."
+msgstr "Trackpad modua orain:"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "ON"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "OFF"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Pasatu bi atzamara eskuinean gaitu/desgaitzeko."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Auto-arrastatzea orain:"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Pasatu hiru atzamar eskuinean gaitu/desgaitzeko."
#: backends/graphics/opengl/opengl-graphics.cpp:119
-#, fuzzy
msgid "OpenGL"
-msgstr "Ireki"
+msgstr "OpenGL"
#: backends/graphics/opengl/opengl-graphics.cpp:120
msgid "OpenGL (No filtering)"
-msgstr ""
+msgstr "OpenGL (Iragazi gabe)"
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:47
#: backends/graphics/wincesdl/wincesdl-graphics.cpp:88
@@ -1779,19 +1764,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normala"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Formatu-ratio zuzenketa gaituta"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Formatu-ratio zuzenketa desgaituta"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Filtro grafiko aktiboa:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Leiho modua"
@@ -2053,24 +2038,23 @@ msgstr "Saguaren kontrola"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Datuak ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Baliabideak ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SD Txartela ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Multimedia ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Konpartituriko direktorioa:"
+msgstr "[ Konpartitua ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2327,7 +2311,7 @@ msgstr "Eguneraketak bilatzen..."
#: engines/neverhood/detection.cpp:160 engines/sci/detection.cpp:404
#: engines/toltecs/detection.cpp:200 engines/zvision/detection_tables.h:51
msgid "Use original save/load screens"
-msgstr ""
+msgstr "Erabili jatorrizko gorde/kargatu pantailak"
#: engines/agi/detection.cpp:148 engines/cine/detection.cpp:71
#: engines/drascula/detection.cpp:303 engines/dreamweb/detection.cpp:48
@@ -2335,35 +2319,48 @@ msgstr ""
#: engines/toltecs/detection.cpp:201
msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr ""
+"Erabili jatorrizko gorde/kargatu pantailak, ScummVM-renak erabilibeharrean"
#: engines/agi/detection.cpp:157
msgid "Use an alternative palette"
-msgstr ""
+msgstr "Erabili paleta alternatiboa"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"Erabili kolore-paleta alternatiboa, Amiga joko guztientzako komuna. Hau zen "
+"konportamendu zaharra"
#: engines/agi/detection.cpp:167
msgid "Mouse support"
-msgstr ""
+msgstr "Saguaren euskarria"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"Saguaren euskarria giatzen du. Sagua mugitzeko eta jokoko menuetan "
+"erabiltzea ahalbidetzen du"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Jokoa kargatu:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Kargatu"
@@ -2406,16 +2403,14 @@ msgid "Cutscene file '%s' not found!"
msgstr "'%s' bideo fitxategia ez da aurkitu!"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Klikatzeko modua"
+msgstr "Daltonikoentzako modua"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Gaitu daltonikoentzako modua lehenetsi modura"
#: engines/drascula/saveload.cpp:47
-#, fuzzy
msgid ""
"ScummVM found that you have old savefiles for Drascula that should be "
"converted.\n"
@@ -2425,8 +2420,8 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
-"ScummVM-k aurkitu du konbertitu beharko liratekeen Broken Sword 1-eko "
-"partida gorde zaharrak dituzula.\n"
+"ScummVM-k aurkitu du konbertitu beharko liratekeen Drascula-ko partida gorde "
+"zaharrak dituzula.\n"
"Partida gordeen formatu zaharra ez da bateragarria jada, eta beraz ezingo "
"dituzu zure partidak kargatu ez badituzu formatu berrira pasatzen.\n"
"\n"
@@ -2434,13 +2429,12 @@ msgstr ""
"martxan jartzen duzunean.\n"
#: engines/dreamweb/detection.cpp:57
-#, fuzzy
msgid "Use bright palette mode"
-msgstr "Goiko eskuineko objektua"
+msgstr "Erabili paleta argia"
#: engines/dreamweb/detection.cpp:58
msgid "Display graphics using the game's bright palette"
-msgstr ""
+msgstr "Erakutsi grafikoak jokoaren paleta argia erabilita"
#: engines/gob/inter_playtoons.cpp:256 engines/gob/inter_v2.cpp:1470
#: engines/gob/inter_geisha.cpp:232 engines/tinsel/saveload.cpp:532
@@ -2457,13 +2451,12 @@ msgid "Failed to delete file."
msgstr "Ezin izan da fitxategia ezabatu"
#: engines/groovie/detection.cpp:312
-#, fuzzy
msgid "Fast movie speed"
-msgstr "Modu bizkorra"
+msgstr "Bideo abiadura azkarra"
#: engines/groovie/detection.cpp:313
msgid "Play movies at an increased speed"
-msgstr ""
+msgstr "Erreproduzitu bidoeak abiadura handiagoan"
#: engines/groovie/script.cpp:408
msgid "Failed to save game"
@@ -2471,71 +2464,69 @@ msgstr "Ezin izan da jokoa gorde"
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Gore modua"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Gaitu Gore modua eskuragarri dagoenean"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
#: engines/kyra/detection.cpp:62
msgid "Studio audience"
-msgstr ""
+msgstr "Estudio ingurunea"
#: engines/kyra/detection.cpp:63
msgid "Enable studio audience"
-msgstr ""
+msgstr "Gaitu estudio ingurunea"
#. I18N: This option allows the user to skip text and cutscenes.
#: engines/kyra/detection.cpp:73
msgid "Skip support"
-msgstr ""
+msgstr "Jauzi egin"
#: engines/kyra/detection.cpp:74
msgid "Allow text and cutscenes to be skipped"
-msgstr ""
+msgstr "Utzi testua eta bideoak saltatzen"
#. I18N: Helium mode makes people sound like they've inhaled Helium.
#: engines/kyra/detection.cpp:84
msgid "Helium mode"
-msgstr ""
+msgstr "Helio modua"
#: engines/kyra/detection.cpp:85
-#, fuzzy
msgid "Enable helium mode"
-msgstr "Roland GS modua gaitu"
+msgstr "Gaitu helio modua"
#. I18N: When enabled, this option makes scrolling smoother when
#. changing from one screen to another.
#: engines/kyra/detection.cpp:99
msgid "Smooth scrolling"
-msgstr ""
+msgstr "Korritze leuna"
#: engines/kyra/detection.cpp:100
msgid "Enable smooth scrolling when walking"
-msgstr ""
+msgstr "Gaitu korritze leuna oinez ibiltzean"
#. I18N: When enabled, this option changes the cursor when it floats to the
#. edge of the screen to a directional arrow. The player can then click to
#. walk towards that direction.
#: engines/kyra/detection.cpp:112
-#, fuzzy
msgid "Floating cursors"
-msgstr "Kurtsore normala"
+msgstr "Kurtsore flotatzaileak"
#: engines/kyra/detection.cpp:113
msgid "Enable floating cursors"
-msgstr ""
+msgstr "Gaitu kurtsore flotatzaileak"
#. I18N: HP stands for Hit Points
#: engines/kyra/detection.cpp:127
msgid "HP bar graphs"
-msgstr ""
+msgstr "HP barrak"
#: engines/kyra/detection.cpp:128
msgid "Enable hit point bar graphs"
-msgstr ""
+msgstr "Gaitu bizitza barrak"
#: engines/kyra/lol.cpp:478
msgid "Attack 1"
@@ -2575,7 +2566,7 @@ msgstr "Eskuinera biratu"
#: engines/kyra/lol.cpp:487
msgid "Rest"
-msgstr "Kargatu"
+msgstr "Atsedena"
#: engines/kyra/lol.cpp:488
msgid "Options"
@@ -2586,7 +2577,6 @@ msgid "Choose Spell"
msgstr "Sorginkeria aukeratu"
#: engines/kyra/sound_midi.cpp:477
-#, fuzzy
msgid ""
"You appear to be using a General MIDI device,\n"
"but your game only supports Roland MT32 MIDI.\n"
@@ -2610,6 +2600,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Hurrengo jatorrizko gordetako fitxategia aurkitu da bidean:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Gordetako jokoaren fitxategia ScummVM-rekin erabili?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2617,6 +2613,9 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"Joko gorde baten fitxategia aurkitu da zehaztutako %d zirrikituan."
+"Gainidatzi?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2628,6 +2627,10 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"Jatorrizko %d gordetako joko fitxategi ondo inportatu dira \n"
+"ScummVM-era. Geroago eskuz jatorrizko joko gordeak inportatu\n"
+"nahi izanez gero ScummVM debug konsola ireki eta 'import_savefile'\n"
+"agindau erabili.\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2657,19 +2660,20 @@ msgstr "~U~r-efektua gaituta"
#: engines/neverhood/detection.cpp:167
msgid "Skip the Hall of Records storyboard scenes"
-msgstr ""
+msgstr "Saltatu Hall of Records-eko eszenak"
#: engines/neverhood/detection.cpp:168
msgid "Allows the player to skip past the Hall of Records storyboard scenes"
msgstr ""
+"Erabiltzaileari Halls of Records-eko eszenak ez ikusteko aukera ematen dio"
#: engines/neverhood/detection.cpp:174
msgid "Scale the making of videos to full screen"
-msgstr ""
+msgstr "Eskalatu bideoen egitea pantaila osora"
#: engines/neverhood/detection.cpp:175
msgid "Scale the making of videos, so that they use the whole screen"
-msgstr ""
+msgstr "Eskalatu bideoak egiteko era, pantaila osoa erabili dezaten"
#: engines/parallaction/saveload.cpp:133
#, c-format
@@ -2680,10 +2684,18 @@ msgstr ""
"Ezin da partida gorde %i zirrikituan\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Kargatu fitxategia:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Jokoa kargatzen..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Gorde fitxategia"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Jokoa gordetzen..."
@@ -2723,110 +2735,114 @@ msgstr ""
#: engines/pegasus/pegasus.cpp:714
msgid "Invalid save file name"
-msgstr ""
+msgstr "Gordetako jokoko fitxategi-izen baliogabea"
#: engines/pegasus/pegasus.cpp:2507
msgid "Up/Zoom In/Move Forward/Open Doors"
-msgstr ""
+msgstr "Gora/Zoom-a hurbildu/Mugitu aurrera/Ireki ateak"
#: engines/pegasus/pegasus.cpp:2508
-#, fuzzy
msgid "Down/Zoom Out"
-msgstr "Zoom-a hurbildu"
+msgstr "Behera/Zoom-a urrundu"
#: engines/pegasus/pegasus.cpp:2511
msgid "Display/Hide Inventory Tray"
-msgstr ""
+msgstr "Erakutsi/Ezkutatu inbentorioaren erretilua"
#: engines/pegasus/pegasus.cpp:2512
msgid "Display/Hide Biochip Tray"
-msgstr ""
+msgstr "Erakutsi/Ezkutatu Biochip erretilua"
#: engines/pegasus/pegasus.cpp:2513
msgid "Action/Select"
-msgstr ""
+msgstr "Ekintza/Aukeratu"
#: engines/pegasus/pegasus.cpp:2514
msgid "Toggle Center Data Display"
-msgstr ""
+msgstr "Erakutsi/Ezkutatu Datu Zentroa"
#: engines/pegasus/pegasus.cpp:2515
msgid "Display/Hide Info Screen"
-msgstr ""
+msgstr "Erakutsi/Ezkutatu informazio pantaila"
#: engines/pegasus/pegasus.cpp:2516
msgid "Display/Hide Pause Menu"
-msgstr ""
+msgstr "Erakutsi/Ezkutatu pausa menua"
#: engines/queen/detection.cpp:56
msgid "Alternative intro"
-msgstr ""
+msgstr "Sarrera alternatiboa"
#: engines/queen/detection.cpp:57
msgid "Use an alternative game intro (CD version only)"
-msgstr ""
+msgstr "Erabili sarrera alternatiboa (CD bertsioa soilik)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Saihestu EGA leuntze pausua (koloretako hondoak)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
+"Saihestu leuntzea EGA jokoetan, grafikoak kolore guztiekin erakustendira"
#: engines/sci/detection.cpp:384
msgid "Enable high resolution graphics"
-msgstr ""
+msgstr "Gaitu erresoluzio altuko grafikoak"
#: engines/sci/detection.cpp:385
msgid "Enable high resolution graphics/content"
-msgstr ""
+msgstr "Gaitu erresoluzio altuko grafikoak/edukiak"
#: engines/sci/detection.cpp:394
-#, fuzzy
msgid "Prefer digital sound effects"
-msgstr "Soinu efektu berezien bolumena"
+msgstr "Lehenetsi soinu efektu digitalak"
#: engines/sci/detection.cpp:395
msgid "Prefer digital sound effects instead of synthesized ones"
-msgstr ""
+msgstr "Lehenetsi soinu efektu digitalak sintetizatuen ordez"
#: engines/sci/detection.cpp:414
msgid "Use IMF/Yamaha FB-01 for MIDI output"
-msgstr ""
+msgstr "Erabili IMF/Yamaha FB-01 MIDI irteerarako"
#: engines/sci/detection.cpp:415
msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
+"Erabili IBM Music Feature txartela edo Yamaha FB-01 FM "
+"sintetizatzailemodulua MIDI irteerarako"
#: engines/sci/detection.cpp:425
msgid "Use CD audio"
-msgstr ""
+msgstr "Erabili audio CDa"
#: engines/sci/detection.cpp:426
msgid "Use CD audio instead of in-game audio, if available"
-msgstr ""
+msgstr "Erabili CD-ko audioa jokokoa beharrean, eskurarri badago"
#: engines/sci/detection.cpp:436
msgid "Use Windows cursors"
-msgstr ""
+msgstr "Erabili Windows-eko kurtsoreak"
#: engines/sci/detection.cpp:437
msgid ""
"Use the Windows cursors (smaller and monochrome) instead of the DOS ones"
msgstr ""
+"Erabili Windows-eko kurtsoreak (txikiagoak eta monokromoak) DOS-ekoak "
+"erabilibeharrean"
#: engines/sci/detection.cpp:447
-#, fuzzy
msgid "Use silver cursors"
-msgstr "Kurtsore normala"
+msgstr "Erabili zilarrezko kurtsoreak"
#: engines/sci/detection.cpp:448
msgid ""
"Use the alternate set of silver cursors, instead of the normal golden ones"
msgstr ""
+"Erabili zilar kolorezko kurtsore multzo alternatiboa, urre-koloreko "
+"kursorenormalak erabili beharrean"
#: engines/scumm/dialogs.cpp:176
#, c-format
@@ -2851,15 +2867,13 @@ msgstr "Joko pausatua. Sakatu ZURIUNEA jarraitzeko."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Ziur zaude berrabiarazi nahi duzula (B/E)B"
+msgstr "Berrabiarazi? (B/E)B"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
-msgstr "Ziur zaude irten nahi duzula? (B/E)B"
+msgstr "Irten? (B/E)B"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
@@ -2994,7 +3008,7 @@ msgstr "Alt"
#: engines/scumm/help.cpp:81
msgid "Save game state 1-10"
-msgstr "1-10 partida gorde"
+msgstr "Gorde 1-10 jokoa"
#: engines/scumm/help.cpp:87 engines/scumm/help.cpp:90
msgid "Enter"
@@ -3368,23 +3382,23 @@ msgstr "Hirugarren gaztea"
#: engines/scumm/help.cpp:292
msgid "Toggle Inventory/IQ Points display"
-msgstr ""
+msgstr "Txandakatu Inbentarioa/IQ puntuak"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Txandakatu teklatu/sagu bidezko borroka (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "* Teklatu bidezko borroka beti dago gaituta"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr " beraz, nahiz eta honelako mezuak erakutsi"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr " benetan sagu bidezko borroka gaitu/desgaitzen du"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3421,7 +3435,7 @@ msgstr "Ukabilkada baxua"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr ""
+msgstr "Ukabilkada inuzentea"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3480,21 +3494,18 @@ msgid "Fly to lower right"
msgstr "Behera eta eskuinera hegan egin"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Behera"
+msgstr "Heldutako korritze barra gaituta"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr ""
+msgstr "Heldutako korritze barra desgaituta"
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "Musika:"
+msgstr "Musika: "
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
msgstr "Azpitit. abiadura:"
@@ -3508,27 +3519,87 @@ msgstr ""
"baina %s ez dago eskuragarri. AdLib erabiliko da."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Maniac Mansion orain hasi beharko litzateke, baina ScummVM-k ez du "
-"baimentzen oraindik. Jolasteko , joan 'Jokoa gehitu' hasierako menura eta "
-"aukeratu 'Maniac' direktorioa Tentacle-ren joko-direktorioaren barruan."
+"Maniac Mansion orain hasi beharko litzateke, baina horretarako, jokoko "
+"fitxategiak 'Maniac' direktorio barruan egon behar dira, Tentacle jokoko "
+"direktorioan, eta jokoa ScummVM-ra gehitu behar da."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Ezin izan da 'Loom' Macintosh exekutagarria aurkitu instrumentuak\n"
+"bertatik irakurtzeko. Musika desgaituta egongo da."
#: 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 ""
+"Ezin izan da 'Monkey Island' Macintosh exekutagarria aurkitu instrumentuak\n"
+"bertatik irakurtzeko. Musika desgaituta egongo da."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Erabili jatorrizko jokoa gordetzeko elkarrizketak"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Jokoko Fitxategiak botoiak jatorrizko jokoa gordetzeko elkarrizketak erakusten "
+"ditu, ScummVM-ren elkarrizketak erakutsi beharrean"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Eszena trantsizio pixelatuak"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Eszenak aldatzean, ausazko pixel trantsizioa egiten da"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Ez erakutsi puntu interesgarriak sagua mugitzean"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Erakutsi puntu interesgarrien izenak haien gainean edota ekintza botoiaren "
+"gainean klik egin eta gero bakarrik "
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Erakutsi pertsonaien erretratuak"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Erakutsi pertsonaien erretratuak elkarrizketetan"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Irristatu elkarrizketak"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Irristatu UI elkarrizketak pantailara, osorik bat-batean erakutsi "
+"beharrean"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Leiho gardenak"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Erakutsi leihoak partzialki gardena den fondoarekin"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3548,16 +3619,16 @@ msgstr ""
#: engines/sky/detection.cpp:44
msgid "Floppy intro"
-msgstr ""
+msgstr "Floppy introa"
#: engines/sky/detection.cpp:45
msgid "Use the floppy version's intro (CD version only)"
-msgstr ""
+msgstr "Erabili floppy bertsioko sarrera (CD bertsioa soilik)"
#: engines/sword1/animation.cpp:524
#, c-format
msgid "PSX stream cutscene '%s' cannot be played in paletted mode"
-msgstr ""
+msgstr "'%s' PSX eszena ezin da erreproduzitu paletatutako moduan"
#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
msgid "DXA cutscenes found but ScummVM has been built without zlib"
@@ -3565,11 +3636,10 @@ msgstr ""
"DXA bideoak aurkitu dira, baina ScummVM zlib euskarri gabe konpilatu da"
#: engines/sword1/animation.cpp:561 engines/sword2/animation.cpp:461
-#, fuzzy
msgid ""
"MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"
msgstr ""
-"DXA bideoak aurkitu dira, baina ScummVM zlib euskarri gabe konpilatu da"
+"MPEG-2 bideoak aurkitu dira, baina ScummVM MPEG-2 euskarri gabe konpilatu da"
#: engines/sword1/animation.cpp:568 engines/sword2/animation.cpp:470
#, c-format
@@ -3624,68 +3694,69 @@ msgstr ""
#: engines/sword2/sword2.cpp:79
msgid "Show object labels"
-msgstr ""
+msgstr "Erakutsi objektuen etiketak"
#: engines/sword2/sword2.cpp:80
msgid "Show labels for objects on mouse hover"
-msgstr ""
+msgstr "Erakutsi objektuen etiketak sagua pasatzean"
#: engines/teenagent/resources.cpp:95
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
-msgstr ""
+msgstr "'teenagent.dat' fitxategia falta da. Eskuratu ScummVM webgunean"
#: engines/teenagent/resources.cpp:116
msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
+"teenagent. dat fitxategia konprimituta dago eta zlib ez dago txertatuta "
+"exekutagarri honetan. Deskonprimitu"
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Erakutsi FPS kontatzailea"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
-msgstr ""
+msgstr "Erakutsi momentuko FPS (frames per second) goiko ezkerreko ertzean"
#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM interface"
msgstr ""
+"Erabili jatorrizko gorde/kargatu pantailak ScummVM interfazearenak beharrean"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Bikoiztu FPSa"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Areagotu framerate-a 30etik 60 FPSra"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Roland GS modua gaitu"
+msgstr "Gaitu Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Roland GS modua gaitu"
+msgstr "Gaitu Venus laguntza sistema"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Desgaitu animazioak biratzean"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Desgaitu animazioak panorama moduan biratzean"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Erabili bereizmen altuko MPEG bideoa"
#: engines/zvision/detection_tables.h:92
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
-msgstr ""
+msgstr "Erabili DVD bertsioko MPEG bideoa, bereizmen baxuagoko AVI-a beharrean"
#~ msgid "EGA undithering"
#~ msgstr "EGA lausotzea"
@@ -3738,6 +3809,3 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Roland GS modua gaitu"
-
-#~ msgid "Save game failed!"
-#~ msgstr "Partida gordeak huts egin du!"
diff --git a/po/fi_FI.po b/po/fi_FI.po
index f4a26a0429..a306d8e537 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.6.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2012-12-01 19:37+0200\n"
"Last-Translator: Toni Saarela <saarela@gmail.com>\n"
"Language-Team: Finnish\n"
@@ -594,16 +594,16 @@ msgid "Search:"
msgstr "Etsi:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Lataa peli:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Lataa"
@@ -773,7 +773,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Erityiset dithering asetukset joita jotkut pelit tukevat"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Kokoruututila"
@@ -1376,12 +1376,12 @@ msgstr ""
msgid "PC-9801 (16 Colors)"
msgstr ""
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr ""
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr ""
@@ -1434,11 +1434,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Palaa p~e~livalitsimeen"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Tallenna peli:"
@@ -1447,11 +1451,15 @@ msgstr "Tallenna peli:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Tallenna"
@@ -1777,19 +1785,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normaali (ei skaalausta)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Kuvasuhteen korjaus päällä"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Kuvasuhteen korjaus pois päältä"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Valittu grafiikkafiltteri:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Ikkunoitu tila"
@@ -2358,15 +2366,23 @@ msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Lataa pelitallenne:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Lataa tallenne"
@@ -2675,10 +2691,20 @@ msgstr ""
"Pelin tallennus kohtaan ei onnistunut kohtaan %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Lataa peli:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Ladataan peliä..."
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Tallenna peli:"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Tallennetaan peliä..."
@@ -3526,6 +3552,60 @@ msgid ""
"instruments from. Music will be disabled."
msgstr ""
+#: engines/sherlock/detection.cpp:71
+#, fuzzy
+msgid "Use original savegame dialog"
+msgstr "Käytä alkuperäisiä tallenna/lataa valikkoja"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+#, fuzzy
+msgid "Show character portraits"
+msgstr "Vaihda hahmoa"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
diff --git a/po/fr_FR.po b/po/fr_FR.po
index e1247dd4ef..e223a96a54 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-01-25 21:35-0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-20 23:17+0000\n"
"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n"
"Language-Team: French <scummvm-devel@lists.sf.net>\n"
"Language: Francais\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n>1;\n"
-"X-Generator: Poedit 1.6.6\n"
+"X-Generator: Poedit 1.8.6\n"
#: gui/about.cpp:94
#, c-format
@@ -591,16 +591,16 @@ msgid "Search:"
msgstr "Filtre :"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Charger le jeu :"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Charger"
@@ -765,7 +765,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Mode spécial de tramage supporté par certains jeux"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Plein écran"
@@ -1368,12 +1368,12 @@ msgstr "PC-9821 (256 couleurs)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 couleurs)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Vert"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Ambre"
@@ -1426,11 +1426,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Retour au ~L~anceur"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Sauvegarde :"
@@ -1439,11 +1443,15 @@ msgstr "Sauvegarde :"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Sauver"
@@ -1768,19 +1776,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Activer la correction du rapport d'aspect"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Désactiver la correction du rapport d'aspect"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Mode graphique actif:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Mode Fenêtre"
@@ -2350,15 +2358,23 @@ msgstr ""
"Activer le support de la souris. Cela permet d'utiliser la souris pour les "
"mouvements et la navigation dans les menus."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Charger le jeu :"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Charger"
@@ -2685,10 +2701,18 @@ msgstr ""
"Erreur lors de la sauvegarde dans l'emplacement %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Charger une partie"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Chargement en cours..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Sauver une partie"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Sauvegarde en cours..."
@@ -3537,6 +3561,66 @@ msgstr ""
"L'exécutable Macintosh de 'Monkey Island' n'a pas été trouvé pour\n"
"y lire les instruments. La musique sera désactivée."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Utiliser le dialogue de sauvegarde d'origine"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Le bouton Fichiers du jeu ouvre le dialogue de sauvegarde d'origine au lieu "
+"d'ouvrir celui de ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Transitions de scènes pixélisées"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+"Lors du changement de scène une transition avec des pixels aléatoires est "
+"utilisée"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Ne pas afficher les zones actives lors du déplacement de la souris"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Afficher le nom des zones actives uniquement après avoir cliqué sur la zone "
+"ou le bouton d'action"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Afficher le portrait des personnages"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Afficher le portrait des personnages lors des conversations"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Utiliser une transition pour les dialogues"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+"Utiliser une transition pour faire apparaître les dialogues au lieu de les "
+"afficher immédiatement"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Fenêtres transparentes"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Afficher les fenêtres avec un fond partiellement transparent"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3752,9 +3836,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Activer le mode Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "Échec de la sauvegarde!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Ajouter..."
diff --git a/po/gl_ES.po b/po/gl_ES.po
index 45408c5fc1..22b99fe2a7 100644
--- a/po/gl_ES.po
+++ b/po/gl_ES.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-02-02 09:10+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-21 00:43+0100\n"
"Last-Translator: Santiago G. Sanz <s.sanz@uvigo.es>\n"
"Language-Team: Santiago G. Sanz <s.sanz@uvigo.es>\n"
"Language: Galego\n"
@@ -589,16 +589,16 @@ msgid "Search:"
msgstr "Buscar:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Cargar partida:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Cargar"
@@ -761,7 +761,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Modos de interpolación de cores compatibles con algúns xogos"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Pantalla completa"
@@ -1357,12 +1357,12 @@ msgstr "PC-9821 (256 cores)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 cores)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules verde"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ámbar"
@@ -1413,11 +1413,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~V~olver ao Iniciador"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Gardar partida:"
@@ -1426,11 +1430,15 @@ msgstr "Gardar partida:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Gardar"
@@ -1755,19 +1763,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (sen escala)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Corrección de proporción activada"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Corrección de proporción desactivada"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Filtro de gráficos activo:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Modo en ventá"
@@ -2334,15 +2342,23 @@ msgstr ""
"Activa a compatibilidade co rato. Permite o uso do rato para o movemento e "
"os menús do xogo."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Restaurar xogo:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Restaurar"
@@ -2666,10 +2682,18 @@ msgstr ""
"Non se pode gardar a partida no espazo %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Cargar ficheiro"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Cargando..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Gardar ficheiro"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Gardando..."
@@ -3519,6 +3543,62 @@ msgstr ""
"Erro ao buscar o executable de Monkey Island para Macintosh\n"
"do que empregar os instrumentos. A música desactivarase."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Empregar pantalla orixinal de gardado"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"O botón de ficheiros do xogo mostra a pantalla orixinal de gardado no canto "
+"do menú de ScummVM."
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Transicións de escenas pixeladas"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Ao mudar de escena, mostrase una transición pixelada aleatoria."
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Non mostrar puntos de acceso ao mover o rato"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Só mostra os nomes dos puntos de acceso despois de premer nun punto de "
+"acceso ou un botón de acción."
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Mostrar retratos de personaxes"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Mostra os retratos dos personaxes nas conversas."
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Deslizar pantallas"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Desliza as pantallas da IU, no canto de mostralas directamente."
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Ventás transparentes"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Mostra ventás cun fondo parcialmente transparente."
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3541,7 +3621,7 @@ msgstr "Intro de disquete"
#: engines/sky/detection.cpp:45
msgid "Use the floppy version's intro (CD version only)"
-msgstr "Empregar a introdución da versión en disquete (só versión en CD)"
+msgstr "Emprega a introdución da versión en disquete (só versión en CD)."
#: engines/sword1/animation.cpp:524
#, c-format
@@ -3618,7 +3698,7 @@ msgstr "Mostrar etiquetas"
#: engines/sword2/sword2.cpp:80
msgid "Show labels for objects on mouse hover"
-msgstr "Mostrar as etiquetas dos obxectos ao apuntar co rato"
+msgstr "Mostra as etiquetas dos obxectos ao apuntar co rato."
#: engines/teenagent/resources.cpp:95
msgid ""
diff --git a/po/hu_HU.po b/po/hu_HU.po
index 35c4856975..02878f4fbc 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-01-27 06:57+0200\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-21 06:24+0200\n"
"Last-Translator: George Kormendi <grubycza@hotmail.com>\n"
"Language-Team: Hungarian\n"
"Language: Magyar\n"
@@ -588,16 +588,16 @@ msgid "Search:"
msgstr "Keresés:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Játék betöltése:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Betöltés"
@@ -761,7 +761,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Néhány játék támogatja a speciális árnyalási módokat"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Teljesképernyõs mód:"
@@ -1353,12 +1353,12 @@ msgstr "PC-9821 (256 Szín)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 Szín)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Zöld"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Sárga"
@@ -1409,11 +1409,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Visszatérés az indítóba"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Játék mentése:"
@@ -1422,11 +1426,15 @@ msgstr "Játék mentése:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Mentés"
@@ -1748,19 +1756,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normál (nincs átméretezés)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Méretarány korrekció engedélyezve"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Méretarány korrekció letiltva"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktív grafikus szûrõk:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Ablakos mód"
@@ -2324,15 +2332,23 @@ msgstr ""
"Egérmód engélyezve. Lehetõvé teszi az egérrel mozgatást játékban és "
"játékmenükben."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Játékmenet visszaállítása:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Visszaállítás"
@@ -2655,10 +2671,18 @@ msgstr ""
"Játékállás nem menthetõ %i slotba\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Fájl betöltése"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Játék betöltés..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Fájl mentése"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Játék mentés..."
@@ -3502,6 +3526,63 @@ msgstr ""
"Nem található a 'Monkey Island' Macintosh futtató állomány, hogy \n"
"beolvassa a hangszereket. Zene le lessz tiltva."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Eredeti játékmentés párbeszéd használata"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Fájl gomb a játékban, az eredeti játékmentés párbeszédet jeleníti meg a "
+"ScummVM-é helyett"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pixeles képátmenetek"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Helyszínek váltásánál, egy randomizált pixel átmenet történik"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Aktív pontok nem látszanak egérmozgatás közben"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Aktív pontok neve csak akkor látszik, ha ténylegesen rákattint vagy "
+"akciógombot nyom"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Karakter képe látható"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "A karakterek képe látható beszélgetés közben"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Párbeszéd csúsztatás nézet"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+"UI párbeszédek csúsztatása ahelyett, hogy egyszerûen megjelenítené azonnal"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Átlátszó ablakok"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Ablakok megjelenítése részben átlászó háttérrel"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3707,9 +3788,6 @@ msgstr "MPEG videót használ DVD verziónál, a kisebb felbontású AVI helyett"
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Roland GS Mód engedélyezve"
-#~ msgid "Save game failed!"
-#~ msgstr "Játék mentése nem sikerült!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Játék hozzáadás"
diff --git a/po/it_IT.po b/po/it_IT.po
index fb40057b41..880c0ca7df 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2014-07-03 17:59-0600\n"
"Last-Translator: Matteo 'Maff' Angelino <matteo.maff at gmail dot com>\n"
"Language-Team: Italian\n"
@@ -590,16 +590,16 @@ msgid "Search:"
msgstr "Cerca:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Carica gioco:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Carica"
@@ -768,7 +768,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Modalità di resa grafica speciali supportate da alcuni giochi"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Modalità a schermo intero"
@@ -1369,12 +1369,12 @@ msgstr ""
msgid "PC-9801 (16 Colors)"
msgstr ""
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules verde"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ambra"
@@ -1425,11 +1425,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~V~ai a elenco giochi"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Salva gioco:"
@@ -1438,11 +1442,15 @@ msgstr "Salva gioco:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Salva"
@@ -1772,19 +1780,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normale (no ridim.)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Correzione proporzioni attivata"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Correzione proporzioni disattivata"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Filtro grafico attivo:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Modalità finestra"
@@ -2351,15 +2359,23 @@ msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Ripristina gioco:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Ripristina"
@@ -2670,10 +2686,20 @@ msgstr ""
"Impossibile salvare nella posizione %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Carica gioco:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Caricamento..."
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Salvataggio fallito!"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Salvataggio..."
@@ -3526,6 +3552,60 @@ msgid ""
"instruments from. Music will be disabled."
msgstr ""
+#: engines/sherlock/detection.cpp:71
+#, fuzzy
+msgid "Use original savegame dialog"
+msgstr "Usa schermate di salvataggio originali"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+#, fuzzy
+msgid "Show character portraits"
+msgstr "Cambia personaggio"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3743,9 +3823,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Attiva la modalità Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "Salvataggio fallito!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Agg. gioco..."
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 0d778341ae..8f105c6d55 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-11 00:02+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-25 23:42+0100\n"
"Last-Translator: Einar Johan Trøan Sømåen <einarjohants@gmail.com>\n"
"Language-Team: somaen <einarjohants@gmail.com>\n"
"Language: Norsk (bokmaal)\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
-"X-Generator: Poedit 1.5.5\n"
+"X-Generator: Poedit 1.8.7\n"
#: gui/about.cpp:94
#, c-format
@@ -75,7 +75,7 @@ msgstr "Velg"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Forfatter:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -83,24 +83,23 @@ msgstr "Navn:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Notater:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "Ok"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Velg fil for lasting"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Skriv inn filnavn for lagring"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Vil du virkelig slette dette lagrede spillet?"
+msgstr "Vil du virkelig overskrive denne filen?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -132,7 +131,7 @@ msgstr "Aktiv"
#: gui/fluidsynth-dialog.cpp:72
msgid "Room:"
-msgstr ""
+msgstr "Rom:"
#: gui/fluidsynth-dialog.cpp:79
msgid "Damp:"
@@ -592,16 +591,16 @@ msgid "Search:"
msgstr "Søk:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Åpne spill:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Åpne"
@@ -678,21 +677,19 @@ msgstr ""
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Stopp"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
msgstr ""
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Bytt"
+msgstr "Bytt til Spill"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Rask modus"
+msgstr "Rask replay"
#: gui/options.cpp:85
msgid "Never"
@@ -769,7 +766,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Spesiel dithering-modus støttet av enkelte spill"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Fullskjermsmodus"
@@ -906,6 +903,8 @@ msgid ""
"Check if you want to enable patch mappings to emulate an MT-32 on a Roland "
"GS device"
msgstr ""
+"Aktiver hvis du vil slå på patch mappinger for å emulere en MT-32 eller "
+"Roland GS enhet"
#: gui/options.cpp:898
msgid "Don't use Roland MT-32 music"
@@ -1080,20 +1079,19 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# neste"
#: gui/predictivedialog.cpp:87
msgid "add"
msgstr ""
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Slett"
+msgstr ""
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
@@ -1103,12 +1101,12 @@ msgstr ""
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Tall"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
@@ -1124,33 +1122,30 @@ msgid "Record"
msgstr ""
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Spill"
+msgstr ""
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Rediger"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Forfatter: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Notater: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Vil du virkelig slette dette lagrede spillet?"
+msgstr ""
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Ukjent feil"
+msgstr "Ukjent Forfatter"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1357,18 +1352,18 @@ msgstr "Hercules Oransje"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 Farger)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 Farger)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Grønn"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Oransje"
@@ -1420,11 +1415,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~T~ilbake til oppstarter"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Lagret spill:"
@@ -1433,11 +1432,15 @@ msgstr "Lagret spill:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Lagre"
@@ -1555,7 +1558,7 @@ msgstr "DOSBox OPL emulator"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA Direct FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1612,17 +1615,15 @@ msgstr "Apple II GS Emulator (IKKE IMPLEMENTERT)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Creative Music System Emulator"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "FM Towns Emulator"
+msgstr "FM Towns Lyd"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Lyd"
+msgstr "PC-98 Lyd"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1717,34 +1718,33 @@ msgstr "Vil du avslutte?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Touchpad-modus deaktivert."
+msgstr "Trackpadmodus er nå"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "PÅ"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "AV"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Sveip to fingre til høyre for å slå av/på"
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Auto-dramodus er nå"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Sveip tre fingre til høyre for å veksle"
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1765,19 +1765,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (ingen skalering)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Aspekt-rate korrigering aktivert"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Aspekt-rate korrigering deaktivert"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktivt grafikkfilter:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Vindusmodus"
@@ -2039,24 +2039,23 @@ msgstr "Styr Mus"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Data ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Ressurser ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SDKort ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Media ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Delt Ressurs:"
+msgstr "[ Delt ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2323,35 +2322,44 @@ msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr "Bruk de originale lagre/laste-skjermene, istedenfor ScummVM-variantene"
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr "Bruk en alternativ intro (Kun for CD-versjon)"
+msgstr "Bruk en alternativ palett"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"Bruk en alternativ palett, fells for alle Amigaspill. Dette var den gamle "
+"oppførselen"
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Hopp over"
+msgstr "Musstøtte"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"Aktiver musstøtte. Tillater å bruke mus for bevegelse og i spillmenyer."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Gjennopprett spill:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Gjenopprett"
@@ -2394,13 +2402,12 @@ msgid "Cutscene file '%s' not found!"
msgstr "Fant ikke cutscenefil '%s'!"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Klikkmodus"
+msgstr "Fargeblindmodus"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Aktiver fargeblindmodus som standard"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2456,11 +2463,11 @@ msgstr "Klarte ikke å lagre spill."
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Gørrmodus"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Aktiver gørrmodus når tilgjengelig"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2474,9 +2481,8 @@ msgstr "Aktiver studiopublikum"
#. I18N: This option allows the user to skip text and cutscenes.
#: engines/kyra/detection.cpp:73
-#, fuzzy
msgid "Skip support"
-msgstr "Hopp over"
+msgstr "Hopp over-støtte"
#: engines/kyra/detection.cpp:74
msgid "Allow text and cutscenes to be skipped"
@@ -2593,6 +2599,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Det følgende originale lagrede spillet ble funnet i spillstien din:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Vil du bruke dette lagrede spillet med ScummVM?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2600,6 +2612,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"Et lagret spill ble funnet i den valgte posisjonen %d. Overskrive?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2611,6 +2625,10 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"%d originale lagrede spill har blitt importert vellykket til ScummVM.\n"
+"Hvis du vil importere flere originale lagrede spill senere, må du åpne\n"
+"ScummVM debugkonsollen og bruke kommandoen «import_savefile»\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2663,10 +2681,18 @@ msgstr ""
"Kan ikke lagre spilltilstand i posisjon %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Last fil"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Laster spill..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Lagre fil"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Lagrer spill..."
@@ -2750,21 +2776,19 @@ msgstr "Bruk en alternativ intro (Kun for CD-versjon)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Hopp over EGA dithering (fullfarge bakgrunner)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "Aktiver hit point-bar grafer"
+msgstr "Aktiver høyoppløselig grafikk"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "Aktiver hit point-bar grafer"
+msgstr "Aktiver høyoppløselig grafikk/innhold"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2836,15 +2860,13 @@ msgstr "Spill pauset. Trykk på MELLOMROMstasten for å fortsette."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Er du sikker på at du vil avslutte? (Y/N)"
+msgstr "Er du sikker på at du vil starte på nytt? (J/N)J"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
-msgstr "Er du sikker på at du vil avslutte? (Y/N)"
+msgstr "Er du sikker på at du vil avslutte? (J/N)J"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
@@ -3357,19 +3379,19 @@ msgstr ""
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Velg Tastatur/Mus-slåssing (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "* Tastaturslåssing er alltid på,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr " så til tross for beskjeden i spillet, vil"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr " dette faktisk slå musslåssing av/på"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3465,23 +3487,20 @@ msgid "Fly to lower right"
msgstr "Fly til nedre høyre"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Myk scrolling"
+msgstr ""
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
msgstr ""
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "Musikkvolum:"
+msgstr "Musikkvolum: "
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
-msgstr "Teksthastighet:"
+msgstr "Teksthastighet: "
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3493,27 +3512,86 @@ msgstr ""
"men %s mangler. Bruker AdLib istedet."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Vanligvis, ville Maniac Mansion ha startet nå. Men ScummVM støtter ikke det "
-"ennå. Så, for å spille Maniac Mansion, gå til 'Legg til spill' i ScummVM-"
-"hovedmenyen og velg 'Maniac'-undermappa i Tentacle-mappa."
+"Vanligvis, ville Maniac Mansion ha startet nå. Men for at det skal fungere "
+"må Maniac Mansion-filene ligge i «Maniac» mappa inni Tentacle-spillmappa, og "
+"spillet må være lagt til i ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Kunne ikke finne Macintosh binærfila «Loom» for å lese instrumenter\n"
+"fra den. Musikk vil bli deaktivert."
#: 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 ""
+"Kunne ikke finne Macintosh-binærfila «Monkey Island» for å lese\n"
+"instrumenter fra den. Musikk vil bli deaktivert."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Bruk original lagringsdialog"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"«Files»-knappen i spillet viser original lagre/laste-dialog istedenfor "
+"ScummVM menyen"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pikselerte sceneoverganger"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Under scenskifter vil en tilfeldig pikselovergang bli gjort"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Ikke vis hotspots når du beveger musa"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Vis hotspots først etter at du faktisk har klikket på en hotspot eller "
+"handlingsknapp"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Vis karakterportretter"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Vis portretter for karakterene når de snakker sammen"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Gjennomsiktige vinduer"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Vis vinduer med en delvis gjennomsiktig bakgrunn"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3625,52 +3703,52 @@ msgstr ""
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Vis FPS-teller"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
+"Vis det gjeldende antall bilder per sekund (FPS) i øvre venstre hjørne av "
+"skjermen"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Bruk de originale lagre/laste-skjermene, istedenfor ScummVM-variantene"
+msgstr ""
+"Bruk de originale lagre/laste-skjermene istedenfor ScummVM-grensesnittet"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Dobbel FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Øk bilderate fra 30 til 60 FPS"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Aktiver helium-modus"
+msgstr "Aktiver Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Aktiver helium-modus"
+msgstr "Aktiver Venus hjelpesystemet"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Deaktiver animasjoner under snuing"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Deaktiver animasjoner under snuing i panoramamodus"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Bruk høyoppløst MPEG-video"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
msgstr ""
-"Bruk det alternative settet med sølvmuspekere, istedenfor de normale gylne."
+"Bruk MPEG-video fra DVD-versjonen istedenfor AVI-versjonen med lavere "
+"oppløsning"
#~ msgid "EGA undithering"
#~ msgstr "EGA av-dithering"
@@ -3719,9 +3797,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Aktiver Roland GS-modus"
-#~ msgid "Save game failed!"
-#~ msgstr "Lagret spill:"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Legg til spill..."
diff --git a/po/nl_NL.po b/po/nl_NL.po
index 42becb84a6..99d1400b04 100644
--- a/po/nl_NL.po
+++ b/po/nl_NL.po
@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-02-02 12:05+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-21 13:05+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.6.10\n"
+"X-Generator: Poedit 1.8.7\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -594,16 +594,16 @@ msgid "Search:"
msgstr "Zoeken:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Laad spel:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Laden"
@@ -772,7 +772,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Speciale ditheringmodi die door sommige games ondersteund worden."
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Volledig-scherm modus"
@@ -1370,12 +1370,12 @@ msgstr "PC-9821 (256 Kleuren)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 Kleuren)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Groen"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Amber"
@@ -1427,11 +1427,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "S~t~artmenu"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Spel opslaan:"
@@ -1440,11 +1444,15 @@ msgstr "Spel opslaan:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Opslaan"
@@ -1772,19 +1780,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normaal (niet schalen)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Pixelverhoudingcorrectie ingeschakeld"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Pixelverhoudingcorrectie uitgeschakeld"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Actieve grafische filter:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Venstermodus"
@@ -1994,7 +2002,7 @@ msgstr "Meerdere Functies"
#: backends/platform/symbian/src/SymbianActions.cpp:48
msgid "Swap character"
-msgstr "Verwissel karakter"
+msgstr "Verwissel personage"
#: backends/platform/symbian/src/SymbianActions.cpp:49
msgid "Skip text"
@@ -2353,15 +2361,23 @@ msgstr ""
"Zet muis ondersteuning aan. Maakt het mogelijk om de muis te gebruiken voor "
"bewegen en in spelmenus."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Laad opgeslagen spel:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Laad"
@@ -2686,10 +2702,18 @@ msgstr ""
"Spel opslaan in slot %i mislukt\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Laad bestand"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Spel laden..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Bestand opslaan"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Spel opslaan..."
@@ -3366,7 +3390,7 @@ msgstr "Rechter middelste voorwerp"
#: engines/scumm/help.cpp:280 engines/scumm/help.cpp:285
msgid "Switching characters:"
-msgstr "Verwissel karakters:"
+msgstr "Verwissel personages:"
#: engines/scumm/help.cpp:282
msgid "Second kid"
@@ -3540,6 +3564,63 @@ msgstr ""
"De 'Monkey Island' Macintosh executable is niet gevonden om de instrumenten "
"van te laden. Muziek wordt uitgeschakeld."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Gebruik originele spel-opslaan schermen"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"In-game knop Files toont originele spel opslaan dialoogvenster in plaats van "
+"het ScummVM menu"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pixellated scèneovergangen"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+"Bij scene wijzigingen wordt er een willekeurig pixel transitie gebruikt"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Toon geen hotspots als de muis beweegt"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Toon alleen hotspots wanneer er daadwerkelijk op hotspot of actieknop "
+"geklikt word"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Toon personage portretfoto's"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Toon portretten van de personages bij het converseren"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Schuif dialoogvensters in beeld"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Schuif dialoogvensters in beeld, in plaats van onmiddellijk tonen"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Transparante vensters"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Toon vensters met een gedeeltelijk transparante achtergrond"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
diff --git a/po/nn_NO.po b/po/nn_NO.po
index b8cdd24cce..62f7c07beb 100644
--- a/po/nn_NO.po
+++ b/po/nn_NO.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-11 00:04+0100\n"
-"Last-Translator: Einar Johan Trøan Sømåen <einarjohants@gmail.com>\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-26 00:37+0100\n"
+"Last-Translator: Einar Johan Trøan Sømåen <einarjohants@gmail.com>\n"
"Language-Team: somaen <einarjohants@gmail.com>\n"
"Language: Norsk (nynorsk)\n"
"MIME-Version: 1.0\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 1.5.5\n"
+"X-Generator: Poedit 1.8.7\n"
#: gui/about.cpp:94
#, c-format
@@ -75,7 +75,7 @@ msgstr "Vel"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Forfattar:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -83,24 +83,23 @@ msgstr "Namn:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Notatar:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "Ok"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Vel fil for lasting"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Skriv inn filnamn for lagring"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Vil du verkeleg slette det lagra spelet?"
+msgstr "Vil du verkeleg overskrive fila?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -132,7 +131,7 @@ msgstr "Aktiv"
#: gui/fluidsynth-dialog.cpp:72
msgid "Room:"
-msgstr ""
+msgstr "Rom:"
#: gui/fluidsynth-dialog.cpp:79
msgid "Damp:"
@@ -226,10 +225,10 @@ msgid "OK"
msgstr "OK"
#: gui/fluidsynth-dialog.cpp:217
-#, fuzzy
msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
-msgstr "Vil du verkeleg slette det lagra spelet?"
+msgstr ""
+"Vil du verkeleg sette alle FluidSynth-innstillingar til standardverdiar?"
#: gui/gui-manager.cpp:119 backends/keymapper/remap-dialog.cpp:53
#: engines/scumm/help.cpp:126 engines/scumm/help.cpp:141
@@ -447,7 +446,7 @@ msgstr "Ekstrasti:"
#: gui/launcher.cpp:330 gui/launcher.cpp:332 gui/launcher.cpp:333
msgid "Specifies path to additional data used by the game"
-msgstr ""
+msgstr "Veljer sti til tilleggsdata nytta av spelet"
#: gui/launcher.cpp:332 gui/options.cpp:1150
msgctxt "lowres"
@@ -461,7 +460,7 @@ msgstr "Lagringssti:"
#: gui/launcher.cpp:339 gui/launcher.cpp:341 gui/launcher.cpp:342
#: gui/options.cpp:1132 gui/options.cpp:1134 gui/options.cpp:1135
msgid "Specifies where your saved games are put"
-msgstr ""
+msgstr "Veljer kor lagra spel vert lagra"
#: gui/launcher.cpp:341 gui/options.cpp:1134
msgctxt "lowres"
@@ -493,9 +492,8 @@ msgid "Select directory with game data"
msgstr "Vel mappe med speldata"
#: gui/launcher.cpp:547
-#, fuzzy
msgid "Select additional game directory"
-msgstr "Vel mappe med speldata"
+msgstr "Vel mappe med tileggsdata for spelet"
#: gui/launcher.cpp:559 gui/options.cpp:1377
msgid "Select directory for saved games"
@@ -503,7 +501,7 @@ msgstr "Vel mappe for lagra spel"
#: gui/launcher.cpp:586
msgid "This game ID is already taken. Please choose another one."
-msgstr ""
+msgstr "Denne spel-IDen er allerede teken. Vær vennleg og vel ein anna."
#: gui/launcher.cpp:626 engines/dialogs.cpp:111
msgid "~Q~uit"
@@ -567,7 +565,7 @@ msgstr "~F~jern spel"
#: gui/launcher.cpp:642 gui/launcher.cpp:649
msgid "Remove game from the list. The game data files stay intact"
-msgstr ""
+msgstr "Fjern spel frå lista. Speldataene forblir intakte"
#: gui/launcher.cpp:645
msgctxt "lowres"
@@ -593,16 +591,16 @@ msgid "Search:"
msgstr "Søk:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Åpne spel:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Åpne"
@@ -670,27 +668,26 @@ msgid "Scanned %d directories ..."
msgstr "Søkt i %d mappar ..."
#: gui/massadd.cpp:269
-#, fuzzy, c-format
+#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
-msgstr "Oppdaga %d nye spel ..."
+msgstr ""
+"Oppdaga %d nye spel, ignorerte %d spel som har vorte lagt til tidlegare..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Stopp"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
msgstr ""
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Bytt"
+msgstr "Bytt til spel"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Rask modus"
+msgstr ""
#: gui/options.cpp:85
msgid "Never"
@@ -740,7 +737,7 @@ msgstr "Ingen"
#: gui/options.cpp:389
msgid "Failed to apply some of the graphic options changes:"
-msgstr ""
+msgstr "Klarte ikkje å aktivere nokre av grafikkvalendringane:"
#: gui/options.cpp:401
msgid "the video mode could not be changed."
@@ -752,7 +749,7 @@ msgstr "Fullskjerminstillinga kunne ikkje endrast"
#: gui/options.cpp:413
msgid "the aspect ratio setting could not be changed"
-msgstr ""
+msgstr "aspektrate-innstillinga kunne ikkje endrast"
#: gui/options.cpp:732
msgid "Graphics mode:"
@@ -767,7 +764,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Spesielle dithering-modus som støttast av nokre spel"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Fullskjermsmodus"
@@ -796,16 +793,14 @@ msgid "Specifies output sound device or sound card emulator"
msgstr ""
#: gui/options.cpp:771
-#, fuzzy
msgctxt "lowres"
msgid "Preferred Dev.:"
-msgstr "Føretrukken eining:"
+msgstr ""
#: gui/options.cpp:771
-#, fuzzy
msgctxt "lowres"
msgid "Music Device:"
-msgstr "Ingen musikk"
+msgstr "Musikkeining:"
#: gui/options.cpp:798
msgid "AdLib emulator:"
@@ -833,7 +828,7 @@ msgstr "GM Eining:"
#: gui/options.cpp:820
msgid "Specifies default sound device for General MIDI output"
-msgstr ""
+msgstr "Veljer standard lydeining for General MIDI avspeling"
#: gui/options.cpp:831
msgid "Don't use General MIDI music"
@@ -878,7 +873,7 @@ msgstr "MT-32 Eining:"
#: gui/options.cpp:879
msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
-msgstr ""
+msgstr "Veljer standard lydeining for Roland MT-32/LAPC1/CM32l/CM64 avspeling"
#: gui/options.cpp:884
msgid "True Roland MT-32 (disable GM emulation)"
@@ -889,6 +884,8 @@ msgid ""
"Check if you want to use your real hardware Roland-compatible sound device "
"connected to your computer"
msgstr ""
+"Vel om du vil nytte din Roland-kompatible lydeining som du har tilkopla "
+"datamaskina di."
#: gui/options.cpp:886
msgctxt "lowres"
@@ -896,9 +893,8 @@ msgid "True Roland MT-32 (no GM emulation)"
msgstr "Ekte Roland MT-32 (ingen GS-emulering)"
#: gui/options.cpp:889
-#, fuzzy
msgid "Roland GS Device (enable MT-32 mappings)"
-msgstr "Ekte Roland MT-32 (deaktiver GM-emulering)"
+msgstr ""
#: gui/options.cpp:889
msgid ""
@@ -976,7 +972,7 @@ msgstr "Lydeffektvolum:"
#: gui/options.cpp:971 gui/options.cpp:973 gui/options.cpp:974
msgid "Special sound effects volume"
-msgstr ""
+msgstr "Spesiallydeffekt volum"
#: gui/options.cpp:973
msgctxt "lowres"
@@ -1079,20 +1075,19 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# neste"
#: gui/predictivedialog.cpp:87
msgid "add"
msgstr ""
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Slett"
+msgstr ""
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
@@ -1102,12 +1097,12 @@ msgstr ""
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Tal"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
@@ -1123,33 +1118,30 @@ msgid "Record"
msgstr ""
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Spel"
+msgstr ""
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Rediger"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Forfattar: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Notatar: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Vil du verkeleg slette det lagra spelet?"
+msgstr ""
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Ukjend feil"
+msgstr "Ukjend Forfattar"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1339,7 +1331,7 @@ msgstr "Spelmotor-plugin støttar ikkje lagra tilstandar."
#: common/error.cpp:71
msgid "User canceled"
-msgstr ""
+msgstr "Brukar avbraut"
#: common/error.cpp:75
msgid "Unknown error"
@@ -1356,18 +1348,18 @@ msgstr "Hercules Raudgul"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 Fargar)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 Fargar)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Grønn"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Raudgul"
@@ -1419,11 +1411,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Tilbake til Oppsta~r~tar"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Lagra spel:"
@@ -1432,11 +1428,15 @@ msgstr "Lagra spel:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Lagre"
@@ -1446,6 +1446,9 @@ msgid ""
"the README for basic information, and for instructions on how to obtain "
"further assistance."
msgstr ""
+"Orsak, men denne spelmotoren støtter for augeblikket ikkje hjelp i spelet. "
+"Vennlegst se i README-fila for grunnlegjande informasjon, og for "
+"instruksjonar om korleis du kan få ytterlegare hjelp."
#: engines/dialogs.cpp:234 engines/pegasus/pegasus.cpp:393
#, c-format
@@ -1453,6 +1456,9 @@ msgid ""
"Gamestate save failed (%s)! Please consult the README for basic information, "
"and for instructions on how to obtain further assistance."
msgstr ""
+"Speltilstandslagring feila (%s)!. Vennligst sjå i README-fila for "
+"grunnlegjande informasjon, og for instruskjonar om korleis du kan få "
+"ytterlegare hjelp."
#: engines/dialogs.cpp:307 engines/mohawk/dialogs.cpp:109
#: engines/mohawk/dialogs.cpp:170 engines/tsage/dialogs.cpp:106
@@ -1470,20 +1476,19 @@ msgstr "~T~astar"
#: engines/engine.cpp:339
msgid "Could not initialize color format."
-msgstr ""
+msgstr "Høgkvalitetslyd (treigare) (omstart)"
#: engines/engine.cpp:347
msgid "Could not switch to video mode: '"
msgstr "Kunne ikkje veksle til videomodus: '"
#: engines/engine.cpp:356
-#, fuzzy
msgid "Could not apply aspect ratio setting."
-msgstr "Veksle aspekt-korrigering"
+msgstr "Kunne ikkje slå på aspekt-korrigering"
#: engines/engine.cpp:361
msgid "Could not apply fullscreen setting."
-msgstr ""
+msgstr "Kunne ikkje aktiver fullskjermsinnstilling."
#: engines/engine.cpp:461
msgid ""
@@ -1493,6 +1498,11 @@ msgid ""
"the data files to your hard disk instead.\n"
"See the README file for details."
msgstr ""
+"Det ser ut til at du speler dette spelet rett frå\n"
+"CD. Dette er kjend for å skape problemar,\n"
+"og det er derfor tilråda at du kopierar\n"
+"datafilane til harddisken din istaden. \n"
+"Sjå README-fila for detaljar."
#: engines/engine.cpp:472
msgid ""
@@ -1509,6 +1519,9 @@ msgid ""
"Gamestate load failed (%s)! Please consult the README for basic information, "
"and for instructions on how to obtain further assistance."
msgstr ""
+"Speltilstandslasting feila (%s)!. Vennligst sjå i README-fila for "
+"grunnlegjande informasjon, og for instruskjonar om korleis du kan få "
+"ytterlegare hjelp."
#: engines/engine.cpp:543
msgid ""
@@ -1538,7 +1551,7 @@ msgstr "DOSBox OPL emulator"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA Direct FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1546,11 +1559,13 @@ msgid ""
"The selected audio device '%s' was not found (e.g. might be turned off or "
"disconnected)."
msgstr ""
+"Den valde lydeininga '%s' vart ikkje funne (t.d. kan den vere avslått eller "
+"fråkopla)"
#: audio/mididrv.cpp:209 audio/mididrv.cpp:221 audio/mididrv.cpp:257
#: audio/mididrv.cpp:272
msgid "Attempting to fall back to the next available device..."
-msgstr ""
+msgstr "Prøver å nytte den neste tilgjengelege eininga..."
#: audio/mididrv.cpp:221
#, c-format
@@ -1558,6 +1573,8 @@ msgid ""
"The selected audio device '%s' cannot be used. See log file for more "
"information."
msgstr ""
+"Den foretrukne lydeininga '%s' kan ikkje nyttast. Sjå loggfila for meir "
+"informasjon."
#: audio/mididrv.cpp:257
#, c-format
@@ -1565,6 +1582,8 @@ msgid ""
"The preferred audio device '%s' was not found (e.g. might be turned off or "
"disconnected)."
msgstr ""
+"Den foretrukne lydeininga '%s' vart ikkje funne (t.d. kan den vere avslått "
+"eller fråkopla)"
#: audio/mididrv.cpp:272
#, c-format
@@ -1572,6 +1591,8 @@ msgid ""
"The preferred audio device '%s' cannot be used. See log file for more "
"information."
msgstr ""
+"Den foretrukne lydeininga '%s' kan ikkje nyttast. Sjå loggfila for meir "
+"informasjon."
#: audio/mods/paula.cpp:196
msgid "Amiga Audio Emulator"
@@ -1587,22 +1608,19 @@ msgstr "Apple II GS Emulator (IKKJE IMPLEMENTERT)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Creative Music System Emulator"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "FM Towns Emulator"
+msgstr "FM-Towns Lyd"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Lyd"
+msgstr "PC-98 Lyd"
#: audio/softsynth/mt32.cpp:200
-#, fuzzy
msgid "Initializing MT-32 Emulator"
-msgstr "MT-32 Emulator"
+msgstr "Initialiserar MT-32 Emulator"
#: audio/softsynth/mt32.cpp:426
msgid "MT-32 Emulator"
@@ -1644,16 +1662,14 @@ msgstr "Avslutt"
#: backends/events/gph/gph-events.cpp:385
#: backends/events/gph/gph-events.cpp:428
#: backends/events/openpandora/op-events.cpp:168
-#, fuzzy
msgid "Touchscreen 'Tap Mode' - Left Click"
-msgstr "Tap for venstre-klikk, dobbelt-tap for høgre-klikk"
+msgstr "Touchscreen 'Tap Mode' - Venstreklikk"
#: backends/events/gph/gph-events.cpp:387
#: backends/events/gph/gph-events.cpp:430
#: backends/events/openpandora/op-events.cpp:170
-#, fuzzy
msgid "Touchscreen 'Tap Mode' - Right Click"
-msgstr "Tap for venstre-klikk, dobbelt-tap for høgre-klikk"
+msgstr "Touchscreen 'Tap Mode' - Høgreklikk"
#: backends/events/gph/gph-events.cpp:389
#: backends/events/gph/gph-events.cpp:432
@@ -1666,24 +1682,20 @@ msgid "Maximum Volume"
msgstr "Maks Volum"
#: backends/events/gph/gph-events.cpp:411
-#, fuzzy
msgid "Increasing Volume"
-msgstr "Volum"
+msgstr "Auker Volum"
#: backends/events/gph/gph-events.cpp:417
-#, fuzzy
msgid "Minimal Volume"
-msgstr "Volum"
+msgstr "Minste Volum"
#: backends/events/gph/gph-events.cpp:419
-#, fuzzy
msgid "Decreasing Volume"
-msgstr "Volum"
+msgstr "Senkar Volum"
#: backends/events/maemosdl/maemosdl-events.cpp:180
-#, fuzzy
msgid "Clicking Enabled"
-msgstr "~O~vergangar aktivert"
+msgstr "Klikking aktivert"
#: backends/events/maemosdl/maemosdl-events.cpp:180
msgid "Clicking Disabled"
@@ -1699,21 +1711,20 @@ msgstr "Vil du avslutte?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Deaktivert GFX"
+msgstr "Trackpadmodus er no"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "PÅ"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "AV"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
@@ -1726,7 +1737,7 @@ msgstr ""
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Sveip tre fingre til høgre for å veksle"
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1747,21 +1758,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (ikkje skaler)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
-#, fuzzy
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
-msgstr "Aspekt-korrigering"
+msgstr "Aspekt-korrigering aktivert"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
-#, fuzzy
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
-msgstr "Aspekt-korrigering"
+msgstr "Aspekt-korrigering ikkje aktivert"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktivt grafikkfilter:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Vindusmodus"
@@ -1770,9 +1779,8 @@ msgid "Keymap:"
msgstr "Tastkopling:"
#: backends/keymapper/remap-dialog.cpp:67
-#, fuzzy
msgid " (Effective)"
-msgstr " (Aktivt)"
+msgstr ""
#: backends/keymapper/remap-dialog.cpp:107
msgid " (Active)"
@@ -1886,16 +1894,14 @@ msgstr ""
#: backends/platform/ios7/ios7_osys_events.cpp:322
#: backends/platform/ios7/ios7_osys_events.cpp:540
#: backends/platform/iphone/osys_events.cpp:313
-#, fuzzy
msgid "Touchpad mode enabled."
-msgstr "~O~vergangar aktivert"
+msgstr "Touchpadmodus påslått."
#: backends/platform/ios7/ios7_osys_events.cpp:324
#: backends/platform/ios7/ios7_osys_events.cpp:542
#: backends/platform/iphone/osys_events.cpp:315
-#, fuzzy
msgid "Touchpad mode disabled."
-msgstr "Deaktivert GFX"
+msgstr "Touchpadmodus avslått."
#: backends/platform/maemo/maemo.cpp:208
msgid "Click Mode"
@@ -1970,16 +1976,15 @@ msgstr "Sone"
#: backends/platform/wince/CEActionsPocket.cpp:54
#: backends/platform/wince/CEActionsSmartphone.cpp:48
msgid "Multi Function"
-msgstr ""
+msgstr "Multifunksjon"
#: backends/platform/symbian/src/SymbianActions.cpp:48
msgid "Swap character"
-msgstr ""
+msgstr "Bytt karakter"
#: backends/platform/symbian/src/SymbianActions.cpp:49
-#, fuzzy
msgid "Skip text"
-msgstr "Hopp over tekstlinje"
+msgstr "Hopp over tekst"
#: backends/platform/symbian/src/SymbianActions.cpp:51
msgid "Fast mode"
@@ -2002,14 +2007,12 @@ msgid "Key mapper"
msgstr "Tastkopler"
#: backends/platform/tizen/form.cpp:263
-#, fuzzy
msgid "Right Click Once"
-msgstr "Høgreklikk"
+msgstr "Høgreklikk ein gong"
#: backends/platform/tizen/form.cpp:271
-#, fuzzy
msgid "Move Only"
-msgstr "Tale"
+msgstr ""
#: backends/platform/tizen/form.cpp:294
msgid "Escape Key"
@@ -2024,30 +2027,28 @@ msgid "Show Keypad"
msgstr "Syn taltastatur"
#: backends/platform/tizen/form.cpp:309
-#, fuzzy
msgid "Control Mouse"
-msgstr "Musklikk"
+msgstr ""
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Data ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Ressursar ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SDKort ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Media ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr ", delt ressurs ikkje montert"
+msgstr "[ Delt ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2074,9 +2075,8 @@ msgid "Input"
msgstr "Input"
#: backends/platform/wii/options.cpp:74
-#, fuzzy
msgid "GC Pad sensitivity:"
-msgstr "Sensitivitet"
+msgstr "GC Pad Sensitivitet"
#: backends/platform/wii/options.cpp:80
msgid "GC Pad acceleration:"
@@ -2111,9 +2111,8 @@ msgid "Server:"
msgstr "Teinar:"
#: backends/platform/wii/options.cpp:110
-#, fuzzy
msgid "Share:"
-msgstr ", delt ressurs ikkje montert"
+msgstr "Delt:"
#: backends/platform/wii/options.cpp:114
msgid "Username:"
@@ -2156,9 +2155,8 @@ msgid "Network up"
msgstr "Nettverket er oppe"
#: backends/platform/wii/options.cpp:166
-#, fuzzy
msgid ", error while mounting the share"
-msgstr "Feil under montering av DVD"
+msgstr ", feil under montering av delt ressurs"
#: backends/platform/wii/options.cpp:168
msgid ", share not mounted"
@@ -2169,19 +2167,17 @@ msgid "Network down"
msgstr "Nettverket er nede"
#: backends/platform/wii/options.cpp:178
-#, fuzzy
msgid "Initializing network"
-msgstr "Init nettverk"
+msgstr "Initialiserar nettverk"
#: backends/platform/wii/options.cpp:182
-#, fuzzy
msgid "Timeout while initializing network"
-msgstr "Initialiserer nettverk"
+msgstr ""
#: backends/platform/wii/options.cpp:186
-#, fuzzy, c-format
+#, c-format
msgid "Network not initialized (%d)"
-msgstr "Init nettverk"
+msgstr "Nettverk ikkje initialisert (%d)"
#: backends/platform/wince/CEActionsPocket.cpp:46
msgid "Hide Toolbar"
@@ -2317,9 +2313,8 @@ msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr ""
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr "Nytt diskettversjonens åpning (Kun CD-versjon)"
+msgstr "Nytt ein alternativ palett"
#: engines/agi/detection.cpp:158
msgid ""
@@ -2328,24 +2323,31 @@ msgid ""
msgstr ""
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Hopp over"
+msgstr "Musstøtte"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Gjenopprett spel:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Gjenopprett"
@@ -2379,13 +2381,12 @@ msgid "Cutscene file '%s' not found!"
msgstr ""
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Klikkmodus"
+msgstr "Fargeblindmodus"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Slå på fargeblindmodus som standard"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2397,11 +2398,17 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
+"ScummVM oppdaga at du har gamle spellagringar for Drascula som vi kan "
+"konvertere.\n"
+"Det gamle spellagringsformatet er ikkje lenger støtta, så du vil ikkje vere "
+"i stand til å laste dei om du ikkje konverterar dei\n"
+"\n"
+"Trykk OK for å konvertere dei no, ellers kjem du til å verte spurt neste "
+"gong du startar spelet.\n"
#: engines/dreamweb/detection.cpp:57
-#, fuzzy
msgid "Use bright palette mode"
-msgstr "Øvre høgre gjenstand"
+msgstr "Nytt lys palett-modus"
#: engines/dreamweb/detection.cpp:58
msgid "Display graphics using the game's bright palette"
@@ -2422,26 +2429,24 @@ msgid "Failed to delete file."
msgstr "Klarte ikkje slette fil."
#: engines/groovie/detection.cpp:312
-#, fuzzy
msgid "Fast movie speed"
-msgstr "Rask modus"
+msgstr "Rask filmfart"
#: engines/groovie/detection.cpp:313
msgid "Play movies at an increased speed"
msgstr "Spel filmar med auka hastighet"
#: engines/groovie/script.cpp:408
-#, fuzzy
msgid "Failed to save game"
-msgstr "Lagra spel:"
+msgstr "Klarte ikkje lagre spel"
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Gørrmodus"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Slå på gørrmodus når tilgjengeleg"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2455,46 +2460,42 @@ msgstr "Aktiver studiopublikum"
#. I18N: This option allows the user to skip text and cutscenes.
#: engines/kyra/detection.cpp:73
-#, fuzzy
msgid "Skip support"
-msgstr "Hopp over"
+msgstr "Hopp over-støtte"
#: engines/kyra/detection.cpp:74
msgid "Allow text and cutscenes to be skipped"
-msgstr ""
+msgstr "Tillat å hoppe over tekst og cutscenes"
#. I18N: Helium mode makes people sound like they've inhaled Helium.
#: engines/kyra/detection.cpp:84
-#, fuzzy
msgid "Helium mode"
-msgstr "Grafikkmodus:"
+msgstr "Heliummodus"
#: engines/kyra/detection.cpp:85
-#, fuzzy
msgid "Enable helium mode"
-msgstr "Grafikkmodus:"
+msgstr "Slå på heliummodus"
#. I18N: When enabled, this option makes scrolling smoother when
#. changing from one screen to another.
#: engines/kyra/detection.cpp:99
msgid "Smooth scrolling"
-msgstr ""
+msgstr "Mjuk rulling"
#: engines/kyra/detection.cpp:100
msgid "Enable smooth scrolling when walking"
-msgstr ""
+msgstr "Slå på mjuk rulling under gåing"
#. I18N: When enabled, this option changes the cursor when it floats to the
#. edge of the screen to a directional arrow. The player can then click to
#. walk towards that direction.
#: engines/kyra/detection.cpp:112
-#, fuzzy
msgid "Floating cursors"
-msgstr "Vanleg peikar"
+msgstr "Flytande peikarar"
#: engines/kyra/detection.cpp:113
msgid "Enable floating cursors"
-msgstr ""
+msgstr "Slå på flytande peikarar"
#. I18N: HP stands for Hit Points
#: engines/kyra/detection.cpp:127
@@ -2506,61 +2507,52 @@ msgid "Enable hit point bar graphs"
msgstr ""
#: engines/kyra/lol.cpp:478
-#, fuzzy
msgid "Attack 1"
-msgstr "byttast 7, 4, og 1 med"
+msgstr "Åtak 1"
#: engines/kyra/lol.cpp:479
msgid "Attack 2"
-msgstr ""
+msgstr "Åtak 2"
#: engines/kyra/lol.cpp:480
-#, fuzzy
msgid "Attack 3"
-msgstr "9, 6, og 3, henhaldsvis."
+msgstr "Åtak 3"
#: engines/kyra/lol.cpp:481
msgid "Move Forward"
-msgstr ""
+msgstr "Beveg Framover"
#: engines/kyra/lol.cpp:482
-#, fuzzy
msgid "Move Back"
-msgstr "Bakoversteg"
+msgstr "Beveg Bakover"
#: engines/kyra/lol.cpp:483
-#, fuzzy
msgid "Slide Left"
-msgstr "Venstre"
+msgstr "Skli til Venstre"
#: engines/kyra/lol.cpp:484
-#, fuzzy
msgid "Slide Right"
-msgstr "Høgre"
+msgstr "Skli til Høyre"
#: engines/kyra/lol.cpp:485 engines/pegasus/pegasus.cpp:2509
-#, fuzzy
msgid "Turn Left"
-msgstr "Slå på"
+msgstr "Snu til Venstre"
#: engines/kyra/lol.cpp:486 engines/pegasus/pegasus.cpp:2510
-#, fuzzy
msgid "Turn Right"
-msgstr "Slå på"
+msgstr "Snu til Høyre"
#: engines/kyra/lol.cpp:487
-#, fuzzy
msgid "Rest"
-msgstr "Gjenopprett"
+msgstr "Kvil"
#: engines/kyra/lol.cpp:488
msgid "Options"
msgstr "Val"
#: engines/kyra/lol.cpp:489
-#, fuzzy
msgid "Choose Spell"
-msgstr "Vel"
+msgstr ""
#: engines/kyra/sound_midi.cpp:477
msgid ""
@@ -2611,9 +2603,8 @@ msgstr "~O~vergangar aktivert"
#. I18N: Drop book page
#: engines/mohawk/dialogs.cpp:95
-#, fuzzy
msgid "~D~rop Page"
-msgstr "Søkt i %d mappar ..."
+msgstr ""
#: engines/mohawk/dialogs.cpp:99
msgid "~S~how Map"
@@ -2652,10 +2643,18 @@ msgstr ""
"Kan ikkje lagre spel i spor %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Last fil:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Lastar spel..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Lagra fil:"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Lagrar spel..."
@@ -2691,9 +2690,8 @@ msgid "Up/Zoom In/Move Forward/Open Doors"
msgstr ""
#: engines/pegasus/pegasus.cpp:2508
-#, fuzzy
msgid "Down/Zoom Out"
-msgstr "Zoom ned"
+msgstr "Ned/Zoom Ut"
#: engines/pegasus/pegasus.cpp:2511
msgid "Display/Hide Inventory Tray"
@@ -2704,9 +2702,8 @@ msgid "Display/Hide Biochip Tray"
msgstr ""
#: engines/pegasus/pegasus.cpp:2513
-#, fuzzy
msgid "Action/Select"
-msgstr "Vel ei handling, og klikk 'Kople'"
+msgstr "Handling/Vel"
#: engines/pegasus/pegasus.cpp:2514
msgid "Toggle Center Data Display"
@@ -2722,12 +2719,11 @@ msgstr "Skjul/Vis pausemeny"
#: engines/queen/detection.cpp:56
msgid "Alternative intro"
-msgstr ""
+msgstr "Alternativ intro"
#: engines/queen/detection.cpp:57
-#, fuzzy
msgid "Use an alternative game intro (CD version only)"
-msgstr "Nytt diskettversjonens åpning (Kun CD-versjon)"
+msgstr "Nytt alternativ spillåpning (Kun CD-versjon)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
@@ -2739,11 +2735,11 @@ msgstr ""
#: engines/sci/detection.cpp:384
msgid "Enable high resolution graphics"
-msgstr ""
+msgstr "Nytt høgoppløyseleg grafikk"
#: engines/sci/detection.cpp:385
msgid "Enable high resolution graphics/content"
-msgstr ""
+msgstr "Nytt høgoppløyseleg grafikk/innhald"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2762,6 +2758,8 @@ msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
+"Nytt eit IBM Music Feature-kort eller ein Yamaha FB-01 FM synth modul for "
+"MIDI avspeling"
#: engines/sci/detection.cpp:425
msgid "Use CD audio"
@@ -2792,7 +2790,7 @@ msgstr "Nytt det alternative settet med sølvpeikarar, istaden for dei gylne"
#: engines/scumm/dialogs.cpp:176
#, c-format
msgid "Insert Disk %c and Press Button to Continue."
-msgstr ""
+msgstr "Sett inn disk %c og trykk på knappen for å fortsette."
#: engines/scumm/dialogs.cpp:177
#, c-format
@@ -2812,33 +2810,29 @@ msgstr "Spelet er pausa. Trykk MELLOMROM for å fortsette."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Er du sikker på at du vil starte på nytt (Y/N)?"
+msgstr "Er du sikker på at du vil starte på nytt (J/N)J"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
-msgstr "Er du sikker på at du vil avslutte (Y/N)?"
+msgstr "Er du sikker på at du vil avslutte (J/N)J"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
msgstr "Spel"
#: engines/scumm/dialogs.cpp:194
-#, fuzzy
msgid "Insert save/load game disk"
-msgstr "Vil du åpne eller lagre spelet?"
+msgstr "Sett in lagre/laste speldisk"
#: engines/scumm/dialogs.cpp:195
msgid "You must enter a name"
msgstr "Du må skrive eit namn"
#: engines/scumm/dialogs.cpp:196
-#, fuzzy
msgid "The game was NOT saved (disk full?)"
-msgstr "Full speltittel:"
+msgstr "Spelet vart IKKJE lagra (full disk?)"
#: engines/scumm/dialogs.cpp:197
msgid "The game was NOT loaded"
@@ -2894,9 +2888,8 @@ msgid "Speech & Subs"
msgstr "Tekst & Tale"
#: engines/scumm/dialogs.cpp:658
-#, fuzzy
msgid "Select a Proficiency Level."
-msgstr "Gå til forrige mappenivå"
+msgstr ""
#: engines/scumm/dialogs.cpp:660
msgid "Refer to your Loom(TM) manual for help."
@@ -2904,7 +2897,7 @@ msgstr "Sjå i Loom(TM)-manualen for hjelp."
#: engines/scumm/dialogs.cpp:664
msgid "Practice"
-msgstr ""
+msgstr "Øving"
#: engines/scumm/dialogs.cpp:665
msgid "Expert"
@@ -3037,9 +3030,8 @@ msgid " since they may cause crashes"
msgstr " dei kan forårsake kræsj og"
#: engines/scumm/help.cpp:111
-#, fuzzy
msgid " or incorrect game behavior."
-msgstr "Spel"
+msgstr " eller feilaktig speloppførsel."
#: engines/scumm/help.cpp:115
msgid "Spinning drafts on the keyboard:"
@@ -3445,23 +3437,20 @@ msgid "Fly to lower right"
msgstr "Fly til nedre høgre"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Bla liste ned"
+msgstr ""
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
msgstr ""
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
msgstr "Musikkvolum:"
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
-msgstr "Undertekstfart:"
+msgstr "Subtitle speed: "
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3471,27 +3460,82 @@ msgid ""
msgstr ""
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Opprinneleg, skulle Maniac Mansion ha starta no. Men ScummVM støttar ikkje "
-"det enno. For å spele Maniac Mansion, gå til 'Legg til spel' i ScummVM-"
-"menyen og vel 'Maniac'-undermappa i 'Tentacle'-mappa."
+"Opprinneleg, skulle Maniac Mansion ha starta no. Men for at det skal virke "
+"må du ha datafilane til Maniac Mansion i «Maniac»-mappa inni «Tentacle»-"
+"spelmappa, og spelet må vere lagt til i ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Kunne ikkje finne Macintosh-binærfila «Loom» for å lese\n"
+"instrumenter frå den. Musikk vert deaktivert."
#: 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 ""
+"Kunne ikkje finne Macintosh-binærfila «Monkey Island» for å lese\n"
+"instrumentar frå den. Musikk vert deaktivert."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Nytt opprinnelege skjerm for lagring/lasting"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pikselerte sceneovergangar"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Syn karakterportrettar"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Gjennomsiktige vindauge"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
#: engines/sky/compact.cpp:130
msgid ""
@@ -3518,21 +3562,21 @@ msgstr "Nytt diskettversjonens åpning (Kun CD-versjon)"
#: engines/sword1/animation.cpp:524
#, c-format
msgid "PSX stream cutscene '%s' cannot be played in paletted mode"
-msgstr ""
+msgstr "PSX strømme cutscene '%s' kan ikkje avspelast i pallettmodus"
#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
msgid "DXA cutscenes found but ScummVM has been built without zlib"
-msgstr ""
+msgstr "DXA cutscenar funne, men ScummVM vart bygd utan zlib"
#: engines/sword1/animation.cpp:561 engines/sword2/animation.cpp:461
msgid ""
"MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"
-msgstr ""
+msgstr "MPEG-2 cutscenar funne, men ScummVM er bygd utan MPEG-2 støtte"
#: engines/sword1/animation.cpp:568 engines/sword2/animation.cpp:470
-#, fuzzy, c-format
+#, c-format
msgid "Cutscene '%s' not found"
-msgstr "Hopp over cutscene"
+msgstr "Cutscene '%s' ikkje funne"
#: engines/sword1/control.cpp:863
msgid ""
@@ -3544,6 +3588,13 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
+"ScummVM oppdaga at du har gamle lagra speltilstandar for Broken Sword 1 som "
+"vi kan konvertere.\n"
+"Det gamle formatet for lagra speltilstandar støttast ikkje lengre, så du vil "
+"ikkje kunne laste dei utan å konvertere dei.\n"
+"\n"
+"Trykk OK for å konvertere dei no, ellers vil du bli spurt igjen neste gong "
+"du starter spelet.\n"
#: engines/sword1/control.cpp:1232
#, c-format
@@ -3551,6 +3602,9 @@ msgid ""
"Target new save game already exists!\n"
"Would you like to keep the old save game (%s) or the new one (%s)?\n"
msgstr ""
+"Målet for den lagrede speltilstanden finst!\n"
+"Vil du ta vare på den gamle tilstanden (%s) eller den nye (%s)?\n"
+" \n"
#: engines/sword1/control.cpp:1235
msgid "Keep the old one"
@@ -3567,16 +3621,15 @@ msgstr "Dette er slutten på Broken Sword 1-demoen"
#: engines/sword2/animation.cpp:425
msgid ""
"PSX cutscenes found but ScummVM has been built without RGB color support"
-msgstr ""
+msgstr "PSX cutscenar vart funne, men ScummVM er bygd utan RGB fargestøtte"
#: engines/sword2/sword2.cpp:79
-#, fuzzy
msgid "Show object labels"
-msgstr "Objekt"
+msgstr "Syn objektmerkelappar"
#: engines/sword2/sword2.cpp:80
msgid "Show labels for objects on mouse hover"
-msgstr ""
+msgstr "Syn merkelappar for objekt når musa er over dei"
#: engines/teenagent/resources.cpp:95
msgid ""
@@ -3588,54 +3641,57 @@ msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
+"Fila teenagent.dat er komprimert og zlib er ikkje inkludert i binærfila, "
+"vennlegs dekomprimer den."
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Syn FPS-teller"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
+"Vis det gjeldande antall bilete per sekund i øvre venstre hjørne av skjermen"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Nytt opprinnelege skjermar for lagring/lasting"
+msgstr ""
+"Nytt opprinnelege skjermar for lagring/lasting istadenfor ScummVM "
+"grensesnittet"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Dobbel FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Auk bilderate frå 30 til 60 FPS"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Grafikkmodus:"
+msgstr "Slå på Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Grafikkmodus:"
+msgstr "Slå på Venus-hjelpesystemet"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Slå av animasjonar under snuing"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Slå av animasjonar under snuing i panoramamodus"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Nytt høgoppløyseleg MPEG-video"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
-msgstr "Nytt det alternative settet med sølvpeikarar, istaden for dei gylne"
+msgstr ""
+"Nytt MPEG video frå DVD-versjonen, framfor AVI-versjonen med lågare "
+"oppløysning"
#~ msgctxt "lowres"
#~ msgid "Mass Add..."
@@ -3664,10 +3720,6 @@ msgstr "Nytt det alternative settet med sølvpeikarar, istaden for dei gylne"
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Aktiver Roland GS-modus"
-#, fuzzy
-#~ msgid "Save game failed!"
-#~ msgstr "Lagra spel:"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Legg til spill..."
diff --git a/po/pl_PL.po b/po/pl_PL.po
index ff719a3e9f..6546259ade 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -7,14 +7,16 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-02 12:28+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-20 23:43+0100\n"
"Last-Translator: Micha³ Zi±bkowski <mziab@o2.pl>\n"
"Language-Team: Grajpopolsku.pl <grajpopolsku@gmail.com>\n"
"Language: Polski\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-2\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : ((n%10>=2 && n%10<=4 && (n"
+"%100<10 || n%100>=20)) ? 1 : 2));\n"
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-Language: Polish\n"
@@ -76,7 +78,7 @@ msgstr "Wybierz"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Autor:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -84,24 +86,23 @@ msgstr "Nazwa:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Uwagi:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "Ok"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Wybierz plik do wczytania"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Podaj nazwê pliku do zapisania"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Na pewno chcesz skasowaæ ten zapis?"
+msgstr "Na pewno chcesz nadpisaæ ten plik?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -266,7 +267,7 @@ msgstr "Wybierz akcjê i kliknij 'Przypisz'"
#: gui/KeysDialog.cpp:80 gui/KeysDialog.cpp:102 gui/KeysDialog.cpp:141
#, c-format
msgid "Associated key : %s"
-msgstr "Przypisany klawisz : %s"
+msgstr "Przypisany klawisz: %s"
#: gui/KeysDialog.cpp:82 gui/KeysDialog.cpp:104 gui/KeysDialog.cpp:143
#, c-format
@@ -591,16 +592,16 @@ msgid "Search:"
msgstr "Szukaj"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Wczytaj grê:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Wczytaj"
@@ -642,11 +643,11 @@ msgstr "ScummVM nie znalaz³ silnika zdolnego uruchomiæ wybran± grê!"
#: gui/launcher.cpp:1161
msgid "Mass Add..."
-msgstr "Masowe dodawanie..."
+msgstr "Przeszukaj..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr ""
+msgstr "Nagraj..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
@@ -659,35 +660,33 @@ msgstr "Skanowanie zakoñczone!"
#: gui/massadd.cpp:262
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
-msgstr "Wykryto %d nowych gier, zignorowano %d poprzednio dodanych."
+msgstr "Wykryto %d now± grê, zignorowano %d poprzednio dodanych."
#: gui/massadd.cpp:266
#, c-format
msgid "Scanned %d directories ..."
-msgstr "Przeskanowano %d katalogów ..."
+msgstr "Przeskanowano %d katalog..."
#: gui/massadd.cpp:269
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
-msgstr "Wykryto %d nowych gier, zignorowano %d poprzednio dodanych..."
+msgstr "Wykryto %d now± grê, zignorowano %d poprzednio dodanych..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Stop"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr ""
+msgstr "Edytuj opis nagrania"
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Prze³±cz"
+msgstr "Prze³±cz do gry"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Tryb szybki"
+msgstr "Szybka powtórka"
#: gui/options.cpp:85
msgid "Never"
@@ -764,7 +763,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Specjalne tryby ditheringu wspierane przez niektóre gry"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Pe³ny ekran"
@@ -1080,39 +1079,38 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# nastêpny"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr ""
+msgstr "dodaj"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Skasuj"
+msgstr "Usuñ znak"
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr ""
+msgstr "* Pre"
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* Num"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* Abc"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr ""
+msgstr "Nagrywanie/odtwarzanie rozgrywki"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1121,36 +1119,33 @@ msgstr "Skasuj"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr ""
+msgstr "Nagrywaj"
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Uruchom"
+msgstr "Odtwarzaj"
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Edytuj"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Autor: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Uwagi: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Na pewno chcesz skasowaæ ten zapis?"
+msgstr "Na pewno chcesz usun±æ to nagranie?"
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Nieznany b³±d"
+msgstr "Nieznany autor"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1357,18 +1352,18 @@ msgstr "Bursztynowy Hercules"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 kolorów)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 kolorów)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Zielony Hercules"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Bursztynowy Hercules"
@@ -1419,11 +1414,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~P~owrót do launchera"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Zapis:"
@@ -1432,11 +1431,15 @@ msgstr "Zapis:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Zapisz"
@@ -1550,7 +1553,7 @@ msgstr "Emulator OPL DOSBox"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "Bezpo¶rednie FM Alsa"
#: audio/mididrv.cpp:209
#, c-format
@@ -1607,17 +1610,15 @@ msgstr "Emulator Apple II GS (NIE ZAIMPLEMENTOWANY)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Emulator Creative Music System"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "Emulator FM Towns"
+msgstr "D¼wiêk FM-Towns"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "D¼wiêk"
+msgstr "D¼wiêk PC-98"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1712,34 +1713,33 @@ msgstr "Chcesz wyj¶æ?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Tryb touchpada wy³±czony."
+msgstr "Tryb g³adzika jest"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "w³±czony"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "wy³±czony"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Przesuñ dwoma palcami, ¿eby zmieniæ."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Tryb automatycznego przeci±gania jest"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Przesuñ trzema palcami, ¿eby zmieniæ."
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1760,19 +1760,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Zwyk³y (bez skalowania)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "W³±czono korekcjê formatu obrazu"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Wy³±czono korekcjê formatu obrazu"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktywny filtr graficzny:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Okno"
@@ -1839,7 +1839,7 @@ msgstr "Przesuniêcie Y ekranu do dotykania"
#: backends/platform/ds/arm9/source/dsoptions.cpp:87
msgid "Use laptop trackpad-style cursor control"
-msgstr "U¿yj kursora w stylu trackpada z laptopa do sterowania"
+msgstr "U¿yj kursora w stylu g³adzika laptopa do sterowania"
#: backends/platform/ds/arm9/source/dsoptions.cpp:88
msgid "Tap for left click, double tap right click"
@@ -2034,24 +2034,23 @@ msgstr "Steruj myszk±"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Dane ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Zasoby ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ Karta SD ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Media ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Udzia³:"
+msgstr "[ Wspó³dzielone ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2315,35 +2314,45 @@ msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr "U¿yj oryginalnych ekranów odczytu/zapisu zamiast tych ze ScummVM"
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr "U¿yj alternatywnego intra (tylko dla wersji CD)"
+msgstr "U¿yj alternatywnej palety"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"U¿yj alternatywnej palety dla wszystkich amigowych gier. Takie by³o dawne "
+"zachowanie"
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Obs³uga pomijania"
+msgstr "Obs³uga myszki"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"W³±cza obs³ugê myszki. Pozwala na u¿ycie myszki do przemieszczania i w menu "
+"gry."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Wznów grê:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Wznów"
@@ -2386,13 +2395,12 @@ msgid "Cutscene file '%s' not found!"
msgstr "Nie znaleziono pliku przerywnika '%s'!"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Tryb klikania"
+msgstr "Tryb dla daltonistów"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Domy¶lnie w³±cz tryb dla daltonistów"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2447,11 +2455,11 @@ msgstr "Nie uda³o siê zapisaæ stanu gry"
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Tryb krwi"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "W³±cz tryb krwi, je¶li jest dostêpny"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2582,6 +2590,12 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"W ¶cie¿ce gry znaleziono oryginalny zapis gry:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Chcesz u¿yæ tego zapisu w ScummVM?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2589,6 +2603,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"W wybranym slocie %d znaleziono zapis gry. Nadpisaæ?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2600,6 +2616,10 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"Pomy¶lnie zaimportowano %d oryginalny zapis gry do ScummVM. Je¶li pó¼niej "
+"zechcesz zaimportowaæ oryginalne zapisy, bêdziesz musia³ otworzyæ konsolê "
+"debugowania ScummVM i u¿yæ komendy 'import_savefile'.\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2652,10 +2672,18 @@ msgstr ""
"Nie mo¿na zapisaæ w slocie %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Wczytaj plik"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Wczytywanie stanu gry..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Zapisz plik"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Zapisywanie stanu gry..."
@@ -2738,21 +2766,20 @@ msgstr "U¿yj alternatywnego intra (tylko dla wersji CD)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Pomiñ dithering EGA (t³a w pe³nym kolorze)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
msgstr ""
+"Pomiñ dithering w grach EGA, grafika bêdzie wy¶wietlana w pe³nym kolorze"
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "W³±cz histogramy punktów ¿ycia"
+msgstr "W³±cz grafikê wysokiej rozdzielczo¶ci"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "W³±cz histogramy punktów ¿ycia"
+msgstr "W³±cz grafikê/zawarto¶æ wysokiej rozdzielczo¶ci"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2825,15 +2852,13 @@ msgstr "Gra wstrzymana. Naci¶nij spacjê, aby wznowiæ."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
-msgstr "Na pewno chcesz zrestartowaæ grê? (T/N)T"
+msgstr "Na pewno chcesz zrestartowaæ? (T/N)T"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
-msgstr "Na pewno chcesz wyj¶æ? (T/N)T"
+msgstr "Na pewno chcesz wyj¶æ? (T/N)T"
#: engines/scumm/dialogs.cpp:190
msgid "Play"
@@ -3341,25 +3366,24 @@ msgid "Third kid"
msgstr "Trzeci dzieciak"
#: engines/scumm/help.cpp:292
-#, fuzzy
msgid "Toggle Inventory/IQ Points display"
-msgstr "W³±cz/wy³±cz widok danych"
+msgstr "W³±cz/wy³±cz widok ekwipunku/punktów IQ"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Prze³±cz miêdzy walk± klawiatur± a mysz± (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "* Walka klawiatur± jest zawsze w³±czona,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr " wiêc wbrew komunikatowi w grze"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr " to ustawienie w³±cza/wy³±cza walkê mysz±"
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3396,7 +3420,7 @@ msgstr "Niskie uderzenie"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr ""
+msgstr "Cios z zaskoczenia"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3455,23 +3479,20 @@ msgid "Fly to lower right"
msgstr "Leæ w dó³, w prawo"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "P³ynne przewijanie"
+msgstr "Przesuwanie skokowe w³±czone"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr ""
+msgstr "Przesuwanie skokowe wy³±czone"
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "G³o¶no¶æ muzyki:"
+msgstr "G³o¶no¶æ muzyki: "
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
-msgstr "Prêd. napisów:"
+msgstr "Prêd. napisów: "
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3483,27 +3504,86 @@ msgstr ""
"ale brakuje %s. Prze³±czam na tryb AdLib."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Zwykle w tym momencie uruchomi³oby siê Maniac Mansion, ale ScummVM jeszcze "
-"tego nie obs³uguje. Aby zagraæ, u¿yj \"Dodaj grê...\" z menu startowego "
-"ScummVM i wybierz podkatalog \"Maniac\" z katalogu gry Tentacle."
+"Zwykle w tym momencie uruchomi³oby siê Maniac Mansion. Ale ¿eby to "
+"zadzia³a³o, pliki Maniac Mansion musz± znajdowaæ siê w podkatalogu \"Maniac"
+"\" w katalogu gry Day of the Tentacle, a gra musi byæ dodana do ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Nie znaleziono pliku wykonywalnego \"Loom\" dla Macintosha do odczytania "
+"instrumentów. Muzyka bêdzie wy³±czona."
#: 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 ""
+"Nie znaleziono pliku wykonywalnego \"Monkey Island\" dla Macintosha do "
+"odczytania instrumentów. Muzyka bêdzie wy³±czona."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "U¿ywaj oryginalnego ekranu odczytu/zapisu"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Przycisk zapisu w grze wy¶wietla oryginalny ekran odczytu/zapisu zamiast "
+"menu ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pikselizowane przej¶cia miêdzy scenami"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "U¿ywaj losowej pikselizacji przy zmianie sceny"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Nie wy¶wietlaj hotspotów przy poruszaniu mysz±"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Wy¶wietlaj nazwy hotspotów dopiero po klikniêciu ich lub u¿yciu przycisku "
+"akcji"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Wy¶wietl portrety postaci"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Wy¶wietl portrety postaci podczas rozmowy"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Przysuñ okna"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Przysuñ okna interfejsu zamiast wy¶wietliæ je od razu"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Przezroczyste okna"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Wy¶wietlaj okna z pó³przezroczystym t³em"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3611,7 +3691,7 @@ msgstr "Poka¿ etykiety obiektów przy najechaniu myszk±"
#: engines/teenagent/resources.cpp:95
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
-msgstr "Nie masz pliku 'teenagent.dat'. Pobierz go ze strony ScummVM"
+msgstr "Nie masz pliku \"teenagent.dat\". Pobierz go ze strony ScummVM"
#: engines/teenagent/resources.cpp:116
msgid ""
@@ -3623,52 +3703,47 @@ msgstr ""
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Poka¿ licznik klatek na sekundê"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
-msgstr ""
+msgstr "Wy¶wietl aktualn± liczbê klatek na sekundê w lewym, górnym logu"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "U¿yj oryginalnych ekranów odczytu/zapisu zamiast tych ze ScummVM"
+msgstr "U¿yj oryginalnych ekranów odczytu/zapisu zamiast interfejsu ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Podwójna liczba klatek"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Zwiêksz liczbê klatek na sekundê z 30 do 60"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "W³±cz tryb helowy"
+msgstr "W³±cz Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "W³±cz tryb helowy"
+msgstr "W³±cz system pomocy Venus"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Wy³±cz animacjê podczas obrotu"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Wy³±cz animacjê podczas trybu panoramy"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "U¿yj wideo MPEG w wysokiej rozdzielczo¶ci"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
-msgstr ""
-"U¿yj alternatywnego zestawu srebrnych kursorów zamiast zwyk³ych z³otych"
+msgstr "U¿yj wideo MPEG z wersji DVD zamiast AVI ni¿szej rozdzielczo¶ci"
#~ msgid "EGA undithering"
#~ msgstr "Anty-dithering EGA"
@@ -3720,9 +3795,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "W³±cz tryb Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "Nie uda³o siê zapisaæ stanu gry!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Dodaj grê..."
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 73b6fc8bae..b42ccf2bff 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2011-10-21 21:30-0300\n"
"Last-Translator: Saulo Benigno <saulobenigno@gmail.com>\n"
"Language-Team: ScummBR (www.scummbr.com) <scummbr@yahoo.com.br>\n"
@@ -598,16 +598,16 @@ msgid "Search:"
msgstr "Pesquisar:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Carregar jogo:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Carregar"
@@ -779,7 +779,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Modos especiais de dithering suportados por alguns jogos"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Modo Tela Cheia"
@@ -1387,12 +1387,12 @@ msgstr ""
msgid "PC-9801 (16 Colors)"
msgstr ""
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules Green"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules Amber"
@@ -1444,11 +1444,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~V~oltar ao menu"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Salvar jogo:"
@@ -1457,11 +1461,15 @@ msgstr "Salvar jogo:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Salvar"
@@ -1793,19 +1801,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normal (sem escala)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Correção de proporção habilitada"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Correção de proporção desabilitada"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Ativa os filtros gráficos"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Modo janela"
@@ -2371,15 +2379,23 @@ msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Restaurar jogo:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Restaurar"
@@ -2707,10 +2723,20 @@ msgstr ""
"Não é possível salvar o jogo na posição %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Carregar jogo:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Carregando jogo..."
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Falha ao salvar jogo!"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Salvando jogo..."
@@ -3559,6 +3585,59 @@ msgid ""
"instruments from. Music will be disabled."
msgstr ""
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+#, fuzzy
+msgid "Show character portraits"
+msgstr "Trocador de caracteres"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3772,9 +3851,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Ligar modo Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "Falha ao salvar jogo!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Adicionar Jogo..."
diff --git a/po/ru_RU.po b/po/ru_RU.po
index be2d972979..ba91013bb5 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2016-02-02 20:38+0300\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-21 23:32+0300\n"
"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
"Language-Team: Russian\n"
"Language: Russian\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Poedit 1.8.6\n"
+"X-Generator: Poedit 1.8.7\n"
#: gui/about.cpp:94
#, c-format
@@ -591,16 +591,16 @@ msgid "Search:"
msgstr "¿ÞØáÚ:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "·ÐÓàã×Øâì ØÓàã:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "·ÐÓàã×Øâì"
@@ -763,7 +763,7 @@ msgid "Special dithering modes supported by some games"
msgstr "ÁßÕæØÐÛìÝëÕ àÕÖØÜë àÕÝÔÕàØÝÓÐ, ßÞÔÔÕàÖØÒÐÕÜëÕ ÝÕÚÞâÞàëÜØ ØÓàÐÜØ"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ"
@@ -1362,12 +1362,12 @@ msgstr "PC-9821 (256 æÒÕâÞÒ)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 æÒÕâÞÒ)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules ·ÕÛñÝëÙ"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ÏÝâÐàÝëÙ"
@@ -1419,11 +1419,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~²~ ÓÛÐÒÝÞÕ ÜÕÝî"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "ÁÞåàÐÝØâì ØÓàã:"
@@ -1432,11 +1436,15 @@ msgstr "ÁÞåàÐÝØâì ØÓàã:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "ÁÞåàÐÝØâì"
@@ -1634,7 +1642,7 @@ msgstr "ÍÜãÛïâÞà MT-32"
#: audio/softsynth/pcspk.cpp:139
msgid "PC Speaker Emulator"
-msgstr "ÍÜãÛïâÞà PC áßØÚÕàÐ"
+msgstr "ÍÜãÛïâÞà PC-áßØÚÕàÐ"
#: audio/softsynth/pcspk.cpp:158
msgid "IBM PCjr Emulator"
@@ -1718,7 +1726,7 @@ msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ÒëÙâØ?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
msgid "Trackpad mode is now"
-msgstr "ÀÕÖØÜ âàÕÚßÐÔÐ ÒÚÛîçÕÝ."
+msgstr "ÀÕÖØÜ âàÕÚßÐÔÐ áÕÙçÐá"
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
@@ -1739,7 +1747,7 @@ msgstr "¿àÞÒÕÔØâÕ ÔÒãÜï ßÐÛìæÐÜØ ÝÐßàÐÒÞ ÔÛï ßÕàÕÚÛîçÕÝØï."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr "ÀÕÖØÜ ÐÒâÞ-ÔàÕÓ ÒÚÛîçÕÝ"
+msgstr "ÀÕÖØÜ ÐÒâÞÔàíÓÐ áÕÙçÐá"
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
@@ -1764,19 +1772,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "±Õ× ãÒÕÛØçÕÝØï"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "ºÞààÕÚæØï áÞÞâÝÞèÕÝØï áâÞàÞÝ ÒÚÛîçÕÝÐ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "ºÞààÕÚæØï áÞÞâÝÞèÕÝØï áâÞàÞÝ ÒëÚÛîçÕÝÐ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "°ÚâØÒÝëÙ ÓàÐäØçÕáÚØÙ äØÛìâà:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "¾ÚÞÝÝëÙ àÕÖØÜ"
@@ -1951,7 +1959,7 @@ msgstr "¾ÚÝÞ"
#: backends/platform/sdl/macosx/appmenu_osx.mm:125
msgid "Minimize"
-msgstr "ÃÑàÐâì Ò Dock"
+msgstr "ÁÒÕàÝãâì"
#: backends/platform/symbian/src/SymbianActions.cpp:38
#: backends/platform/wince/CEActionsSmartphone.cpp:39
@@ -2082,11 +2090,11 @@ msgstr "²ÒÞÔ"
#: backends/platform/wii/options.cpp:74
msgid "GC Pad sensitivity:"
-msgstr "ÇãÒáâÒØâÕÛìÝÞáâì GC ßÐÔÐ:"
+msgstr "ÇãÒáâÒØâÕÛìÝÞáâì GC-ßÐÔÐ:"
#: backends/platform/wii/options.cpp:80
msgid "GC Pad acceleration:"
-msgstr "ÃáÚÞàÕÝØÕ GC ßÐÔÐ:"
+msgstr "ÃáÚÞàÕÝØÕ GC-ßÐÔÐ:"
#: backends/platform/wii/options.cpp:86
msgid "DVD"
@@ -2282,7 +2290,7 @@ msgstr "½Ð×ÝÐçØâì ÔÕÙáâÒØÕ 'áßàïâÐâì ßÐÝÕÛì ØÝáâàãÜÕÝâÞÒ'"
#: backends/platform/wince/wince-sdl.cpp:533
msgid "You must map a key to the 'Hide toolbar' action to play this game"
-msgstr "²ë ÔÞÛÖÝë ÝÐ×ÝÐçØâì ÚÛÐÒØèã ÝÐ ÔÕÙâáâÒØÕ 'Hide toolbar' ÔÛï íâÞÙ ØÓàë"
+msgstr "²ë ÔÞÛÖÝë ÝÐ×ÝÐçØâì ÚÛÐÒØèã ÝÐ ÔÕÙáâÒØÕ 'Hide toolbar' ÔÛï íâÞÙ ØÓàë"
#: backends/platform/wince/wince-sdl.cpp:542
msgid "Map Zoom Up action (optional)"
@@ -2316,7 +2324,7 @@ msgstr "¸áßÞÛì×ÞÒÐâì ÞàØÓØÝÐÛìÝëÕ íÚàÐÝë ×ÐßØáØ/çâÕÝØï ØÓàë"
#: engines/toltecs/detection.cpp:201
msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr ""
-"¸áßÞÛì×ÞÒÐâì ÞàØÓØÝÐÛìÝëÕ íÚàÐÝë ×ÐßØáØ Ø áÞåàÐÝÕÝØï ØÓàë ÒÜÕáâÞ áÔÕÛÐÝÝëå Ò "
+"¸áßÞÛì×ÞÒÐâì ÞàØÓØÝÐÛìÝëÕ íÚàÐÝë çâÕÝØï Ø áÞåàÐÝÕÝØï ØÓàë ÒÜÕáâÞ áÔÕÛÐÝÝëå Ò "
"ScummVM"
#: engines/agi/detection.cpp:157
@@ -2342,15 +2350,23 @@ msgstr ""
"²ÚÛîçÐÕâ ßÞÔÔÕàÖÚã ÜëèØ. ¿Þ×ÒÞÛïÕâ ØáßÞÛì×ÞÒÐâì Üëèì ÔÛï ßÕàÕÜÕéÕÝØï Ø Ò "
"ÜÕÝî ØÓàë."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "²ÞááâÐÝÞÒØâì ØÓàã:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "²ÞááâÐÝÞÒØâì"
@@ -2596,7 +2612,7 @@ msgstr ""
"\n"
"%s %s\n"
"\n"
-"½Õ ÖÕÛÐÕâÕ ÛØ ØáßÞÛì×ÞÒÐâì íâÞ áÞåàÐÝÕÝØÕ Ò ScummVM?\n"
+"²ë åÞâØâÕ ØáßÞÛì×ÞÒÐâì íâÞ áÞåàÐÝÕÝØÕ Ò ScummVM?\n"
"\n"
#: engines/kyra/saveload_eob.cpp:590
@@ -2674,10 +2690,18 @@ msgstr ""
"½Õ ÜÞÓã áÞåàÐÝØâì ØÓàã Ò ßÞ×ØæØî %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "·ÐÓàã×Øâì äÐÙÛ"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "·ÐÓàãÖÐî ØÓàã..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "ÁÞåàÐÝØâì äÐÙÛ"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "ÁÞåàÐÝïî ØÓàã..."
@@ -2721,11 +2745,11 @@ msgstr "½ÕÒÕàÝÞÕ ØÜï äÐÙÛÐ áÞåàÐÝÕÝØï"
#: engines/pegasus/pegasus.cpp:2507
msgid "Up/Zoom In/Move Forward/Open Doors"
-msgstr "²ÒÕàå/ÃÜÕÝìèØâì ÜÐáèâÐÑ/²ßÕàñÔ/¾âÚàëâì ÔÒÕàØ"
+msgstr "²ÒÕàå/ÃÒÕÛ. ÜÐáèâÐÑ/²ßÕàñÔ/¾âÚàëâì ÔÒÕàØ"
#: engines/pegasus/pegasus.cpp:2508
msgid "Down/Zoom Out"
-msgstr "²ÝØ×/ÃÒÕÛ. ÜÐáèâÐÑ"
+msgstr "²ÝØ×/ÃÜÕÝìè. ÜÐáèâÐÑ"
#: engines/pegasus/pegasus.cpp:2511
msgid "Display/Hide Inventory Tray"
@@ -2757,7 +2781,7 @@ msgstr "°ÛìâÕàÝÐâØÒÝÞÕ ÒáâãßÛÕÝØÕ"
#: engines/queen/detection.cpp:57
msgid "Use an alternative game intro (CD version only)"
-msgstr "¸áßÞÛì×ÞÒÐâì ÐÛìâÕàÝÐâØÒÝÞÕ ÒáâãßÛÕÝØÕ (âÞÛìÚÞ ÔÛï CD ÒÕàáØØ ØÓàë)"
+msgstr "¸áßÞÛì×ÞÒÐâì ÐÛìâÕàÝÐâØÒÝÞÕ ÒáâãßÛÕÝØÕ (âÞÛìÚÞ ÔÛï CD-ÒÕàáØØ ØÓàë)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
@@ -2935,7 +2959,7 @@ msgstr "²ëÑÕàØâÕ ãàÞÒÕÝì áÛÞÖÝÞáâØ."
#: engines/scumm/dialogs.cpp:660
msgid "Refer to your Loom(TM) manual for help."
-msgstr "·Ð ßÞÜÞéìî ÞÑàÐâØâÕáì Ú ØÝáâãÚæØØ Loom(TM)"
+msgstr "·Ð ßÞÜÞéìî ÞÑàÐâØâÕáì Ú ØÝáâàãÚæØØ Loom(TM)."
#: engines/scumm/dialogs.cpp:664
msgid "Practice"
@@ -3005,7 +3029,7 @@ msgstr "³àÞÜÚÞáâì Üã×ëÚØ ãÒÕÛØçØâì / ãÜÕÝìèØâì"
#: engines/scumm/help.cpp:89
msgid "Text speed slower / faster"
-msgstr "ÁÚÞàÞáâì âÕÚáâÐ ÑëáâàÕÕ / ÜÕÔÛÕÝÝÕÕ"
+msgstr "ÁÚÞàÞáâì âÕÚáâÐ ÜÕÔÛÕÝÝÕÕ / ÑëáâàÕÕ"
#: engines/scumm/help.cpp:90
msgid "Simulate left mouse button"
@@ -3025,7 +3049,7 @@ msgstr "ÁßÕæØÐÛìÝëÕ ÚÛÐÒØÐâãàÝëÕ ÚÞÜÐÝÔë:"
#: engines/scumm/help.cpp:95
msgid "Show / Hide console"
-msgstr "¿ÞÚÐ×Ðâì / ÃÑàÐâì ÚÞÝáÞÛì"
+msgstr "¿ÞÚÐ×Ðâì / ãÑàÐâì ÚÞÝáÞÛì"
#: engines/scumm/help.cpp:96
msgid "Start the debugger"
@@ -3053,7 +3077,7 @@ msgstr "¿ÕàÕÚÛîçÕÝØÕ ÜÕÖÔã ÓàÐäØçÕáÚØÜØ äØÛìâàÐÜØ"
#: engines/scumm/help.cpp:102
msgid "Increase / Decrease scale factor"
-msgstr "ÃÒÕÛØçØâì/ãÜÕÝìèØâì ÜÐáèâÐÑ"
+msgstr "ÃÒÕÛØçØâì / ãÜÕÝìèØâì ÜÐáèâÐÑ"
#: engines/scumm/help.cpp:103
msgid "Toggle aspect-ratio correction"
@@ -3187,7 +3211,7 @@ msgstr "¿ãâÕèÕáâÒÞÒÐâì"
#: engines/scumm/help.cpp:176
msgid "To Henry / To Indy"
-msgstr "³ÕÝàØ/¸ÝÔØ"
+msgstr "³ÕÝàØ / ¸ÝÔØ"
#. I18N: These are different musical notes
#: engines/scumm/help.cpp:180
@@ -3371,7 +3395,7 @@ msgstr "¿ÕàÕÚÛîçØâì ßÞÚÐ× ØÝÒÕÝâÐàï/ÞçÚÞÒ IQ"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr "¿ÕàÕÚÛîçØâì ãßàÐÒÛÕÝØÕ ÑÞïÜØ ºÛÐÒØÐâãàÞÙ/¼ëèìî (*)"
+msgstr "¿ÕàÕÚÛîçØâì ãßàÐÒÛÕÝØÕ ÑÞïÜØ ÚÛÐÒØÐâãàÞÙ/Üëèìî (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
@@ -3484,7 +3508,7 @@ msgstr "¿àÞÚàãâÚÐ áÚÐçÚÐÜØ ÒÚÛîçÕÝÐ"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr "¿àÞÚàãâÚÐ áÚÐçÚÐÜØ ÒëÚÛ"
+msgstr "¿àÞÚàãâÚÐ áÚÐçÚÐÜØ ÒëÚÛîçÕÝÐ"
#: engines/scumm/input.cpp:595
msgid "Music volume: "
@@ -3529,6 +3553,62 @@ msgstr ""
"½Õ ãÔÐÛÞáì ÝÐÙâØ ØáßÞÛÝØÜëÙ äÐÙÛ 'Monkey Island' Macintosh, çâÞÑë ßàÞçØâÐâì\n"
"ÔÐÝÝëÕ ÞÑ ØÝáâàãÜÕÝâÐå. ¼ã×ëÚÐ ÑãÔÕâ ÒëÚÛîçÕÝÐ."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "¸áßÞÛì×ÞÒÐâì ÞàØÓØÝÐÛìÝëÕ íÚàÐÝë ×ÐßØáØ/çâÕÝØï ØÓàë"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"ºÝÞßÚÐ \"ÄÐÙÛë\" Ò ØÓàÕ ßÞÚÐ×ëÒÐÕâ ÞàØÓØÝÐÛìÝëÙ ÔØÐÛÞÓ áÞåàÐÝÕÝØï, Ð ÝÕ ÜÕÝî "
+"ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "¿ÕàÕåÞÔë ÜÕÖÔã áæÕÝÐÜØ á ßØÚáÕÛØ×ÐæØÕÙ"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "¿àØ áÜÕÝÕ áæÕÝ ßàÞØáåÞÔØâ ßÕàÕåÞÔ á àÐÝÔÞÜØ×ØàÞÒÐÝÝëÜØ ßØÚáÕÛïÜØ"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "½Õ ßÞÚÐ×ëÒÐâì åÞâáßÞâë ßàØ ÝÐÒÕÔÕÝØØ Üëèìî"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"¿ÞÚÐ×ëÒÐâì ÝÐ×ÒÐÝØï åÞâáßÞâÞÒ âÞÛìÚÞ ßÞáÛÕ ÚÛØÚÐ ßÞ ÝØÜ ÛØÑÞ ßÞáÛÕ ÝÐÖÐâØï "
+"ÝÐ ÚÝÞßÚã ÔÕÙáâÒØï"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "¿ÞÚÐ×ëÒÐâì ßÞàâàÕâë ÓÕàÞÕÒ"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "¿ÞÚÐ×ëÒÐâì ßÞàâàÕâë ÓÕàÞÕÒ ÒÞ ÒàÕÜï ÔØÐÛÞÓÞÒ"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "²êÕ×ÖÐîéØÕ ÔØÐÛÞÓØ"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "´ØÐÛÞÓØ ÑãÔãâ ÒêÕ×ÖÐâì, Ð ÝÕ ßÞÚÐ×ëÒÐâìáï ÜÓÝÞÒÕÝÝÞ"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "¿àÞ×àÐçÝëÕ ÞÚÝÐ"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "¿ÞÚÐ×ëÒÐâì ÞÚÝÐ á çÐáâØçÝÞ ßàÞ×àÐçÝëÜ äÞÝÞÜ"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
@@ -3547,7 +3627,7 @@ msgstr ""
#: engines/sky/detection.cpp:44
msgid "Floppy intro"
-msgstr "²áâãßÛÕÝØÕ á äÛÞßßØÚÞÒ"
+msgstr "²áâãßÛÕÝØÕ á ÔØáÚÕâ"
#: engines/sky/detection.cpp:45
msgid "Use the floppy version's intro (CD version only)"
@@ -3584,7 +3664,8 @@ msgid ""
"Press OK to convert them now, otherwise you will be asked again the next "
"time you start the game.\n"
msgstr ""
-"ScummVM ÞÑÝÐàãÖØÛ ã ÒÐá áÞåàÐÝÕÝØï ØÓàë ÁÛÞÜÐÝÝëÙ ¼Õç Ò áâÐàÞÜ äÞàÜÐâÕ.\n"
+"ScummVM ÞÑÝÐàãÖØÛ ã ÒÐá áÞåàÐÝÕÝØï ØÓàë \"ÁÛÞÜÐÝÝëÙ ÜÕç 1\" Ò áâÐàÞÜ "
+"äÞàÜÐâÕ.\n"
"ÁâÐàëÙ äÞàÜÐâ ÑÞÛìèÕ ÝÕ ßÞÔÔÕàÖØÒÐÕâáï, Ø, çâÞÑë ×ÐÓàã×Øâì áÞåàÐÝÕÝØï, ÞÝØ "
"ÔÞÛÖÝë Ñëâì ßÕàÕÒÕÔÕÝë Ò ÝÞÒëÙ äÞàÜÐâ.\n"
"\n"
@@ -3610,13 +3691,13 @@ msgstr "ÁÔÕÛÐâì ÝÞÒÞÕ"
#: engines/sword1/logic.cpp:1633
msgid "This is the end of the Broken Sword 1 Demo"
-msgstr "ÍâÞ ×ÐÒÕàèÕÝØÕ ÔÕÜÞ ÁÛÞÜÐÝÝÞÓÞ ¼ÕçÐ 1"
+msgstr "ÍâÞ ×ÐÒÕàèÕÝØÕ ÔÕÜÞ \"ÁÛÞÜÐÝÝÞÓÞ ÜÕçÐ 1\""
#: engines/sword2/animation.cpp:425
msgid ""
"PSX cutscenes found but ScummVM has been built without RGB color support"
msgstr ""
-"½ÐÙÔÕÝë ×ÐáâÐÒÚØ Ò äÞàÜÐâÕ PSX, ÝÞ ScummVM ÑëÛ áÞÑàÐÝ ÑÕ× ßÞÔÔÕàÖÚØ RGB "
+"½ÐÙÔÕÝë ×ÐáâÐÒÚØ Ò äÞàÜÐâÕ PSX, ÝÞ ScummVM ÑëÛ áÞÑàÐÝ ÑÕ× ßÞÔÔÕàÖÚØ RGB-"
"æÒÕâÞÒ"
#: engines/sword2/sword2.cpp:79
@@ -3740,9 +3821,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "²ÚÛîçØâì àÕÖØÜ Roland GS"
-#~ msgid "Save game failed!"
-#~ msgstr "½Õ ãÔÐÛÞáì áÞåàÐÝØâì ØÓàã!"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "´ÞÑ. ØÓàã"
diff --git a/po/scummvm.pot b/po/scummvm.pot
index 255200110d..1edbe00e20 100644
--- a/po/scummvm.pot
+++ b/po/scummvm.pot
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: ScummVM 1.8.0git\n"
+"Project-Id-Version: ScummVM 1.9.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -584,16 +584,16 @@ msgid "Search:"
msgstr ""
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr ""
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr ""
@@ -754,7 +754,7 @@ msgid "Special dithering modes supported by some games"
msgstr ""
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr ""
@@ -1338,12 +1338,12 @@ msgstr ""
msgid "PC-9801 (16 Colors)"
msgstr ""
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr ""
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr ""
@@ -1394,11 +1394,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr ""
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr ""
@@ -1407,11 +1411,15 @@ msgstr ""
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr ""
@@ -1708,19 +1716,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr ""
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr ""
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr ""
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr ""
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr ""
@@ -2278,15 +2286,23 @@ msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr ""
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr ""
@@ -2573,10 +2589,18 @@ msgid ""
"\n"
msgstr ""
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr ""
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr ""
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr ""
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr ""
@@ -3398,6 +3422,58 @@ msgid ""
"instruments from. Music will be disabled."
msgstr ""
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr ""
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr ""
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
diff --git a/po/se_SE.po b/po/sv_SE.po
index a3a644501f..82357b4dc2 100644
--- a/po/se_SE.po
+++ b/po/sv_SE.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.5.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
-"PO-Revision-Date: 2014-07-02 16:30+0100\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-02-25 23:06+0100\n"
"Last-Translator: Hampus Flink <hampus.flink@gmail.com>\n"
"Language-Team: \n"
"Language: Svenska\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
-"X-Generator: Poedit 1.6.5\n"
+"X-Generator: Poedit 1.8.7\n"
#: gui/about.cpp:94
#, c-format
@@ -30,7 +30,7 @@ msgstr "Funktioner kompilerade i:"
#: gui/about.cpp:110
msgid "Available engines:"
-msgstr "Tillgängliga motorer"
+msgstr "Tillgängliga motorer:"
#: gui/browser.cpp:68 gui/browser_osx.mm:104
msgid "Show hidden files"
@@ -75,7 +75,7 @@ msgstr "Välj"
#: gui/editrecorddialog.cpp:58
msgid "Author:"
-msgstr ""
+msgstr "Skapare:"
#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
msgid "Name:"
@@ -83,24 +83,23 @@ msgstr "Namn:"
#: gui/editrecorddialog.cpp:60
msgid "Notes:"
-msgstr ""
+msgstr "Anteckningar:"
#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
msgid "Ok"
-msgstr ""
+msgstr "OK"
#: gui/filebrowser-dialog.cpp:49
msgid "Choose file for loading"
-msgstr ""
+msgstr "Välj en fil att ladda"
#: gui/filebrowser-dialog.cpp:49
msgid "Enter filename for saving"
-msgstr ""
+msgstr "Ange ett filnamn för att spara"
#: gui/filebrowser-dialog.cpp:132
-#, fuzzy
msgid "Do you really want to overwrite the file?"
-msgstr "Vill du verkligen radera den här spardatan?"
+msgstr "Vill du verkligen skriva över filen?"
#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
@@ -594,16 +593,16 @@ msgid "Search:"
msgstr "Sök:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "Ladda spel:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "Ladda"
@@ -651,7 +650,7 @@ msgstr "Masstillägg..."
#: gui/launcher.cpp:1163
msgid "Record..."
-msgstr ""
+msgstr "Spela in..."
#: gui/massadd.cpp:79 gui/massadd.cpp:82
msgid "... progress ..."
@@ -678,21 +677,19 @@ msgstr "Upptäckte %d nya spel, ignorerade %d tidigare tillagda spel ..."
#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
msgid "Stop"
-msgstr ""
+msgstr "Stopp"
#: gui/onscreendialog.cpp:106
msgid "Edit record description"
-msgstr ""
+msgstr "Redigera beskrivning av inspelning"
#: gui/onscreendialog.cpp:108
-#, fuzzy
msgid "Switch to Game"
-msgstr "Byt"
+msgstr "Växla till spelet"
#: gui/onscreendialog.cpp:110
-#, fuzzy
msgid "Fast replay"
-msgstr "Snabbläge"
+msgstr "Snabb uppspelning"
#: gui/options.cpp:85
msgid "Never"
@@ -769,7 +766,7 @@ msgid "Special dithering modes supported by some games"
msgstr "Speciella gitterlägen stödda av vissa spel"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "Fullskärmsläge"
@@ -1085,39 +1082,38 @@ msgstr ""
#. I18N: You must leave "#" as is, only word 'next' is translatable
#: gui/predictivedialog.cpp:86
msgid "# next"
-msgstr ""
+msgstr "# nästa"
#: gui/predictivedialog.cpp:87
msgid "add"
-msgstr ""
+msgstr "Lägg till"
#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
-#, fuzzy
msgid "Delete char"
-msgstr "Radera"
+msgstr "Radera tecken"
#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
msgid "<"
-msgstr ""
+msgstr "<"
#. I18N: Pre means 'Predictive', leave '*' as is
#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
msgid "* Pre"
-msgstr ""
+msgstr "* Pre."
#. I18N: 'Num' means Numbers
#: gui/predictivedialog.cpp:575
msgid "* Num"
-msgstr ""
+msgstr "* 123"
#. I18N: 'Abc' means Latin alphabet input
#: gui/predictivedialog.cpp:578
msgid "* Abc"
-msgstr ""
+msgstr "* ABC"
#: gui/recorderdialog.cpp:64
msgid "Recorder or Playback Gameplay"
-msgstr ""
+msgstr "Inspelare eller återuppspelning"
#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
@@ -1126,36 +1122,33 @@ msgstr "Radera"
#: gui/recorderdialog.cpp:71
msgid "Record"
-msgstr ""
+msgstr "Spela in"
#: gui/recorderdialog.cpp:72
-#, fuzzy
msgid "Playback"
-msgstr "Spela"
+msgstr "Spela upp"
#: gui/recorderdialog.cpp:74
msgid "Edit"
-msgstr ""
+msgstr "Redigera"
#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
#: gui/recorderdialog.cpp:253
msgid "Author: "
-msgstr ""
+msgstr "Skapare: "
#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
#: gui/recorderdialog.cpp:254
msgid "Notes: "
-msgstr ""
+msgstr "Anteckningar: "
#: gui/recorderdialog.cpp:155
-#, fuzzy
msgid "Do you really want to delete this record?"
-msgstr "Vill du verkligen radera den här spardatan?"
+msgstr "Vill du verkligen radera den här inspelningen?"
#: gui/recorderdialog.cpp:174
-#, fuzzy
msgid "Unknown Author"
-msgstr "Okänt fel"
+msgstr "Okänd skapare"
#: gui/saveload-dialog.cpp:167
msgid "List view"
@@ -1362,18 +1355,18 @@ msgstr "Herkules bärnsten"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
-msgstr ""
+msgstr "PC-9821 (256 färger)"
#: common/rendermode.cpp:43
msgid "PC-9801 (16 Colors)"
-msgstr ""
+msgstr "PC-9801 (16 färger)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Herkules grön"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Herkules bärnsten"
@@ -1425,11 +1418,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "Åte~r~vänd till launcher"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "Spara spelet:"
@@ -1438,11 +1435,15 @@ msgstr "Spara spelet:"
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "Spara"
@@ -1560,7 +1561,7 @@ msgstr "DOSBox OPL-emulator"
#: audio/fmopl.cpp:67
msgid "ALSA Direct FM"
-msgstr ""
+msgstr "ALSA Direct FM"
#: audio/mididrv.cpp:209
#, c-format
@@ -1617,17 +1618,15 @@ msgstr "Apple II GS-emulator (INTE IMPLEMENTERAD)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr ""
+msgstr "Creative Music System-emulator"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
-#, fuzzy
msgid "FM-Towns Audio"
-msgstr "FM Towns-emulator"
+msgstr "FM Towns-ljud"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
-#, fuzzy
msgid "PC-98 Audio"
-msgstr "Ljud"
+msgstr "PC-98 ljud"
#: audio/softsynth/mt32.cpp:200
msgid "Initializing MT-32 Emulator"
@@ -1722,34 +1721,33 @@ msgstr "Vill du avsluta?"
#. I18N: Trackpad mode toggle status.
#: backends/events/webossdl/webossdl-events.cpp:308
-#, fuzzy
msgid "Trackpad mode is now"
-msgstr "Touchpad-läge inaktiverat."
+msgstr "Trackpad-läge "
#. I18N: Trackpad mode on or off.
#. I18N: Auto-drag on or off.
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "ON"
-msgstr ""
+msgstr "PÅ"
#: backends/events/webossdl/webossdl-events.cpp:311
#: backends/events/webossdl/webossdl-events.cpp:338
msgid "OFF"
-msgstr ""
+msgstr "AV"
#: backends/events/webossdl/webossdl-events.cpp:315
msgid "Swipe two fingers to the right to toggle."
-msgstr ""
+msgstr "Svep åt höger med två fingrar för att byta läge."
#. I18N: Auto-drag toggle status.
#: backends/events/webossdl/webossdl-events.cpp:335
msgid "Auto-drag mode is now"
-msgstr ""
+msgstr "Automatiskt dragläge "
#: backends/events/webossdl/webossdl-events.cpp:342
msgid "Swipe three fingers to the right to toggle."
-msgstr ""
+msgstr "Svep åt höger med tre fingrar för att byta läge."
#: backends/graphics/opengl/opengl-graphics.cpp:119
msgid "OpenGL"
@@ -1770,19 +1768,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "Normalt (ingen skalning)"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "Korrektion av bildförhållande på"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "Korrektion av bildförhållande av"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "Aktivt grafikfilter:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "Fönsterläge"
@@ -2044,24 +2042,23 @@ msgstr "Kontrollera musen"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"
-msgstr ""
+msgstr "[ Data ]"
#: backends/platform/tizen/fs.cpp:263
msgid "[ Resources ]"
-msgstr ""
+msgstr "[ Resurser ]"
#: backends/platform/tizen/fs.cpp:267
msgid "[ SDCard ]"
-msgstr ""
+msgstr "[ SD-kort ]"
#: backends/platform/tizen/fs.cpp:271
msgid "[ Media ]"
-msgstr ""
+msgstr "[ Media ]"
#: backends/platform/tizen/fs.cpp:275
-#, fuzzy
msgid "[ Shared ]"
-msgstr "Delad:"
+msgstr "[ Delad ]"
#: backends/platform/wii/options.cpp:51
msgid "Video"
@@ -2328,35 +2325,45 @@ msgid "Use the original save/load screens, instead of the ScummVM ones"
msgstr "Använder originalskärmarna för spara/ladda istället för ScummVM:s"
#: engines/agi/detection.cpp:157
-#, fuzzy
msgid "Use an alternative palette"
-msgstr "Använd alternativt spelintro (endast CD-version)"
+msgstr "Använd alternativ färgkarta"
#: engines/agi/detection.cpp:158
msgid ""
"Use an alternative palette, common for all Amiga games. This was the old "
"behavior"
msgstr ""
+"Använd en alternativ färgkarta typisk för alla Amiga-spel. Det här är det "
+"mala beteendet"
#: engines/agi/detection.cpp:167
-#, fuzzy
msgid "Mouse support"
-msgstr "Skipp-stöd"
+msgstr "Musstöd"
#: engines/agi/detection.cpp:168
msgid ""
"Enables mouse support. Allows to use mouse for movement and in game menus."
msgstr ""
+"Aktiverar musstöd. Möjliggör användning av musen för rörelser och i "
+"spelmenyer."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "Återställ spel:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "Återställ"
@@ -2399,13 +2406,12 @@ msgid "Cutscene file '%s' not found!"
msgstr "Filmscensfilen '%s' hittades ej!"
#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
-#, fuzzy
msgid "Color Blind Mode"
-msgstr "Klickläge"
+msgstr "Färgblint läge"
#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
msgid "Enable Color Blind Mode by default"
-msgstr ""
+msgstr "Aktivera färgblint läge som standard"
#: engines/drascula/saveload.cpp:47
msgid ""
@@ -2461,11 +2467,11 @@ msgstr "Kunde inte spara spelet."
#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
msgid "Gore Mode"
-msgstr ""
+msgstr "Våldsamt läge"
#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
msgid "Enable Gore Mode when available"
-msgstr ""
+msgstr "Aktivera våldsamt läge om tillgängligt"
#. I18N: Studio audience adds an applause and cheering sounds whenever
#. Malcolm makes a joke.
@@ -2597,6 +2603,13 @@ msgid ""
"Do you wish to use this save game file with ScummVM?\n"
"\n"
msgstr ""
+"Följande originalspardata hittades i sökvägen för ditt spel:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Vill du använda den här spardatan med ScummVM?\n"
+"\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:590
#, c-format
@@ -2604,6 +2617,8 @@ msgid ""
"A save game file was found in the specified slot %d. Overwrite?\n"
"\n"
msgstr ""
+"En sparfil hittades på den angivna platsen %d. Vill du skriva över den?\n"
+"\n"
#: engines/kyra/saveload_eob.cpp:623
#, c-format
@@ -2615,6 +2630,11 @@ msgid ""
"'import_savefile'.\n"
"\n"
msgstr ""
+"%d originalspardata har importerats till ScummVM.\n"
+"Om du vill importera originalspardata manuellt måste du öppna "
+"debuggkonsolen\n"
+"och använda kommandot 'import_savefile'.\n"
+"\n"
#. I18N: Option for fast scene switching
#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
@@ -2667,10 +2687,20 @@ msgstr ""
"Kan inte spara data i position %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+#, fuzzy
+msgid "Load file"
+msgstr "Ladda spel:"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "Laddar speldata..."
+#: engines/parallaction/saveload.cpp:212
+#, fuzzy
+msgid "Save file"
+msgstr "Spara spelet:"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "Sparar speldata..."
@@ -2754,21 +2784,19 @@ msgstr "Använd alternativt spelintro (endast CD-version)"
#: engines/sci/detection.cpp:374
msgid "Skip EGA dithering pass (full color backgrounds)"
-msgstr ""
+msgstr "Skippa EGA-gitterpass (bakgrunder i full färg)"
#: engines/sci/detection.cpp:375
msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
-msgstr ""
+msgstr "Skippa gitterpass i EGA-spel. Grafik visas i full färg."
#: engines/sci/detection.cpp:384
-#, fuzzy
msgid "Enable high resolution graphics"
-msgstr "Aktivera livmätare"
+msgstr "Aktivera högupplöst grafik"
#: engines/sci/detection.cpp:385
-#, fuzzy
msgid "Enable high resolution graphics/content"
-msgstr "Aktivera livmätare"
+msgstr "Aktivera högupplöst grafik/innehåll"
#: engines/sci/detection.cpp:394
msgid "Prefer digital sound effects"
@@ -2841,13 +2869,11 @@ msgstr "Spelet pausat. Tryck MELLANSLAG för att fortsätta."
#. "Moechten Sie wirklich neu starten? (J/N)J"
#. Will react to J as 'Yes'
#: engines/scumm/dialogs.cpp:183
-#, fuzzy
msgid "Are you sure you want to restart? (Y/N)Y"
msgstr "Är du säker på att du vill starta om? (J/N)J"
#. I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
#: engines/scumm/dialogs.cpp:185
-#, fuzzy
msgid "Are you sure you want to quit? (Y/N)Y"
msgstr "Är du säker på att du vill avsluta? (J/N)J"
@@ -3357,25 +3383,24 @@ msgid "Third kid"
msgstr "Tredje ungen"
#: engines/scumm/help.cpp:292
-#, fuzzy
msgid "Toggle Inventory/IQ Points display"
-msgstr "Aktivera centrerad dataskärm"
+msgstr "Visa inventarie/IQ-poäng"
#: engines/scumm/help.cpp:293
msgid "Toggle Keyboard/Mouse Fighting (*)"
-msgstr ""
+msgstr "Aktivera slagsmål med tangentbord/mus (*)"
#: engines/scumm/help.cpp:295
msgid "* Keyboard Fighting is always on,"
-msgstr ""
+msgstr "(*) Slagsmål med tangentbord är alltid på,"
#: engines/scumm/help.cpp:296
msgid " so despite the in-game message this"
-msgstr ""
+msgstr "så trots meddelandet i spelet"
#: engines/scumm/help.cpp:297
msgid " actually toggles Mouse Fighting Off/On"
-msgstr ""
+msgstr "aktiverar det här endast slagsmål med mus."
#: engines/scumm/help.cpp:304
msgid "Fighting controls (numpad):"
@@ -3412,7 +3437,7 @@ msgstr "Slå lågt"
#: engines/scumm/help.cpp:315
msgid "Sucker punch"
-msgstr ""
+msgstr "Smocka"
#: engines/scumm/help.cpp:318
msgid "These are for Indy on left."
@@ -3471,23 +3496,20 @@ msgid "Fly to lower right"
msgstr "Flyg åt nedre höger"
#: engines/scumm/input.cpp:580
-#, fuzzy
msgid "Snap scroll on"
-msgstr "Mjuk rullning"
+msgstr "Snäpprullning på"
#: engines/scumm/input.cpp:582
msgid "Snap scroll off"
-msgstr ""
+msgstr "Snäpprullning av"
#: engines/scumm/input.cpp:595
-#, fuzzy
msgid "Music volume: "
-msgstr "Musikvolym:"
+msgstr "Musikvolym: "
#: engines/scumm/input.cpp:612
-#, fuzzy
msgid "Subtitle speed: "
-msgstr "Texthastighet:"
+msgstr "Texthastighet: "
#: engines/scumm/scumm.cpp:1832
#, c-format
@@ -3499,27 +3521,88 @@ msgstr ""
"men %s saknas. Använder AdLib istället."
#: engines/scumm/scumm.cpp:2644
-#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
"Tentacle game directory, and the game has to be added to ScummVM."
msgstr ""
-"Vanligtvis hade Maniac Mansion startat nu, men ScummVM kan inte göra detta "
-"än. För att spela spelet, gå till \"Lägg till spel\" i ScummVM:s huvudmeny "
-"och välj \"Maniac\"-katalogen inuti \"Tentacle\" katalogen."
+"Vanligtvis hade Maniac Mansion startat nu, men för att det ska fungera måste "
+"Maniac Mansion-filerna placeras i 'Maniac'-katalogen i 'Tentacle'-katalogen. "
+"Spelet måste även läggas till i ScummVM."
#: engines/scumm/players/player_v3m.cpp:129
msgid ""
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."
msgstr ""
+"Kunde inte hitta Macintosh-programmet för 'Loom'\n"
+"för att läsa instrumenten. Musiken kommer att avaktiveras."
#: 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 ""
+"Kunde inte hitta Macintosh-programmet för 'Monkey Island'\n"
+"för att läsa instrumenten. Musiken kommer att avaktiveras."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Använd originalskärmar för spara/ladda"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"Filknappen i spelet visar originalskärmen för spara/ladda istället för "
+"ScummVM-menyn"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Pixliga scenövergångar"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "En slumpmässig pixelövergång visas vid scenbyten"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Visa inte aktiveringspunkter vid musrörelse"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"Visar endast namn för aktiveringspunkter när du klickar på en "
+"aktiveringspunkt eller handlingsknapp"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Visa karaktärsporträtt"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Visa porträtt för karaktärerna under dialoger"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Låt dialogrutor glida in"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr ""
+"Låter gränssnittets dialogrutor glida in i bilden istället för att bara visa "
+"dem direkt"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Genomskinliga fönster"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Visar fönster med en delvis genomskinlig bakgrund"
#: engines/sky/compact.cpp:130
msgid ""
@@ -3601,7 +3684,7 @@ msgstr "Behåll den nya"
#: engines/sword1/logic.cpp:1633
msgid "This is the end of the Broken Sword 1 Demo"
-msgstr "Här slutar Broken Sword 1 demon"
+msgstr "Här slutar Broken Sword 1-demon"
#: engines/sword2/animation.cpp:425
msgid ""
@@ -3627,56 +3710,53 @@ msgid ""
"executable. Please decompress it"
msgstr ""
"Teenagent.dat-filen är komprimerad och zlib har inte inkluderats i det här "
-"programmet. Var god dekomprimera den"
+"programmet. Var god dekomprimera den"
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
-msgstr ""
+msgstr "Visa FPS-räknare"
#: engines/wintermute/detection.cpp:59
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
+"Visar det aktuella antalet bildrutor per sekund i det övre vänstra hörnet"
#: engines/zvision/detection_tables.h:52
-#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Använder originalskärmarna för spara/ladda istället för ScummVM:s"
+msgstr "Använd originalskärmarna för spara/ladda istället för ScummVM:s"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr ""
+msgstr "Dubbel FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
-msgstr ""
+msgstr "Öka antalet bildrutor per sekund från 30 till 60"
#: engines/zvision/detection_tables.h:71
-#, fuzzy
msgid "Enable Venus"
-msgstr "Aktivera heliumläge"
+msgstr "Aktivera Venus"
#: engines/zvision/detection_tables.h:72
-#, fuzzy
msgid "Enable the Venus help system"
-msgstr "Aktivera heliumläge"
+msgstr "Aktivera Venus-hjälpsystemet"
#: engines/zvision/detection_tables.h:81
msgid "Disable animation while turning"
-msgstr ""
+msgstr "Avaktivera animering när skärmen vänds"
#: engines/zvision/detection_tables.h:82
msgid "Disable animation while turning in panorama mode"
-msgstr ""
+msgstr "Avaktivera animering medan skärmen vänds i panorama-läge"
#: engines/zvision/detection_tables.h:91
msgid "Use high resolution MPEG video"
-msgstr ""
+msgstr "Använd högupplöst MPEG-video"
#: engines/zvision/detection_tables.h:92
-#, fuzzy
msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
msgstr ""
-"Använd de alternativa silverpekarna istället för de normala guldpekarna"
+"Använd högupplöst MPEG-video från DVD-versionen istället för lågupplöst AVI"
#~ msgid "EGA undithering"
#~ msgstr "EGA anti-gitter"
@@ -3726,10 +3806,6 @@ msgstr ""
#~ msgid "Enable Roland GS Mode"
#~ msgstr "Aktivera Roland GS-läge"
-#, fuzzy
-#~ msgid "Save game failed!"
-#~ msgstr "Spara spelet:"
-
#~ msgctxt "lowres"
#~ msgid "Add Game..."
#~ msgstr "Lägg till spel..."
diff --git a/po/uk_UA.po b/po/uk_UA.po
index 940b86d605..5ab87a4155 100644
--- a/po/uk_UA.po
+++ b/po/uk_UA.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
-"POT-Creation-Date: 2016-02-01 21:58+0000\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
"PO-Revision-Date: 2015-11-06 10:07+0300\n"
"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
"Language-Team: Ukrainian\n"
@@ -592,16 +592,16 @@ msgid "Search:"
msgstr "¿ÞèãÚ:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/myst.cpp:245 engines/mohawk/riven.cpp:718
-#: engines/pegasus/pegasus.cpp:353 engines/tsage/scenes.cpp:600
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
msgid "Load game:"
msgstr "·ÐÒÐÝâÐÖØâØ Óàã:"
#: gui/launcher.cpp:685 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/cruise/menu.cpp:214 engines/mohawk/myst.cpp:245
-#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
msgid "Load"
msgstr "·ÐÒÐÝâÐÖØâØ"
@@ -764,7 +764,7 @@ msgid "Special dithering modes supported by some games"
msgstr "ÁßÕæöÐÛìÝö àÕÖØÜØ àÐáâàãÒÐÝÝï, ïÚö ßöÔâàØÜãîâì ÔÕïÚö öÓàØ"
#: gui/options.cpp:758
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2313
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
msgid "Fullscreen mode"
msgstr "¿ÞÒÝÞÕÚàÐÝÝØÙ àÕÖØÜ"
@@ -1361,12 +1361,12 @@ msgstr "PC-9821 (256 ÚÞÛìÞàöÒ)"
msgid "PC-9801 (16 Colors)"
msgstr "PC-9801 (16 ÚÞÛìÞàöÒ)"
-#: common/rendermode.cpp:71
+#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
msgstr "Hercules ×ÕÛÕÝØÙ"
-#: common/rendermode.cpp:72
+#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
msgstr "Hercules ÑãàèâØÝÝØÙ"
@@ -1417,11 +1417,15 @@ msgctxt "lowres"
msgid "~R~eturn to Launcher"
msgstr "~¿~ÞÒÕà.Ò ÓÞÛÞÒÝÕ ÜÕÝî"
-#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:714
-#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
-#: engines/dreamweb/saveload.cpp:261 engines/neverhood/menumodule.cpp:877
-#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:769
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save game:"
msgstr "·ÑÕàÕÓâØ Óàã: "
@@ -1430,11 +1434,15 @@ msgstr "·ÑÕàÕÓâØ Óàã: "
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
-#: engines/agi/saveload.cpp:714 engines/cruise/menu.cpp:212
-#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
-#: engines/neverhood/menumodule.cpp:877 engines/pegasus/pegasus.cpp:377
-#: engines/sci/engine/kfile.cpp:769 engines/scumm/dialogs.cpp:188
-#: engines/toltecs/menu.cpp:281 engines/tsage/scenes.cpp:598
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
msgid "Save"
msgstr "·ÐßØáÐâØ"
@@ -1759,19 +1767,19 @@ msgctxt "lowres"
msgid "Normal (no scaling)"
msgstr "±Õ× ×ÑöÛìèÕÝÝï"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2212
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
msgid "Enabled aspect ratio correction"
msgstr "ºÞàÕÚæöî áßöÒÒöÔÝÞèÕÝÝï áâÞàöÝ ãÒöÜÚÝÕÝÞ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2218
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
msgid "Disabled aspect ratio correction"
msgstr "ºÞàÕÚæöî áßöÒÒöÔÝÞèÕÝÝï áâÞàöÝ ÒØÜÚÝÕÝÞ"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2273
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
msgid "Active graphics filter:"
msgstr "¿ÞâÞçÝØÙ ÓàÐäöçÝØÙ äöÛìâà:"
-#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2315
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
msgid "Windowed mode"
msgstr "²öÚÞÝÝØÙ àÕÖØÜ"
@@ -2338,15 +2346,23 @@ msgstr ""
"²ÚÛîçÐô ßöÔâàØÜÚã ÜØèö. ´Þ×ÒÞÛïô ÒØÚÞàØáâÞÒãÒÐâØ ÜØèã ÔÛï ßÕàÕáãÒÐÝÝï âÐ "
"ãßàÐÒÛöÝÝï ÜÕÝî."
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore game:"
msgstr "²öÔÝÞÒØâØ Óàã:"
-#: engines/agi/saveload.cpp:727 engines/drascula/saveload.cpp:349
-#: engines/dreamweb/saveload.cpp:169 engines/neverhood/menumodule.cpp:890
-#: engines/sci/engine/kfile.cpp:868 engines/toltecs/menu.cpp:256
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
msgid "Restore"
msgstr "²öÔÝÞÒØâØ"
@@ -2668,10 +2684,18 @@ msgstr ""
"½Õ ÜÞÖã ×ÑÕàÕÓâØ Óàã ã áÛÞâ %i\n"
"\n"
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "·ÐÒÐÝâÐÖØâØ äÐÙÛ"
+
#: engines/parallaction/saveload.cpp:204
msgid "Loading game..."
msgstr "·ÐÒÐÝâÐÖãî Óàã..."
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "·ÑÕàÕÓâØ äÐÙÛ"
+
#: engines/parallaction/saveload.cpp:219
msgid "Saving game..."
msgstr "·ÑÕàÕÖãî Óàã..."
@@ -3518,6 +3542,62 @@ msgstr ""
"½Õ ÒÐÔÛÞáï ×ÝÐÙâØ äÐÙÛ ßàÞÓàÐÜØ 'Monkey Island' Macintosh ÐÑØ ßàÞçØâÐâØ\n"
"× ÝìÞÓÞ öÝáâàãÜÕÝâØ. ¼ã×ØÚã ÑãÛÞ ÒØÜÚÝÕÝÞ."
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "²ØÚÞàØáâÞÒãÒÐâØ ÞàØÓöÝÐÛìÝØÙ ÕÚàÐÝ ×ÑÕàÕÖÕÝÝï"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"ºÝÞßÚÐ \"ÄÐÙÛØ\" ã Óàö ßÞÚÐ×ãÒÐâØÜÕ ÞàØÓöÝÐÛìÝØÙ ÕÚàÐÝ ×ÑÕàÕÖÕÝÝï "
+"×ÐÜöáâì ÜÕÝî ScummVM"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "¿öÕáÕÛìÞÒÐÝö ßÕàÕåÞÔØ ÜöÖ áæÕÝÐÜØ"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "¿àØ ×ÜöÝö áæÕÝ ÑãÔÕ ÒöÔÑãÒÐâØáï ßÕàÕåöÔ ã ÒØÓÛïÔö ÒØßÐÔÚÞÒØå ßöÚáÕÛöÒ"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "½Õ ßÞÚÐ×ãÒÐâØ æöÚÐÒö âÞçÚØ ßàØ ÝÐÒÕÔÕÝÝö ÜØèÕî"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr ""
+"¿ÞÚÐ×ãÒÐâØ ÝÐ×ÒØ æöÚÐÒØå âÞçÞÚ âöÛìÚØ ßöáÛï ÑÕ×ßÞáÕàÕÔÝìÞÓÞ ÚÛöÚã ßÞ ÝØÜ "
+"ÐÑÞ Ôö÷ × ÝØÜØ"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "¿ÞÚÐ×ãÒÐâØ ßÞàâàÕâØ ÓÕàÞ÷Ò"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "¿ÞÚÐ×ãÒÐâØ ßÞàâàÕâØ ÓÕàÞ÷Ò ßöÔ çÐá áßöÛÚãÒÐÝÝï"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "·ÐÒÞÔØâØ ÔöÐÛÞÓØ ÔÞ ÞÑ×Þàã"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "·ÐÒÞÔØâØ ÔöÐÛÞÓØ ÔÞ ÞÑ×Þàã ×ÐÜöáâì ÜØââôÒÞÓÞ ßÞÚÐ×ã"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "¿àÞ×Þàö ÒöÚÝÐ"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "¿ÞÚÐ×ãÒÐâØ ÒöÚÝÐ × çÐáâÚÞÒÞ ßàÞ×ÞàØÜ âÛÞÜ"
+
#: engines/sky/compact.cpp:130
msgid ""
"Unable to find \"sky.cpt\" file!\n"
diff --git a/po/zh-Latn_CN.po b/po/zh-Latn_CN.po
new file mode 100644
index 0000000000..12105429a7
--- /dev/null
+++ b/po/zh-Latn_CN.po
@@ -0,0 +1,3730 @@
+# LANGUAGE translation for ScummVM.
+# Copyright (C) YEAR ScummVM Team
+# This file is distributed under the same license as the ScummVM package.
+# Chenbo Li <lichenbo1949@gmail.com>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ScummVM 1.9.0git\n"
+"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n"
+"POT-Creation-Date: 2016-02-20 21:22+0000\n"
+"PO-Revision-Date: 2016-03-15 04:09-0700\n"
+"Last-Translator: Chenbo Li <lichenbo1949@gmail.com>\n"
+"Language-Team: Chenbo Li <lichenbo1949@gmail.com>\n"
+"Language: Chinese Pinyin (Mandarin)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: gui/about.cpp:94
+#, c-format
+msgid "(built on %s)"
+msgstr "(Bianyiyu %s)"
+
+#: gui/about.cpp:101
+msgid "Features compiled in:"
+msgstr "Gongneng BianyiYu"
+
+#: gui/about.cpp:110
+msgid "Available engines:"
+msgstr "KeyongDeYinQing"
+
+#: gui/browser.cpp:68 gui/browser_osx.mm:104
+msgid "Show hidden files"
+msgstr "Xianshi Yincang Wenjian"
+
+#: gui/browser.cpp:68
+msgid "Show files marked with the hidden attribute"
+msgstr "Xianshi Suoyou Yincang Shuxing Wenjian"
+
+#: gui/browser.cpp:72
+msgid "Go up"
+msgstr "ShangYiJi"
+
+#: gui/browser.cpp:72 gui/browser.cpp:74
+msgid "Go to previous directory level"
+msgstr "Fanhui Zhiqian Mulu"
+
+#: gui/browser.cpp:74
+msgctxt "lowres"
+msgid "Go up"
+msgstr "ShangYiJi"
+
+#: gui/browser.cpp:75 gui/chooser.cpp:46 gui/editrecorddialog.cpp:67
+#: gui/filebrowser-dialog.cpp:64 gui/fluidsynth-dialog.cpp:152
+#: gui/KeysDialog.cpp:43 gui/launcher.cpp:351 gui/massadd.cpp:95
+#: gui/options.cpp:1237 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:70
+#: gui/recorderdialog.cpp:156 gui/saveload-dialog.cpp:216
+#: gui/saveload-dialog.cpp:276 gui/saveload-dialog.cpp:547
+#: gui/saveload-dialog.cpp:931 gui/themebrowser.cpp:55 engines/engine.cpp:546
+#: backends/events/default/default-events.cpp:196
+#: backends/events/default/default-events.cpp:218
+#: backends/platform/wii/options.cpp:48 engines/drascula/saveload.cpp:49
+#: engines/parallaction/saveload.cpp:274 engines/scumm/dialogs.cpp:191
+#: engines/sword1/control.cpp:865
+msgid "Cancel"
+msgstr "Quxiao"
+
+#: gui/browser.cpp:76 gui/browser_osx.mm:103 gui/chooser.cpp:47
+#: gui/filebrowser-dialog.cpp:65 gui/themebrowser.cpp:56
+msgid "Choose"
+msgstr "Xuanze"
+
+#: gui/editrecorddialog.cpp:58
+msgid "Author:"
+msgstr "Zuozhe:"
+
+#: gui/editrecorddialog.cpp:59 gui/launcher.cpp:204
+msgid "Name:"
+msgstr "Xingming:"
+
+#: gui/editrecorddialog.cpp:60
+msgid "Notes:"
+msgstr "Beizhu:"
+
+#: gui/editrecorddialog.cpp:68 gui/predictivedialog.cpp:74
+msgid "Ok"
+msgstr "Queding"
+
+#: gui/filebrowser-dialog.cpp:49
+msgid "Choose file for loading"
+msgstr "Xuanze YaoJiazai de Wenjian"
+
+#: gui/filebrowser-dialog.cpp:49
+msgid "Enter filename for saving"
+msgstr "Shuru Baocun de Wenjianming"
+
+#: gui/filebrowser-dialog.cpp:132
+msgid "Do you really want to overwrite the file?"
+msgstr "Nin Shifou Queding Fugai Ciwenjian"
+
+#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
+#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
+#: backends/events/symbiansdl/symbiansdl-events.cpp:186
+#: backends/platform/wince/CEActionsPocket.cpp:326
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+#: backends/platform/wince/CELauncherDialog.cpp:83
+#: engines/kyra/saveload_eob.cpp:557 engines/kyra/saveload_eob.cpp:590
+msgid "Yes"
+msgstr "Shi"
+
+#: gui/filebrowser-dialog.cpp:132 gui/fluidsynth-dialog.cpp:217
+#: gui/launcher.cpp:795 gui/launcher.cpp:943 gui/launcher.cpp:1002
+#: backends/events/symbiansdl/symbiansdl-events.cpp:186
+#: backends/platform/wince/CEActionsPocket.cpp:326
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+#: backends/platform/wince/CELauncherDialog.cpp:83
+#: engines/kyra/saveload_eob.cpp:557 engines/kyra/saveload_eob.cpp:590
+msgid "No"
+msgstr "Fou"
+
+#: gui/fluidsynth-dialog.cpp:68
+msgid "Reverb"
+msgstr "Hunxiang"
+
+#: gui/fluidsynth-dialog.cpp:70 gui/fluidsynth-dialog.cpp:102
+msgid "Active"
+msgstr "Jihuo"
+
+#: gui/fluidsynth-dialog.cpp:72
+msgid "Room:"
+msgstr "Fangjian:"
+
+#: gui/fluidsynth-dialog.cpp:79
+msgid "Damp:"
+msgstr "Shiqi:"
+
+#: gui/fluidsynth-dialog.cpp:86
+msgid "Width:"
+msgstr "Kuandu:"
+
+#: gui/fluidsynth-dialog.cpp:93 gui/fluidsynth-dialog.cpp:111
+msgid "Level:"
+msgstr "Jibie:"
+
+#: gui/fluidsynth-dialog.cpp:100
+msgid "Chorus"
+msgstr "Hechang:"
+
+#: gui/fluidsynth-dialog.cpp:104
+msgid "N:"
+msgstr "N:"
+
+#: gui/fluidsynth-dialog.cpp:118
+msgid "Speed:"
+msgstr "Sudu:"
+
+#: gui/fluidsynth-dialog.cpp:125
+msgid "Depth:"
+msgstr "Shendu:"
+
+#: gui/fluidsynth-dialog.cpp:132
+msgid "Type:"
+msgstr "Leixing:"
+
+#: gui/fluidsynth-dialog.cpp:135
+msgid "Sine"
+msgstr "Zhengxian"
+
+#: gui/fluidsynth-dialog.cpp:136
+msgid "Triangle"
+msgstr "Sanjiaoxing"
+
+#: gui/fluidsynth-dialog.cpp:138 gui/options.cpp:1168
+msgid "Misc"
+msgstr "Zaxiang"
+
+#: gui/fluidsynth-dialog.cpp:140
+msgid "Interpolation:"
+msgstr "Chazhi:"
+
+#: gui/fluidsynth-dialog.cpp:143
+msgid "None (fastest)"
+msgstr "Wu (Zuikuai)"
+
+#: gui/fluidsynth-dialog.cpp:144
+msgid "Linear"
+msgstr "Xianxing"
+
+#: gui/fluidsynth-dialog.cpp:145
+msgid "Fourth-order"
+msgstr "DiSiXu"
+
+#: gui/fluidsynth-dialog.cpp:146
+msgid "Seventh-order"
+msgstr "DiQiXu"
+
+#: gui/fluidsynth-dialog.cpp:150
+msgid "Reset"
+msgstr "Chongzhi"
+
+#: gui/fluidsynth-dialog.cpp:150
+msgid "Reset all FluidSynth settings to their default values."
+msgstr "Chongzhi Suoyou de FluidSynth Shezhi"
+
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:42 gui/launcher.cpp:352
+#: gui/launcher.cpp:1050 gui/launcher.cpp:1054 gui/massadd.cpp:92
+#: gui/options.cpp:1238 gui/saveload-dialog.cpp:932 engines/engine.cpp:465
+#: engines/engine.cpp:476 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:408 engines/parallaction/saveload.cpp:274
+#: engines/scumm/dialogs.cpp:193 engines/scumm/scumm.cpp:1834
+#: engines/scumm/players/player_v3m.cpp:130
+#: engines/scumm/players/player_v5m.cpp:108 engines/sky/compact.cpp:131
+#: engines/sky/compact.cpp:141 engines/sword1/animation.cpp:524
+#: engines/sword1/animation.cpp:545 engines/sword1/animation.cpp:561
+#: engines/sword1/animation.cpp:569 engines/sword1/control.cpp:865
+#: engines/sword1/logic.cpp:1633 engines/sword2/animation.cpp:425
+#: engines/sword2/animation.cpp:445 engines/sword2/animation.cpp:461
+#: engines/sword2/animation.cpp:471
+msgid "OK"
+msgstr "Queding"
+
+#: gui/fluidsynth-dialog.cpp:217
+msgid ""
+"Do you really want to reset all FluidSynth settings to their default values?"
+msgstr "Ni Shifou Yao Chongzhi Suoyou de FluidSynth Shezhi?"
+
+#: gui/gui-manager.cpp:119 backends/keymapper/remap-dialog.cpp:53
+#: engines/scumm/help.cpp:126 engines/scumm/help.cpp:141
+#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:192
+#: engines/scumm/help.cpp:210
+msgid "Close"
+msgstr "Guanbi"
+
+#: gui/gui-manager.cpp:122
+msgid "Mouse click"
+msgstr "Shubiao Danji"
+
+#: gui/gui-manager.cpp:126 base/main.cpp:322
+msgid "Display keyboard"
+msgstr "Xianshi Jianpan"
+
+#: gui/gui-manager.cpp:130 base/main.cpp:326
+msgid "Remap keys"
+msgstr "Yingshe Jianwei"
+
+#: gui/gui-manager.cpp:133 base/main.cpp:329 engines/scumm/help.cpp:87
+msgid "Toggle fullscreen"
+msgstr "Quanping Qiehuan"
+
+#: gui/KeysDialog.cpp:41
+msgid "Map"
+msgstr "Yingshe"
+
+#: gui/KeysDialog.cpp:49
+msgid "Select an action and click 'Map'"
+msgstr "Xuanze Yige Xingwei bing Danji ‘Yingshe’"
+
+#: gui/KeysDialog.cpp:80 gui/KeysDialog.cpp:102 gui/KeysDialog.cpp:141
+#, c-format
+msgid "Associated key : %s"
+msgstr "Guanlian Anjian : %s"
+
+#: gui/KeysDialog.cpp:82 gui/KeysDialog.cpp:104 gui/KeysDialog.cpp:143
+#, c-format
+msgid "Associated key : none"
+msgstr "Guanlian Anjian : Wu"
+
+#: gui/KeysDialog.cpp:90
+msgid "Please select an action"
+msgstr "Qing Xuanze Xingwei"
+
+#: gui/KeysDialog.cpp:106
+msgid "Press the key to associate"
+msgstr "Anxia Anjian lai Guanlian"
+
+#: gui/KeysDialog.cpp:145 gui/KeysDialog.h:36
+msgid "Choose an action to map"
+msgstr "Xuanze yao Yingshe de Xingwei"
+
+#: gui/launcher.cpp:193
+msgid "Game"
+msgstr "Youxi"
+
+#: gui/launcher.cpp:197
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:197 gui/launcher.cpp:199 gui/launcher.cpp:200
+msgid ""
+"Short game identifier used for referring to saved games and running the game "
+"from the command line"
+msgstr ""
+"Yige Jianduan de Biaoshifu lai Baocun Youxi huo Cong Minglinghang zhong "
+"Yunxing"
+
+#: gui/launcher.cpp:199
+msgctxt "lowres"
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:204 gui/launcher.cpp:206 gui/launcher.cpp:207
+msgid "Full title of the game"
+msgstr "Youxi Quanming"
+
+#: gui/launcher.cpp:206
+msgctxt "lowres"
+msgid "Name:"
+msgstr "Mingcheng:"
+
+#: gui/launcher.cpp:210
+msgid "Language:"
+msgstr "Yuyan:"
+
+#: gui/launcher.cpp:210 gui/launcher.cpp:211
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Youxi de Yuyan. CiXiang buhui jiang Yige XibanyaYu Banben Zhuancheng Yingwen"
+
+#: gui/launcher.cpp:212 gui/launcher.cpp:226 gui/options.cpp:87
+#: gui/options.cpp:735 gui/options.cpp:748 gui/options.cpp:1208
+#: audio/null.cpp:41
+msgid "<default>"
+msgstr "<Moren>"
+
+#: gui/launcher.cpp:222
+msgid "Platform:"
+msgstr "Pingtai:"
+
+#: gui/launcher.cpp:222 gui/launcher.cpp:224 gui/launcher.cpp:225
+msgid "Platform the game was originally designed for"
+msgstr "Youxi Chushi Yunxing de Pingtai:"
+
+#: gui/launcher.cpp:224
+msgctxt "lowres"
+msgid "Platform:"
+msgstr "Pingtai:"
+
+#: gui/launcher.cpp:237
+msgid "Engine"
+msgstr "Yinqing"
+
+#: gui/launcher.cpp:245 gui/options.cpp:1071 gui/options.cpp:1088
+msgid "Graphics"
+msgstr "Tuxiang"
+
+#: gui/launcher.cpp:245 gui/options.cpp:1071 gui/options.cpp:1088
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:248
+msgid "Override global graphic settings"
+msgstr "Fugai Quanju Tuxiang Shezhi"
+
+#: gui/launcher.cpp:250
+msgctxt "lowres"
+msgid "Override global graphic settings"
+msgstr "Fugai Quanju Tuxiang Shezhi"
+
+#: gui/launcher.cpp:257 gui/options.cpp:1094
+msgid "Audio"
+msgstr "Yinpin"
+
+#: gui/launcher.cpp:260
+msgid "Override global audio settings"
+msgstr "Fugai Quanju Yinpin Shezhi"
+
+#: gui/launcher.cpp:262
+msgctxt "lowres"
+msgid "Override global audio settings"
+msgstr "Fugai QUanju Yinpin Shezhi"
+
+#: gui/launcher.cpp:271 gui/options.cpp:1099
+msgid "Volume"
+msgstr "Yinliang"
+
+#: gui/launcher.cpp:273 gui/options.cpp:1101
+msgctxt "lowres"
+msgid "Volume"
+msgstr "YinLiang"
+
+#: gui/launcher.cpp:276
+msgid "Override global volume settings"
+msgstr "Fugai Quanju YinLiang Shezhi"
+
+#: gui/launcher.cpp:278
+msgctxt "lowres"
+msgid "Override global volume settings"
+msgstr "Fugai Quanju YinLiang Shezhi"
+
+#: gui/launcher.cpp:286 gui/options.cpp:1109
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:289
+msgid "Override global MIDI settings"
+msgstr "Fugai Quanju MIDI Shezhi"
+
+#: gui/launcher.cpp:291
+msgctxt "lowres"
+msgid "Override global MIDI settings"
+msgstr "Fugai Quanju MIDI Shezhi"
+
+#: gui/launcher.cpp:300 gui/options.cpp:1115
+msgid "MT-32"
+msgstr "MT-32"
+
+#: gui/launcher.cpp:303
+msgid "Override global MT-32 settings"
+msgstr "Fugai Quanju MT-32 Shezhi"
+
+#: gui/launcher.cpp:305
+msgctxt "lowres"
+msgid "Override global MT-32 settings"
+msgstr "Fugai Quanju MT-32 Shezhi"
+
+#: gui/launcher.cpp:314 gui/options.cpp:1122
+msgid "Paths"
+msgstr "Lujing"
+
+#: gui/launcher.cpp:316 gui/options.cpp:1124
+msgctxt "lowres"
+msgid "Paths"
+msgstr "Lujing"
+
+#: gui/launcher.cpp:323
+msgid "Game Path:"
+msgstr "Youxi Lujing:"
+
+#: gui/launcher.cpp:325
+msgctxt "lowres"
+msgid "Game Path:"
+msgstr "Youxi Lujing:"
+
+#: gui/launcher.cpp:330 gui/options.cpp:1148
+msgid "Extra Path:"
+msgstr "Qita Lujing:"
+
+#: gui/launcher.cpp:330 gui/launcher.cpp:332 gui/launcher.cpp:333
+msgid "Specifies path to additional data used by the game"
+msgstr "Zhiding Youxi Suoyong de Shuju de Cunfang Lujing"
+
+#: gui/launcher.cpp:332 gui/options.cpp:1150
+msgctxt "lowres"
+msgid "Extra Path:"
+msgstr "Qita Lujing:"
+
+#: gui/launcher.cpp:339 gui/options.cpp:1132
+msgid "Save Path:"
+msgstr "Baocun Lujing:"
+
+#: gui/launcher.cpp:339 gui/launcher.cpp:341 gui/launcher.cpp:342
+#: gui/options.cpp:1132 gui/options.cpp:1134 gui/options.cpp:1135
+msgid "Specifies where your saved games are put"
+msgstr "Zhiding Nin Jiang Youxi Baocun Zai le Nali"
+
+#: gui/launcher.cpp:341 gui/options.cpp:1134
+msgctxt "lowres"
+msgid "Save Path:"
+msgstr "Baocun Lujing:"
+
+#: gui/launcher.cpp:360 gui/launcher.cpp:459 gui/launcher.cpp:517
+#: gui/launcher.cpp:571 gui/options.cpp:1143 gui/options.cpp:1151
+#: gui/options.cpp:1160 gui/options.cpp:1275 gui/options.cpp:1281
+#: gui/options.cpp:1289 gui/options.cpp:1319 gui/options.cpp:1325
+#: gui/options.cpp:1332 gui/options.cpp:1425 gui/options.cpp:1428
+#: gui/options.cpp:1440
+msgctxt "path"
+msgid "None"
+msgstr "Wu"
+
+#: gui/launcher.cpp:365 gui/launcher.cpp:465 gui/launcher.cpp:575
+#: gui/options.cpp:1269 gui/options.cpp:1313 gui/options.cpp:1431
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Moren"
+
+#: gui/launcher.cpp:510 gui/options.cpp:1434
+msgid "Select SoundFont"
+msgstr "Xuanze SoundFont"
+
+#: gui/launcher.cpp:529 gui/launcher.cpp:682
+msgid "Select directory with game data"
+msgstr "Xuanze Youxi Shuju Mulu"
+
+#: gui/launcher.cpp:547
+msgid "Select additional game directory"
+msgstr "Xuanze Qita Youxi Mulu"
+
+#: gui/launcher.cpp:559 gui/options.cpp:1377
+msgid "Select directory for saved games"
+msgstr "Xuanze Youxi Baocun Mulu"
+
+#: gui/launcher.cpp:586
+msgid "This game ID is already taken. Please choose another one."
+msgstr "Ci Youxi ID Yi Bei Zhanyong. Qing Xuanze Qita Mingcheng"
+
+#: gui/launcher.cpp:626 engines/dialogs.cpp:111
+msgid "~Q~uit"
+msgstr "~Q~Tuichu"
+
+#: gui/launcher.cpp:626 backends/platform/sdl/macosx/appmenu_osx.mm:106
+msgid "Quit ScummVM"
+msgstr "Tuichu ScummVM"
+
+#: gui/launcher.cpp:627
+msgid "A~b~out..."
+msgstr "~b~Guanyu"
+
+#: gui/launcher.cpp:627 backends/platform/sdl/macosx/appmenu_osx.mm:80
+msgid "About ScummVM"
+msgstr "Guanyu ScummVM"
+
+#: gui/launcher.cpp:628
+msgid "~O~ptions..."
+msgstr "~O~Xuanxiang"
+
+#: gui/launcher.cpp:628
+msgid "Change global ScummVM options"
+msgstr "Genggai ScummVM Quanju Shezhi"
+
+#: gui/launcher.cpp:630
+msgid "~S~tart"
+msgstr "~S~Kaishi"
+
+#: gui/launcher.cpp:630
+msgid "Start selected game"
+msgstr "Kaishi Xuanze de Youxi"
+
+#: gui/launcher.cpp:633
+msgid "~L~oad..."
+msgstr "~L~Jiazai"
+
+#: gui/launcher.cpp:633
+msgid "Load saved game for selected game"
+msgstr "Jiazai Xuanze Baocun de Youxi"
+
+#: gui/launcher.cpp:638
+msgid "~A~dd Game..."
+msgstr "~A~Tianjia Youxi ..."
+
+#: gui/launcher.cpp:638 gui/launcher.cpp:645
+msgid "Hold Shift for Mass Add"
+msgstr "Anzhu Shift Lai Piliang Tianjia"
+
+#: gui/launcher.cpp:640
+msgid "~E~dit Game..."
+msgstr "~E~Bianji Youxi ..."
+
+#: gui/launcher.cpp:640 gui/launcher.cpp:647
+msgid "Change game options"
+msgstr "Genggai Youxi Xuanxiang"
+
+#: gui/launcher.cpp:642
+msgid "~R~emove Game"
+msgstr "~R~Yichu Youxi"
+
+#: gui/launcher.cpp:642 gui/launcher.cpp:649
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "Cong Liebiao zhong YIchu Youxi. Baoliu Youxi Shuju Wenjian"
+
+#: gui/launcher.cpp:645
+msgctxt "lowres"
+msgid "~A~dd Game..."
+msgstr "~A~Tianjia Youxi ..."
+
+#: gui/launcher.cpp:647
+msgctxt "lowres"
+msgid "~E~dit Game..."
+msgstr "~E~Bianji Youxi ..."
+
+#: gui/launcher.cpp:649
+msgctxt "lowres"
+msgid "~R~emove Game"
+msgstr "~R~Yichu Youxi ..."
+
+#: gui/launcher.cpp:657
+msgid "Search in game list"
+msgstr "Zai Youxi Liebiao zhong Sousuo"
+
+#: gui/launcher.cpp:661 gui/launcher.cpp:1224
+msgid "Search:"
+msgstr "Sousuo:"
+
+#: gui/launcher.cpp:685 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/riven.cpp:718 engines/pegasus/pegasus.cpp:353
+#: engines/tsage/scenes.cpp:600
+msgid "Load game:"
+msgstr "Jiazai Youxi:"
+
+#: gui/launcher.cpp:685 engines/dialogs.cpp:115
+#: backends/platform/wince/CEActionsPocket.cpp:267
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+#: engines/cruise/menu.cpp:214 engines/mohawk/riven.cpp:718
+#: engines/parallaction/saveload.cpp:197 engines/pegasus/pegasus.cpp:353
+#: engines/scumm/dialogs.cpp:189 engines/tsage/scenes.cpp:600
+msgid "Load"
+msgstr "Jiazai"
+
+#: gui/launcher.cpp:794
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"Nin Queding yao Yunxing Youxi Piliang Jiance Ma? Zhe You Keneng Hui Zengjia "
+"Daliang Youxi."
+
+#: gui/launcher.cpp:843
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM Wufa Dakai Zhiding Mulu!"
+
+#: gui/launcher.cpp:855
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM zai Zhiding Mulu Zhong Wufa Zhaodao Renhe Youxi!"
+
+#: gui/launcher.cpp:869
+msgid "Pick the game:"
+msgstr "Xuanze Youxi:"
+
+#: gui/launcher.cpp:943
+msgid "Do you really want to remove this game configuration?"
+msgstr "Nin Zhende Xiangyao Yichu Zhege Youxi Peizhi?"
+
+#: gui/launcher.cpp:1001
+msgid "Do you want to load saved game?"
+msgstr "Nin Yao Zairu Baocun de Youxi ma?"
+
+#: gui/launcher.cpp:1050
+msgid "This game does not support loading games from the launcher."
+msgstr "Ci Youxi Bu Zhichi cong Jiazaiqi Zhong Jiazai Youxi."
+
+#: gui/launcher.cpp:1054
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM Wufa Zhaodao Keyi Yunxing Ci Youxi de Yinqing!"
+
+#: gui/launcher.cpp:1161
+msgid "Mass Add..."
+msgstr "PiLiang Zengjia ..."
+
+#: gui/launcher.cpp:1163
+msgid "Record..."
+msgstr "Luxiang ..."
+
+#: gui/massadd.cpp:79 gui/massadd.cpp:82
+msgid "... progress ..."
+msgstr "... Jindu ..."
+
+#: gui/massadd.cpp:259
+msgid "Scan complete!"
+msgstr "Saomiao Wancheng!"
+
+#: gui/massadd.cpp:262
+#, c-format
+msgid "Discovered %d new games, ignored %d previously added games."
+msgstr "Faxian le %d ge Xinyouxi, Hulue %d ge YiTianjia de Youxi"
+
+#: gui/massadd.cpp:266
+#, c-format
+msgid "Scanned %d directories ..."
+msgstr "YiSaomiao %d ge Mulu ..."
+
+#: gui/massadd.cpp:269
+#, c-format
+msgid "Discovered %d new games, ignored %d previously added games ..."
+msgstr "Faxian le %d ge Xinyouxi, Hulue %d ge YiTianjia de Youxi ..."
+
+#: gui/onscreendialog.cpp:101 gui/onscreendialog.cpp:103
+msgid "Stop"
+msgstr "Tingzhi"
+
+#: gui/onscreendialog.cpp:106
+msgid "Edit record description"
+msgstr "Bianji Luxiang Shuoming"
+
+#: gui/onscreendialog.cpp:108
+msgid "Switch to Game"
+msgstr "Qiehuan zhi Youxi"
+
+#: gui/onscreendialog.cpp:110
+msgid "Fast replay"
+msgstr "Kuaisu Huitui"
+
+#: gui/options.cpp:85
+msgid "Never"
+msgstr "Yongbu"
+
+#: gui/options.cpp:85
+msgid "every 5 mins"
+msgstr "Mei 5 Fenzhong"
+
+#: gui/options.cpp:85
+msgid "every 10 mins"
+msgstr "Mei 10 Fenzhong"
+
+#: gui/options.cpp:85
+msgid "every 15 mins"
+msgstr "Mei 15 Fenzhong"
+
+#: gui/options.cpp:85
+msgid "every 30 mins"
+msgstr "Mei 30 Fenzhong"
+
+#: gui/options.cpp:87
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: gui/options.cpp:87
+msgid "11 kHz"
+msgstr "11 kHz"
+
+#: gui/options.cpp:87
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: gui/options.cpp:87
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: gui/options.cpp:87
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: gui/options.cpp:255 gui/options.cpp:479 gui/options.cpp:580
+#: gui/options.cpp:649 gui/options.cpp:857
+msgctxt "soundfont"
+msgid "None"
+msgstr "Wu"
+
+#: gui/options.cpp:389
+msgid "Failed to apply some of the graphic options changes:"
+msgstr "Tuxing Xuanxiang Genggai Shibai:"
+
+#: gui/options.cpp:401
+msgid "the video mode could not be changed."
+msgstr "Shipin Moshi Wufa Genggai."
+
+#: gui/options.cpp:407
+msgid "the fullscreen setting could not be changed"
+msgstr "Quanping Shezhi Wufa Genggai"
+
+#: gui/options.cpp:413
+msgid "the aspect ratio setting could not be changed"
+msgstr "Bili Xuanxiang Wufa Genggai"
+
+#: gui/options.cpp:732
+msgid "Graphics mode:"
+msgstr "Tuxing Moshi:"
+
+#: gui/options.cpp:746
+msgid "Render mode:"
+msgstr "Xuanran Moshi:"
+
+#: gui/options.cpp:746 gui/options.cpp:747
+msgid "Special dithering modes supported by some games"
+msgstr "Youxi Zhichi Teshu de Doudong Moshi"
+
+#: gui/options.cpp:758
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2316
+msgid "Fullscreen mode"
+msgstr "Quanping Moshi"
+
+#: gui/options.cpp:761
+msgid "Aspect ratio correction"
+msgstr "Bili Jiaozheng"
+
+#: gui/options.cpp:761
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "320x200 Youxi Bili Jiaozheng"
+
+#: gui/options.cpp:769
+msgid "Preferred Device:"
+msgstr "Youxian Shebei:"
+
+#: gui/options.cpp:769
+msgid "Music Device:"
+msgstr "Yinyue Shebei:"
+
+#: gui/options.cpp:769 gui/options.cpp:771
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "Zhiding Youxian Shengyin Shebei huo Shengka Moniqi"
+
+#: gui/options.cpp:769 gui/options.cpp:771 gui/options.cpp:772
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Zhiding Shuchu Shengyin Shebei huo Shengka Moniqi"
+
+#: gui/options.cpp:771
+msgctxt "lowres"
+msgid "Preferred Dev.:"
+msgstr "Youxian Shebei:"
+
+#: gui/options.cpp:771
+msgctxt "lowres"
+msgid "Music Device:"
+msgstr "Yinyue Shebei:"
+
+#: gui/options.cpp:798
+msgid "AdLib emulator:"
+msgstr "AdLib Moniqi:"
+
+#: gui/options.cpp:798 gui/options.cpp:799
+msgid "AdLib is used for music in many games"
+msgstr "AdLib bei Henduo Youxi Yonglai Bofang Yinyue"
+
+#: gui/options.cpp:809
+msgid "Output rate:"
+msgstr "Shuchu Malv:"
+
+#: gui/options.cpp:809 gui/options.cpp:810
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"Genggao de Shuxing Hui Tisheng Yinyue Zhiliang dan Youkeneng Nin de Shengka "
+"Buzhichi"
+
+#: gui/options.cpp:820
+msgid "GM Device:"
+msgstr "GM Shebei:"
+
+#: gui/options.cpp:820
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Zhiding Tongyong MIDI Shuchu Moren Shengyin Shebei"
+
+#: gui/options.cpp:831
+msgid "Don't use General MIDI music"
+msgstr "Buyao Shiyong Tongyong MIDI Yinyue"
+
+#: gui/options.cpp:842 gui/options.cpp:908
+msgid "Use first available device"
+msgstr "Shiyong Diyige keyong de Shebei"
+
+#: gui/options.cpp:854
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:854 gui/options.cpp:856 gui/options.cpp:857
+msgid "SoundFont is supported by some audio cards, FluidSynth and Timidity"
+msgstr "Yixie Shengka Zhichi SoundFont, Biru FluidSynth He Timidity"
+
+#: gui/options.cpp:856
+msgctxt "lowres"
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:862
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Hunhe AdLib/MIDI Moshi"
+
+#: gui/options.cpp:862
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "TongShi Shiyong MIDI He AdLib Shengyin Shengcheng"
+
+#: gui/options.cpp:865
+msgid "MIDI gain:"
+msgstr "MIDI gain:"
+
+#: gui/options.cpp:872
+msgid "FluidSynth Settings"
+msgstr "FluidSynth Xuanxiang"
+
+#: gui/options.cpp:879
+msgid "MT-32 Device:"
+msgstr "MT-32 Shebei:"
+
+#: gui/options.cpp:879
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"QIng Zhiding Yongyu Roland MT-32/LAPC1/CM32I/CM64 Shuchu de Moren Shengyin "
+"Shebei"
+
+#: gui/options.cpp:884
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Zhen Roland MT-32 (Jinyong GM Moni)"
+
+#: gui/options.cpp:884 gui/options.cpp:886
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"Jiancha Shifou Nin Xiang Shiyong Lianjie Dao Jisuanji de Zhenshi de Yingjian "
+"Roland Jianrong Shengyin Shebei"
+
+#: gui/options.cpp:886
+msgctxt "lowres"
+msgid "True Roland MT-32 (no GM emulation)"
+msgstr "Zhen Roland MT-32 Shebei (Wu GM Moni)"
+
+#: gui/options.cpp:889
+msgid "Roland GS Device (enable MT-32 mappings)"
+msgstr "Roland GS Shebei (Qiyong MT-32 Yingshe)"
+
+#: gui/options.cpp:889
+msgid ""
+"Check if you want to enable patch mappings to emulate an MT-32 on a Roland "
+"GS device"
+msgstr ""
+"Jiancha Shifou Nin Xiang Qiyong patch Yingshe Lai Zai Roland GS Shebei "
+"Shangmian Moni MT-32"
+
+#: gui/options.cpp:898
+msgid "Don't use Roland MT-32 music"
+msgstr "Buyao Shiyong Roland MT-32 Yinyue"
+
+#: gui/options.cpp:925
+msgid "Text and Speech:"
+msgstr "Wenzi he Yuyin:"
+
+#: gui/options.cpp:929 gui/options.cpp:939
+msgid "Speech"
+msgstr "Yuyin"
+
+#: gui/options.cpp:930 gui/options.cpp:940
+msgid "Subtitles"
+msgstr "Zimu"
+
+#: gui/options.cpp:931
+msgid "Both"
+msgstr "Liangzhe"
+
+#: gui/options.cpp:933
+msgid "Subtitle speed:"
+msgstr "Zimu Sudu:"
+
+#: gui/options.cpp:935
+msgctxt "lowres"
+msgid "Text and Speech:"
+msgstr "Wenben he Yuyin:"
+
+#: gui/options.cpp:939
+msgid "Spch"
+msgstr "Zimu"
+
+#: gui/options.cpp:940
+msgid "Subs"
+msgstr "Yuyin"
+
+#: gui/options.cpp:941
+msgctxt "lowres"
+msgid "Both"
+msgstr "Dou"
+
+#: gui/options.cpp:941
+msgid "Show subtitles and play speech"
+msgstr "Xianshi Zimu Bing Bofang Yuyin"
+
+#: gui/options.cpp:943
+msgctxt "lowres"
+msgid "Subtitle speed:"
+msgstr "Zimu Sudu"
+
+#: gui/options.cpp:959
+msgid "Music volume:"
+msgstr "Yinyue Yinliang:"
+
+#: gui/options.cpp:961
+msgctxt "lowres"
+msgid "Music volume:"
+msgstr "Yinyue Yinliang:"
+
+#: gui/options.cpp:968
+msgid "Mute All"
+msgstr "Quanbu Jinyin"
+
+#: gui/options.cpp:971
+msgid "SFX volume:"
+msgstr "Yinxiao Yinliang:"
+
+#: gui/options.cpp:971 gui/options.cpp:973 gui/options.cpp:974
+msgid "Special sound effects volume"
+msgstr "Texiao Yinliang"
+
+#: gui/options.cpp:973
+msgctxt "lowres"
+msgid "SFX volume:"
+msgstr "Yinxiao Yinliang:"
+
+#: gui/options.cpp:981
+msgid "Speech volume:"
+msgstr "Yuyin Yinliang:"
+
+#: gui/options.cpp:983
+msgctxt "lowres"
+msgid "Speech volume:"
+msgstr "Yuyin Yinliang:"
+
+#: gui/options.cpp:1140
+msgid "Theme Path:"
+msgstr "Zhuti Lujing:"
+
+#: gui/options.cpp:1142
+msgctxt "lowres"
+msgid "Theme Path:"
+msgstr "Zhuti Lujing:"
+
+#: gui/options.cpp:1148 gui/options.cpp:1150 gui/options.cpp:1151
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr "Zhiding Suoyou Youxi huo ScummVM de Shuju Lujing"
+
+#: gui/options.cpp:1157
+msgid "Plugins Path:"
+msgstr "Chajian Lujing:"
+
+#: gui/options.cpp:1159
+msgctxt "lowres"
+msgid "Plugins Path:"
+msgstr "Chajian Lujing:"
+
+#: gui/options.cpp:1170
+msgctxt "lowres"
+msgid "Misc"
+msgstr "Zaxiang"
+
+#: gui/options.cpp:1172
+msgid "Theme:"
+msgstr "Zhuti:"
+
+#: gui/options.cpp:1176
+msgid "GUI Renderer:"
+msgstr "Jiemian Xuanran:"
+
+#: gui/options.cpp:1188
+msgid "Autosave:"
+msgstr "Zidong Baocun:"
+
+#: gui/options.cpp:1190
+msgctxt "lowres"
+msgid "Autosave:"
+msgstr "Zidong Baocun:"
+
+#: gui/options.cpp:1198
+msgid "Keys"
+msgstr "Guanjianzi"
+
+#: gui/options.cpp:1205
+msgid "GUI Language:"
+msgstr "Jiemian Yuyan:"
+
+#: gui/options.cpp:1205
+msgid "Language of ScummVM GUI"
+msgstr "ScummVM Jiemian Yuyan"
+
+#: gui/options.cpp:1364
+msgid "You have to restart ScummVM before your changes will take effect."
+msgstr "Nin Xuyao Chongqi ScummVM Lai Shi Genggai Shengxiao"
+
+#: gui/options.cpp:1384
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "Zhiding de Mulu Buneng Xieru. Qing Xuanze Qita de Mulu."
+
+#: gui/options.cpp:1393
+msgid "Select directory for GUI themes"
+msgstr "Xuanze Jiemian Zhuti de Mulu"
+
+#: gui/options.cpp:1403
+msgid "Select directory for extra files"
+msgstr "Xuanze QIta Wenjian Mulu"
+
+#: gui/options.cpp:1414
+msgid "Select directory for plugins"
+msgstr "Xuanze Chajian Mulu"
+
+#: gui/options.cpp:1467
+msgid ""
+"The theme you selected does not support your current language. If you want "
+"to use this theme you need to switch to another language first."
+msgstr ""
+"Nin Xuanze de Zhuti Bu Zhichi Xianzai de Yuyan. Qing Xian Qiehuan Dao Qita "
+"Yuyan."
+
+#. I18N: You must leave "#" as is, only word 'next' is translatable
+#: gui/predictivedialog.cpp:86
+msgid "# next"
+msgstr "# Xia Yi Ge"
+
+#: gui/predictivedialog.cpp:87
+msgid "add"
+msgstr "Zengjia"
+
+#: gui/predictivedialog.cpp:92 gui/predictivedialog.cpp:164
+msgid "Delete char"
+msgstr "Shanchu Zifu"
+
+#: gui/predictivedialog.cpp:97 gui/predictivedialog.cpp:168
+msgid "<"
+msgstr "<"
+
+#. I18N: Pre means 'Predictive', leave '*' as is
+#: gui/predictivedialog.cpp:99 gui/predictivedialog.cpp:572
+msgid "* Pre"
+msgstr "* Guanci"
+
+#. I18N: 'Num' means Numbers
+#: gui/predictivedialog.cpp:575
+msgid "* Num"
+msgstr "* Shuzi"
+
+#. I18N: 'Abc' means Latin alphabet input
+#: gui/predictivedialog.cpp:578
+msgid "* Abc"
+msgstr "* Zimu"
+
+#: gui/recorderdialog.cpp:64
+msgid "Recorder or Playback Gameplay"
+msgstr "Youxi Luxiang Huo Huifang"
+
+#: gui/recorderdialog.cpp:69 gui/recorderdialog.cpp:156
+#: gui/saveload-dialog.cpp:220 gui/saveload-dialog.cpp:276
+msgid "Delete"
+msgstr "Shanchu"
+
+#: gui/recorderdialog.cpp:71
+msgid "Record"
+msgstr "Luxiang"
+
+#: gui/recorderdialog.cpp:72
+msgid "Playback"
+msgstr "Huifang"
+
+#: gui/recorderdialog.cpp:74
+msgid "Edit"
+msgstr "Binaji"
+
+#: gui/recorderdialog.cpp:86 gui/recorderdialog.cpp:243
+#: gui/recorderdialog.cpp:253
+msgid "Author: "
+msgstr "Zuozhe:"
+
+#: gui/recorderdialog.cpp:87 gui/recorderdialog.cpp:244
+#: gui/recorderdialog.cpp:254
+msgid "Notes: "
+msgstr "Zhushi:"
+
+#: gui/recorderdialog.cpp:155
+msgid "Do you really want to delete this record?"
+msgstr "Nin Zhende Xinagyao Shanchu Zhege Luxiang ma?"
+
+#: gui/recorderdialog.cpp:174
+msgid "Unknown Author"
+msgstr "Weizhi Zuozhe"
+
+#: gui/saveload-dialog.cpp:167
+msgid "List view"
+msgstr "Liebiao Shitu"
+
+#: gui/saveload-dialog.cpp:168
+msgid "Grid view"
+msgstr "Wangge Shitu"
+
+#: gui/saveload-dialog.cpp:211 gui/saveload-dialog.cpp:360
+msgid "No date saved"
+msgstr "Riqi Wei Baocun"
+
+#: gui/saveload-dialog.cpp:212 gui/saveload-dialog.cpp:361
+msgid "No time saved"
+msgstr "Shijian Wei Baocun"
+
+#: gui/saveload-dialog.cpp:213 gui/saveload-dialog.cpp:362
+msgid "No playtime saved"
+msgstr "Bofang Shijian Wei Baocun"
+
+#: gui/saveload-dialog.cpp:275
+msgid "Do you really want to delete this saved game?"
+msgstr "Nin Zhende Yao Shanchu Zhege Baocun Youxi ma?"
+
+#: gui/saveload-dialog.cpp:385 gui/saveload-dialog.cpp:884
+msgid "Date: "
+msgstr "Riqi: "
+
+#: gui/saveload-dialog.cpp:389 gui/saveload-dialog.cpp:890
+msgid "Time: "
+msgstr "Shijian: "
+
+#: gui/saveload-dialog.cpp:395 gui/saveload-dialog.cpp:898
+msgid "Playtime: "
+msgstr "Bofang Shijian:"
+
+#: gui/saveload-dialog.cpp:408 gui/saveload-dialog.cpp:496
+msgid "Untitled savestate"
+msgstr "Wuming Baocun Zhuangtai"
+
+#: gui/saveload-dialog.cpp:548
+msgid "Next"
+msgstr "Xia Yi Ge"
+
+#: gui/saveload-dialog.cpp:551
+msgid "Prev"
+msgstr "Shang Yi Ge"
+
+#: gui/saveload-dialog.cpp:748
+msgid "New Save"
+msgstr "Xinjian Cundang"
+
+#: gui/saveload-dialog.cpp:748
+msgid "Create a new save game"
+msgstr "Chuangjian Yige Xin Cundang"
+
+#: gui/saveload-dialog.cpp:877
+msgid "Name: "
+msgstr "Mingcheng:"
+
+#: gui/saveload-dialog.cpp:949
+#, c-format
+msgid "Enter a description for slot %d:"
+msgstr "Shuru dui %d Dangwei de Miaoshu"
+
+#: gui/themebrowser.cpp:45
+msgid "Select a Theme"
+msgstr "Xuanze Zhuti"
+
+#: gui/ThemeEngine.cpp:347
+msgid "Disabled GFX"
+msgstr "Jinyong GFX"
+
+#: gui/ThemeEngine.cpp:347
+msgctxt "lowres"
+msgid "Disabled GFX"
+msgstr "Jinyong GFX"
+
+#: gui/ThemeEngine.cpp:348
+msgid "Standard Renderer"
+msgstr "Biaozhun Xuanranqi"
+
+#: gui/ThemeEngine.cpp:348 engines/scumm/dialogs.cpp:663
+msgid "Standard"
+msgstr "Biaozhun"
+
+#: gui/ThemeEngine.cpp:350
+msgid "Antialiased Renderer"
+msgstr "Fanjuchi Xuanranqi"
+
+#: gui/ThemeEngine.cpp:350
+msgid "Antialiased"
+msgstr "Fanjuchi"
+
+#: gui/widget.cpp:323 gui/widget.cpp:325 gui/widget.cpp:331 gui/widget.cpp:333
+msgid "Clear value"
+msgstr "Qingchu Zhi"
+
+#: base/main.cpp:237
+#, c-format
+msgid "Engine does not support debug level '%s'"
+msgstr "Yinqing Buzhichi Tiaoshi Jibie ‘%s’"
+
+#: base/main.cpp:309
+msgid "Menu"
+msgstr "Caidan"
+
+#: base/main.cpp:312 backends/platform/symbian/src/SymbianActions.cpp:45
+#: backends/platform/wince/CEActionsPocket.cpp:45
+#: backends/platform/wince/CEActionsSmartphone.cpp:46
+msgid "Skip"
+msgstr "Tiaoguo"
+
+#: base/main.cpp:315 backends/platform/symbian/src/SymbianActions.cpp:50
+#: backends/platform/wince/CEActionsPocket.cpp:42
+msgid "Pause"
+msgstr "Zanting"
+
+#: base/main.cpp:318
+msgid "Skip line"
+msgstr "Tiaoguo Cihang"
+
+#: base/main.cpp:510
+msgid "Error running game:"
+msgstr "Youxi Yunxing Cuowu:"
+
+#: base/main.cpp:557
+msgid "Could not find any engine capable of running the selected game"
+msgstr "Wufa Zhaodao Shihe Yunxing Youxi de Yinqing"
+
+#: common/error.cpp:38
+msgid "No error"
+msgstr "Wu Cuowu"
+
+#: common/error.cpp:40
+msgid "Game data not found"
+msgstr "Youxi Shuju Weizhaodao"
+
+#: common/error.cpp:42
+msgid "Game id not supported"
+msgstr "Youxi id Bu Zhichi"
+
+#: common/error.cpp:44
+msgid "Unsupported color mode"
+msgstr "Buzhichi Secai Moshi"
+
+#: common/error.cpp:47
+msgid "Read permission denied"
+msgstr "Wu Duqu Quanxian"
+
+#: common/error.cpp:49
+msgid "Write permission denied"
+msgstr "Wu XIeru Quanxian"
+
+#: common/error.cpp:52
+msgid "Path does not exist"
+msgstr "Lujing Bu Cunzai"
+
+#: common/error.cpp:54
+msgid "Path not a directory"
+msgstr "Lujing Bushi Mulu"
+
+#: common/error.cpp:56
+msgid "Path not a file"
+msgstr "Lujing Bushi Wenjian"
+
+#: common/error.cpp:59
+msgid "Cannot create file"
+msgstr "Wufa Chuangjian Wenjian"
+
+#: common/error.cpp:61
+msgid "Reading data failed"
+msgstr "Duqu Shuju Shibai"
+
+#: common/error.cpp:63
+msgid "Writing data failed"
+msgstr "Xieru Shuju Shibai"
+
+#: common/error.cpp:66
+msgid "Could not find suitable engine plugin"
+msgstr "Wufa Zhaodao Heshi de Yinqing Chajian"
+
+#: common/error.cpp:68
+msgid "Engine plugin does not support save states"
+msgstr "Yingqing Chajian Buzhichi Baocun Zhuangtai"
+
+#: common/error.cpp:71
+msgid "User canceled"
+msgstr "Yonghu Quxiao"
+
+#: common/error.cpp:75
+msgid "Unknown error"
+msgstr "Weizhi Cuowu"
+
+#. I18N: Hercules is graphics card name
+#: common/rendermode.cpp:35
+msgid "Hercules Green"
+msgstr "Hercules Green"
+
+#: common/rendermode.cpp:36
+msgid "Hercules Amber"
+msgstr "Hercules Amber"
+
+#: common/rendermode.cpp:42
+msgid "PC-9821 (256 Colors)"
+msgstr "PC-9821 (256 Se)"
+
+#: common/rendermode.cpp:43
+msgid "PC-9801 (16 Colors)"
+msgstr "PC-9801 (16 Se)"
+
+#: common/rendermode.cpp:73
+msgctxt "lowres"
+msgid "Hercules Green"
+msgstr "Hercules Green"
+
+#: common/rendermode.cpp:74
+msgctxt "lowres"
+msgid "Hercules Amber"
+msgstr "Hercules Amber"
+
+#: engines/advancedDetector.cpp:317
+#, c-format
+msgid "The game in '%s' seems to be unknown."
+msgstr "'%s' Zhong de Youxi Weizhi."
+
+#: engines/advancedDetector.cpp:318
+msgid "Please, report the following data to the ScummVM team along with name"
+msgstr "Qing JIang Xialie Shuju Yiji Youxi Baogao Gei ScummVM Tuandui"
+
+#: engines/advancedDetector.cpp:320
+msgid "of the game you tried to add and its version/language/etc.:"
+msgstr "BingQie Fushang Shitu Tianjia de Youximing Yiji Banben/Yuyan Deng"
+
+#: engines/dialogs.cpp:85
+msgid "~R~esume"
+msgstr "~R~Jixu"
+
+#: engines/dialogs.cpp:87
+msgid "~L~oad"
+msgstr "~L~Zairu"
+
+#: engines/dialogs.cpp:91
+msgid "~S~ave"
+msgstr "~S~Baocun"
+
+#: engines/dialogs.cpp:95
+msgid "~O~ptions"
+msgstr "~O~Xuanxiang"
+
+#: engines/dialogs.cpp:100
+msgid "~H~elp"
+msgstr "~H~Bangzhu"
+
+#: engines/dialogs.cpp:102
+msgid "~A~bout"
+msgstr "~A~Guanyu"
+
+#: engines/dialogs.cpp:105 engines/dialogs.cpp:181
+msgid "~R~eturn to Launcher"
+msgstr "~R~Fanhui Qidongqi"
+
+#: engines/dialogs.cpp:107 engines/dialogs.cpp:183
+msgctxt "lowres"
+msgid "~R~eturn to Launcher"
+msgstr "~R~Fanhui Qidongqi"
+
+#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:764
+#: engines/avalanche/parser.cpp:1899 engines/cge/events.cpp:74
+#: engines/cge2/events.cpp:67 engines/cruise/menu.cpp:212
+#: engines/drascula/saveload.cpp:336 engines/dreamweb/saveload.cpp:261
+#: engines/hugo/file.cpp:298 engines/neverhood/menumodule.cpp:877
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
+msgid "Save game:"
+msgstr "Baocun Youxi:"
+
+#: engines/dialogs.cpp:116 backends/platform/symbian/src/SymbianActions.cpp:44
+#: backends/platform/wince/CEActionsPocket.cpp:43
+#: backends/platform/wince/CEActionsPocket.cpp:267
+#: backends/platform/wince/CEActionsSmartphone.cpp:45
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+#: engines/agi/saveload.cpp:764 engines/avalanche/parser.cpp:1899
+#: engines/cge/events.cpp:74 engines/cge2/events.cpp:67
+#: engines/cruise/menu.cpp:212 engines/drascula/saveload.cpp:336
+#: engines/dreamweb/saveload.cpp:261 engines/hugo/file.cpp:298
+#: engines/neverhood/menumodule.cpp:877 engines/parallaction/saveload.cpp:212
+#: engines/pegasus/pegasus.cpp:377 engines/sci/engine/kfile.cpp:768
+#: engines/scumm/dialogs.cpp:188 engines/sherlock/scalpel/scalpel.cpp:1249
+#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:281
+#: engines/toon/toon.cpp:3338 engines/tsage/scenes.cpp:598
+msgid "Save"
+msgstr "Baocun"
+
+#: engines/dialogs.cpp:145
+msgid ""
+"Sorry, this engine does not currently provide in-game help. Please consult "
+"the README for basic information, and for instructions on how to obtain "
+"further assistance."
+msgstr ""
+"Duibuqi, Ci Yinqing Buzhichi Youxi Nei Bangzhu. Qing Chayue README Lai Huoqu "
+"Jiben Xinxi Yiji Ruhe Huode Gengduo Bangzhu."
+
+#: engines/dialogs.cpp:234 engines/pegasus/pegasus.cpp:393
+#, c-format
+msgid ""
+"Gamestate save failed (%s)! Please consult the README for basic information, "
+"and for instructions on how to obtain further assistance."
+msgstr ""
+"Cundang Baocun Shibai (%s)! Qing Chayue README Huode Jiben Xinxi, Yiji "
+"Gengduo Xinxi"
+
+#: engines/dialogs.cpp:307 engines/mohawk/dialogs.cpp:109
+#: engines/mohawk/dialogs.cpp:170 engines/tsage/dialogs.cpp:106
+msgid "~O~K"
+msgstr "~O~Queding"
+
+#: engines/dialogs.cpp:308 engines/mohawk/dialogs.cpp:110
+#: engines/mohawk/dialogs.cpp:171 engines/tsage/dialogs.cpp:107
+msgid "~C~ancel"
+msgstr "~C~Quxiao"
+
+#: engines/dialogs.cpp:311
+msgid "~K~eys"
+msgstr "~K~Guanjianzi"
+
+#: engines/engine.cpp:339
+msgid "Could not initialize color format."
+msgstr "Wufa Chushihua Secai Geshi."
+
+#: engines/engine.cpp:347
+msgid "Could not switch to video mode: '"
+msgstr "Wufa Qiehuandao Shipin Moshi: '"
+
+#: engines/engine.cpp:356
+msgid "Could not apply aspect ratio setting."
+msgstr "Wufa Shezhi Bili Xuanxiang"
+
+#: engines/engine.cpp:361
+msgid "Could not apply fullscreen setting."
+msgstr "Wufa Shezhi Quanping Xuanxiang"
+
+#: engines/engine.cpp:461
+msgid ""
+"You appear to be playing this game directly\n"
+"from the CD. This is known to cause problems,\n"
+"and it is therefore recommended that you copy\n"
+"the data files to your hard disk instead.\n"
+"See the README file for details."
+msgstr ""
+"Sihu Ni Zhengzai Cong CD Zhong Yunxing\n"
+"Youxi. Zhe Keneng Hui Yinfa Wenti.\n"
+"Women Tuijian Nin Ba Shuju Wenjian\n"
+"Kaobei Dao Yingpan Zhong Lai Yunxing.\n"
+"Chakan README Huode Gengduo Xinxi."
+
+#: engines/engine.cpp:472
+msgid ""
+"This game has audio tracks in its disk. These\n"
+"tracks need to be ripped from the disk using\n"
+"an appropriate CD audio extracting tool in\n"
+"order to listen to the game's music.\n"
+"See the README file for details."
+msgstr ""
+"Ci Youxi Zai Guangpan Zhong Baohan Yinyue Wenjian. \n"
+"Zhexie Yingui Xuyao Yong Xiangying de CD Yinpin\n"
+"Jieya Gongju Kaobei Dao Cipan Zhong Cai Neng \n"
+"Bofang.\n"
+"Juti Xinxi Qing Chakan README."
+
+#: engines/engine.cpp:530
+#, c-format
+msgid ""
+"Gamestate load failed (%s)! Please consult the README for basic information, "
+"and for instructions on how to obtain further assistance."
+msgstr ""
+"Cundang Zairu Shibai (%s)! Qing Chayue README Huode Bangzhu XInxi Yiji "
+"Gengduo Bangzhu."
+
+#: engines/engine.cpp:543
+msgid ""
+"WARNING: The game you are about to start is not yet fully supported by "
+"ScummVM. As such, it is likely to be unstable, and any saves you make might "
+"not work in future versions of ScummVM."
+msgstr ""
+"Jinggao: Nin Yao Yunxing de Youxi Bingwei Wanquan Bei ScummVM Zhichi. Youxi "
+"Yunxing Youkeneng Buwending, Renhe Cundang Youkeneng zai Yihou de ScummVM "
+"Banben Bu Keyong."
+
+#: engines/engine.cpp:546
+msgid "Start anyway"
+msgstr "Qiangzhi Qidong"
+
+#: audio/adlib.cpp:2291
+msgid "AdLib Emulator"
+msgstr "AdLib Moniqi"
+
+#: audio/fmopl.cpp:62
+msgid "MAME OPL emulator"
+msgstr "MAME OPL Moniqi"
+
+#: audio/fmopl.cpp:64
+msgid "DOSBox OPL emulator"
+msgstr "DosBox OPL Moniqi"
+
+#: audio/fmopl.cpp:67
+msgid "ALSA Direct FM"
+msgstr "ALSA Direct FM"
+
+#: audio/mididrv.cpp:209
+#, c-format
+msgid ""
+"The selected audio device '%s' was not found (e.g. might be turned off or "
+"disconnected)."
+msgstr ""
+"Weizhaodao Xuanding de Yinpin Shebei '%s' (Liru, Youkeneng Guandiao Huozhe "
+"Weilianjie)."
+
+#: audio/mididrv.cpp:209 audio/mididrv.cpp:221 audio/mididrv.cpp:257
+#: audio/mididrv.cpp:272
+msgid "Attempting to fall back to the next available device..."
+msgstr "ZhengChangshi Xiayige Keyong Shebei..."
+
+#: audio/mididrv.cpp:221
+#, c-format
+msgid ""
+"The selected audio device '%s' cannot be used. See log file for more "
+"information."
+msgstr ""
+"Xuanding de Yinpin Shebei '%s' Wufa Shiyong. Chakan Rizhi Wenjian Huoqu "
+"Gengduo Xinxi."
+
+#: audio/mididrv.cpp:257
+#, c-format
+msgid ""
+"The preferred audio device '%s' was not found (e.g. might be turned off or "
+"disconnected)."
+msgstr ""
+"Youxian Yinpin Shebei '%s' WeiZhaodao (Liru, Youkeneng Guanbi Huo "
+"Weilianjie)."
+
+#: audio/mididrv.cpp:272
+#, c-format
+msgid ""
+"The preferred audio device '%s' cannot be used. See log file for more "
+"information."
+msgstr ""
+"Youxian Yinpin Shebei '%s' Wufa Shiyong. Chakan Rizhi Wenjian Huode Gengduo "
+"Xinxi."
+
+#: audio/mods/paula.cpp:196
+msgid "Amiga Audio Emulator"
+msgstr "Amiga Yinpin Moniqi"
+
+#: audio/null.h:44
+msgid "No music"
+msgstr "Wu Yinyue"
+
+#: audio/softsynth/appleiigs.cpp:33
+msgid "Apple II GS Emulator (NOT IMPLEMENTED)"
+msgstr "Apple II GS Moniqi (Wei Shixian)"
+
+#: audio/softsynth/cms.cpp:350
+msgid "Creative Music System Emulator"
+msgstr "Creative Music System Moniqi"
+
+#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
+msgid "FM-Towns Audio"
+msgstr "FM-Towns Yinpin"
+
+#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:58
+msgid "PC-98 Audio"
+msgstr "PC-98 Yinpin"
+
+#: audio/softsynth/mt32.cpp:200
+msgid "Initializing MT-32 Emulator"
+msgstr "Chushihua MT-32 Moniqi"
+
+#: audio/softsynth/mt32.cpp:426
+msgid "MT-32 Emulator"
+msgstr "MT-32 Moniqi"
+
+#: audio/softsynth/pcspk.cpp:139
+msgid "PC Speaker Emulator"
+msgstr "PC Yangshengqi Moniqi"
+
+#: audio/softsynth/pcspk.cpp:158
+msgid "IBM PCjr Emulator"
+msgstr "IBM PCjr Moniqi"
+
+#: audio/softsynth/sid.cpp:1430
+msgid "C64 Audio Emulator"
+msgstr "C64 Yinpin Moniqi"
+
+#: backends/events/default/default-events.cpp:196
+msgid "Do you really want to return to the Launcher?"
+msgstr "Nin Zhende Xinagyao Fanhui Qidongqi Ma?"
+
+#: backends/events/default/default-events.cpp:196
+msgid "Launcher"
+msgstr "Qidongqi"
+
+#: backends/events/default/default-events.cpp:218
+msgid "Do you really want to quit?"
+msgstr "Nin Zhende Yao Tuichu Ma?"
+
+#: backends/events/default/default-events.cpp:218
+#: backends/platform/symbian/src/SymbianActions.cpp:52
+#: backends/platform/wince/CEActionsPocket.cpp:44
+#: backends/platform/wince/CEActionsSmartphone.cpp:52
+#: engines/scumm/dialogs.cpp:192 engines/scumm/help.cpp:83
+#: engines/scumm/help.cpp:85
+msgid "Quit"
+msgstr "Tuichu"
+
+#: backends/events/gph/gph-events.cpp:385
+#: backends/events/gph/gph-events.cpp:428
+#: backends/events/openpandora/op-events.cpp:168
+msgid "Touchscreen 'Tap Mode' - Left Click"
+msgstr "Chuping 'Chumo Moshi' - Zuojian Danji"
+
+#: backends/events/gph/gph-events.cpp:387
+#: backends/events/gph/gph-events.cpp:430
+#: backends/events/openpandora/op-events.cpp:170
+msgid "Touchscreen 'Tap Mode' - Right Click"
+msgstr "Chuping 'Chumo Moshi' - Youjian Danji"
+
+#: backends/events/gph/gph-events.cpp:389
+#: backends/events/gph/gph-events.cpp:432
+#: backends/events/openpandora/op-events.cpp:172
+msgid "Touchscreen 'Tap Mode' - Hover (No Click)"
+msgstr "Chuping 'Chumo Moshi' - Xuanting (Bu Danji)"
+
+#: backends/events/gph/gph-events.cpp:409
+msgid "Maximum Volume"
+msgstr "Zuida YInliang"
+
+#: backends/events/gph/gph-events.cpp:411
+msgid "Increasing Volume"
+msgstr "Zengda Yinliang"
+
+#: backends/events/gph/gph-events.cpp:417
+msgid "Minimal Volume"
+msgstr "Zuixiao Yinliang"
+
+#: backends/events/gph/gph-events.cpp:419
+msgid "Decreasing Volume"
+msgstr "Jianshao Yinliang"
+
+#: backends/events/maemosdl/maemosdl-events.cpp:180
+msgid "Clicking Enabled"
+msgstr "Qidong Dianji"
+
+#: backends/events/maemosdl/maemosdl-events.cpp:180
+msgid "Clicking Disabled"
+msgstr "Jinyong Dianji"
+
+#: backends/events/openpandora/op-events.cpp:174
+msgid "Touchscreen 'Tap Mode' - Hover (DPad Clicks)"
+msgstr "Chuping 'Chumo Moshi' - Xuanting (Shoubing Dianji)"
+
+#: backends/events/symbiansdl/symbiansdl-events.cpp:186
+msgid "Do you want to quit ?"
+msgstr "Nin Zhende Yao Tuichu Ma?"
+
+#. I18N: Trackpad mode toggle status.
+#: backends/events/webossdl/webossdl-events.cpp:308
+msgid "Trackpad mode is now"
+msgstr "Muqian Wei Chumoban Moshi"
+
+#. I18N: Trackpad mode on or off.
+#. I18N: Auto-drag on or off.
+#: backends/events/webossdl/webossdl-events.cpp:311
+#: backends/events/webossdl/webossdl-events.cpp:338
+msgid "ON"
+msgstr "Kai"
+
+#: backends/events/webossdl/webossdl-events.cpp:311
+#: backends/events/webossdl/webossdl-events.cpp:338
+msgid "OFF"
+msgstr "Guan"
+
+#: backends/events/webossdl/webossdl-events.cpp:315
+msgid "Swipe two fingers to the right to toggle."
+msgstr "XiangYou Shiyong Liang Gen Shouzhi Huadong Qiehuan"
+
+#. I18N: Auto-drag toggle status.
+#: backends/events/webossdl/webossdl-events.cpp:335
+msgid "Auto-drag mode is now"
+msgstr "Muqian Wei Zidong Tuozhuai Moshi"
+
+#: backends/events/webossdl/webossdl-events.cpp:342
+msgid "Swipe three fingers to the right to toggle."
+msgstr "Xiangyou Huadong San Gen Shouzhi Qiehuan"
+
+#: backends/graphics/opengl/opengl-graphics.cpp:119
+msgid "OpenGL"
+msgstr "OpenGL"
+
+#: backends/graphics/opengl/opengl-graphics.cpp:120
+msgid "OpenGL (No filtering)"
+msgstr "OpenGL"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:47
+#: backends/graphics/wincesdl/wincesdl-graphics.cpp:88
+#: backends/graphics/wincesdl/wincesdl-graphics.cpp:95
+msgid "Normal (no scaling)"
+msgstr "Putong"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:66
+msgctxt "lowres"
+msgid "Normal (no scaling)"
+msgstr "Putong"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2215
+msgid "Enabled aspect ratio correction"
+msgstr "Qiyong Bili Jiaozheng"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2221
+msgid "Disabled aspect ratio correction"
+msgstr "Jinyong Bili Jiaozheng"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2276
+msgid "Active graphics filter:"
+msgstr "Huodong de Tuxing Guolvqi:"
+
+#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2318
+msgid "Windowed mode"
+msgstr "Chuangkou Moshi"
+
+#: backends/keymapper/remap-dialog.cpp:48
+msgid "Keymap:"
+msgstr "Jianpan Yingshe:"
+
+#: backends/keymapper/remap-dialog.cpp:67
+msgid " (Effective)"
+msgstr " (Shengxiao)"
+
+#: backends/keymapper/remap-dialog.cpp:107
+msgid " (Active)"
+msgstr " (Huodong)"
+
+#: backends/keymapper/remap-dialog.cpp:107
+msgid " (Blocked)"
+msgstr " (Zuzhi)"
+
+#: backends/keymapper/remap-dialog.cpp:120
+msgid " (Global)"
+msgstr " (Quanju)"
+
+#: backends/keymapper/remap-dialog.cpp:128
+msgid " (Game)"
+msgstr " (Youxi)"
+
+#: backends/midi/windows.cpp:165
+msgid "Windows MIDI"
+msgstr "Windows MIDI"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:56
+#: engines/scumm/dialogs.cpp:291
+msgid "~C~lose"
+msgstr "~C~Guanbi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:57
+msgid "ScummVM Main Menu"
+msgstr "ScummVM Zhucaidan"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:63
+msgid "~L~eft handed mode"
+msgstr "~L~Zuoshou Moshi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:64
+msgid "~I~ndy fight controls"
+msgstr "~I~Indy fight Kongzhi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:65
+msgid "Show mouse cursor"
+msgstr "Xianshi Shubiao Zhizhen"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:66
+msgid "Snap to edges"
+msgstr "TieFu Yu Bianjie"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:68
+msgid "Touch X Offset"
+msgstr "Chumo X Pianyi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:75
+msgid "Touch Y Offset"
+msgstr "Chumo Y Pianyi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:87
+msgid "Use laptop trackpad-style cursor control"
+msgstr "Shiyong Bijiben Diannao Chumoban Shi Zhizhen Kongzhi"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:88
+msgid "Tap for left click, double tap right click"
+msgstr "Chumo Yici Wei Zuojian, Chumo LIangci Wei Youjian"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:90
+msgid "Sensitivity"
+msgstr "Mingandu"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:99
+msgid "Initial top screen scale:"
+msgstr "Chushi Shangping Daxiao"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:105
+msgid "Main screen scaling:"
+msgstr "Zhu Pingmu Daxiao"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:107
+msgid "Hardware scale (fast, but low quality)"
+msgstr "yingjian Suofang (Kuaisu DiXiao)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:108
+msgid "Software scale (good quality, but slower)"
+msgstr "Ruanjian Suofang (Gaoxiao Mansu)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:109
+msgid "Unscaled (you must scroll left and right)"
+msgstr "Wei Suofang (Xuyao ZuoYou Yidong)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:111
+msgid "Brightness:"
+msgstr "Liangdu:"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:121
+msgid "High quality audio (slower) (reboot)"
+msgstr "Gaozhiliang Yinpin (Man) (Chongqi)"
+
+#: backends/platform/ds/arm9/source/dsoptions.cpp:122
+msgid "Disable power off"
+msgstr "Jinyong Guanji"
+
+#: backends/platform/ios7/ios7_osys_events.cpp:309
+#: backends/platform/ios7/ios7_osys_events.cpp:519
+#: backends/platform/iphone/osys_events.cpp:300
+msgid "Mouse-click-and-drag mode enabled."
+msgstr "QIdong Shubiao Dianji-tuozhuai Moshi"
+
+#: backends/platform/ios7/ios7_osys_events.cpp:311
+#: backends/platform/ios7/ios7_osys_events.cpp:521
+#: backends/platform/iphone/osys_events.cpp:302
+msgid "Mouse-click-and-drag mode disabled."
+msgstr "Jinyong Shubiao Dianji-Tuozhuai Moshi."
+
+#: backends/platform/ios7/ios7_osys_events.cpp:322
+#: backends/platform/ios7/ios7_osys_events.cpp:540
+#: backends/platform/iphone/osys_events.cpp:313
+msgid "Touchpad mode enabled."
+msgstr "Qiyong Chumoban Moshi"
+
+#: backends/platform/ios7/ios7_osys_events.cpp:324
+#: backends/platform/ios7/ios7_osys_events.cpp:542
+#: backends/platform/iphone/osys_events.cpp:315
+msgid "Touchpad mode disabled."
+msgstr "Jinyong Chumoban Moshi"
+
+#: backends/platform/maemo/maemo.cpp:208
+msgid "Click Mode"
+msgstr "Danji Moshi"
+
+#: backends/platform/maemo/maemo.cpp:214
+#: backends/platform/symbian/src/SymbianActions.cpp:42
+#: backends/platform/tizen/form.cpp:275
+#: backends/platform/wince/CEActionsPocket.cpp:60
+#: backends/platform/wince/CEActionsSmartphone.cpp:43
+msgid "Left Click"
+msgstr "Zuojian Danji"
+
+#: backends/platform/maemo/maemo.cpp:217
+msgid "Middle Click"
+msgstr "Zhongjian Danji"
+
+#: backends/platform/maemo/maemo.cpp:220
+#: backends/platform/symbian/src/SymbianActions.cpp:43
+#: backends/platform/tizen/form.cpp:267
+#: backends/platform/wince/CEActionsSmartphone.cpp:44
+msgid "Right Click"
+msgstr "Youjian Danji"
+
+#: backends/platform/sdl/macosx/appmenu_osx.mm:88
+msgid "Hide ScummVM"
+msgstr "Yincang ScummVM"
+
+#: backends/platform/sdl/macosx/appmenu_osx.mm:93
+msgid "Hide Others"
+msgstr "Yincang QIta"
+
+#: backends/platform/sdl/macosx/appmenu_osx.mm:98
+msgid "Show All"
+msgstr "Xianshi Quanbu"
+
+#: backends/platform/sdl/macosx/appmenu_osx.mm:120
+#: backends/platform/sdl/macosx/appmenu_osx.mm:131
+msgid "Window"
+msgstr "Chuangkou"
+
+#: backends/platform/sdl/macosx/appmenu_osx.mm:125
+msgid "Minimize"
+msgstr "Zuixiaohua"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:38
+#: backends/platform/wince/CEActionsSmartphone.cpp:39
+msgid "Up"
+msgstr "Shang"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:39
+#: backends/platform/wince/CEActionsSmartphone.cpp:40
+msgid "Down"
+msgstr "Xia"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:40
+#: backends/platform/wince/CEActionsSmartphone.cpp:41
+msgid "Left"
+msgstr "Zuo"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:41
+#: backends/platform/wince/CEActionsSmartphone.cpp:42
+msgid "Right"
+msgstr "You"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:46
+#: backends/platform/wince/CEActionsSmartphone.cpp:47
+msgid "Zone"
+msgstr "Quyu"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:47
+#: backends/platform/wince/CEActionsPocket.cpp:54
+#: backends/platform/wince/CEActionsSmartphone.cpp:48
+msgid "Multi Function"
+msgstr "Duo Gongneng"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:48
+msgid "Swap character"
+msgstr "Qiehuan Juese"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:49
+msgid "Skip text"
+msgstr "Tiaoguo Wenben"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:51
+msgid "Fast mode"
+msgstr "Kuaisu Moshi"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:53
+msgid "Debugger"
+msgstr "Tiaoshi Qi"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:54
+msgid "Global menu"
+msgstr "Quanju Caidan"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:55
+msgid "Virtual keyboard"
+msgstr "Xuni JIanpan"
+
+#: backends/platform/symbian/src/SymbianActions.cpp:56
+msgid "Key mapper"
+msgstr "Jianpan yingshe"
+
+#: backends/platform/tizen/form.cpp:263
+msgid "Right Click Once"
+msgstr "Youjian Danji"
+
+#: backends/platform/tizen/form.cpp:271
+msgid "Move Only"
+msgstr "Jin Yidong"
+
+#: backends/platform/tizen/form.cpp:294
+msgid "Escape Key"
+msgstr "Esc Jian"
+
+#: backends/platform/tizen/form.cpp:299
+msgid "Game Menu"
+msgstr "Youxi Caidan"
+
+#: backends/platform/tizen/form.cpp:304
+msgid "Show Keypad"
+msgstr "Xianshi Jianpan"
+
+#: backends/platform/tizen/form.cpp:309
+msgid "Control Mouse"
+msgstr "Kongzhi Shubiao"
+
+#: backends/platform/tizen/fs.cpp:259
+msgid "[ Data ]"
+msgstr "[ Shuju ]"
+
+#: backends/platform/tizen/fs.cpp:263
+msgid "[ Resources ]"
+msgstr "[ Ziyuan]"
+
+#: backends/platform/tizen/fs.cpp:267
+msgid "[ SDCard ]"
+msgstr "[ SD Ka ]"
+
+#: backends/platform/tizen/fs.cpp:271
+msgid "[ Media ]"
+msgstr "[ Meiti ]"
+
+#: backends/platform/tizen/fs.cpp:275
+msgid "[ Shared ]"
+msgstr "[ gongxiang ]"
+
+#: backends/platform/wii/options.cpp:51
+msgid "Video"
+msgstr "Shipin"
+
+#: backends/platform/wii/options.cpp:54
+msgid "Current video mode:"
+msgstr "Muqian Shipin Moshi:"
+
+#: backends/platform/wii/options.cpp:56
+msgid "Double-strike"
+msgstr "Shuang Ji"
+
+#: backends/platform/wii/options.cpp:60
+msgid "Horizontal underscan:"
+msgstr "Shuiping Saomiao"
+
+#: backends/platform/wii/options.cpp:66
+msgid "Vertical underscan:"
+msgstr "Chuizhi Saomiao"
+
+#: backends/platform/wii/options.cpp:71
+msgid "Input"
+msgstr "Shuru"
+
+#: backends/platform/wii/options.cpp:74
+msgid "GC Pad sensitivity:"
+msgstr "GC Pan Mingandu"
+
+#: backends/platform/wii/options.cpp:80
+msgid "GC Pad acceleration:"
+msgstr "GC Pad Jiasu"
+
+#: backends/platform/wii/options.cpp:86
+msgid "DVD"
+msgstr "DVD"
+
+#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101
+msgid "Status:"
+msgstr "Zhuangtai:"
+
+#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102
+msgid "Unknown"
+msgstr "Weizhi"
+
+#: backends/platform/wii/options.cpp:93
+msgid "Mount DVD"
+msgstr "Jiazai DVD"
+
+#: backends/platform/wii/options.cpp:94
+msgid "Unmount DVD"
+msgstr "Xiezai DVD"
+
+#: backends/platform/wii/options.cpp:98
+msgid "SMB"
+msgstr "SMB"
+
+#: backends/platform/wii/options.cpp:106
+msgid "Server:"
+msgstr "Fuwuqi:"
+
+#: backends/platform/wii/options.cpp:110
+msgid "Share:"
+msgstr "Gongxiang:"
+
+#: backends/platform/wii/options.cpp:114
+msgid "Username:"
+msgstr "Yonghuming:"
+
+#: backends/platform/wii/options.cpp:118
+msgid "Password:"
+msgstr "Mima:"
+
+#: backends/platform/wii/options.cpp:121
+msgid "Init network"
+msgstr "Chushihua Wangluo"
+
+#: backends/platform/wii/options.cpp:123
+msgid "Mount SMB"
+msgstr "Jiazai SMB"
+
+#: backends/platform/wii/options.cpp:124
+msgid "Unmount SMB"
+msgstr "Xiezai SMB"
+
+#: backends/platform/wii/options.cpp:143
+msgid "DVD Mounted successfully"
+msgstr "DVD Jiazai Chenggong"
+
+#: backends/platform/wii/options.cpp:146
+msgid "Error while mounting the DVD"
+msgstr "Jiazai DVD Chucuo"
+
+#: backends/platform/wii/options.cpp:148
+msgid "DVD not mounted"
+msgstr "DVD Wei Jiazai"
+
+#: backends/platform/wii/options.cpp:161
+msgid "Network up, share mounted"
+msgstr "Wangluo Lianjie, Gongxiang Jiazai"
+
+#: backends/platform/wii/options.cpp:163
+msgid "Network up"
+msgstr "Wangluo Lianjie"
+
+#: backends/platform/wii/options.cpp:166
+msgid ", error while mounting the share"
+msgstr ", Jiazai Gongxiang Chucuo"
+
+#: backends/platform/wii/options.cpp:168
+msgid ", share not mounted"
+msgstr ", Wei jiazai Gongxiang"
+
+#: backends/platform/wii/options.cpp:174
+msgid "Network down"
+msgstr "Wangluo Duanxian"
+
+#: backends/platform/wii/options.cpp:178
+msgid "Initializing network"
+msgstr "Chushihua Wnagluo"
+
+#: backends/platform/wii/options.cpp:182
+msgid "Timeout while initializing network"
+msgstr "Chushihua Wnagluo Chaoshi"
+
+#: backends/platform/wii/options.cpp:186
+#, c-format
+msgid "Network not initialized (%d)"
+msgstr "Wangluo Wei Chushihua (%d)"
+
+#: backends/platform/wince/CEActionsPocket.cpp:46
+msgid "Hide Toolbar"
+msgstr "YIncang Gongjulan"
+
+#: backends/platform/wince/CEActionsPocket.cpp:47
+msgid "Show Keyboard"
+msgstr "Xianshi JIanpan"
+
+#: backends/platform/wince/CEActionsPocket.cpp:48
+msgid "Sound on/off"
+msgstr "Shengyin Kai/Guan"
+
+#: backends/platform/wince/CEActionsPocket.cpp:49
+msgid "Right click"
+msgstr "Youjian Danji"
+
+#: backends/platform/wince/CEActionsPocket.cpp:50
+msgid "Show/Hide Cursor"
+msgstr "Xianshi/Yincang Zhizhen"
+
+#: backends/platform/wince/CEActionsPocket.cpp:51
+msgid "Free look"
+msgstr "Ziyou Chakan"
+
+#: backends/platform/wince/CEActionsPocket.cpp:52
+msgid "Zoom up"
+msgstr "Fangda"
+
+#: backends/platform/wince/CEActionsPocket.cpp:53
+msgid "Zoom down"
+msgstr "Suoxiao"
+
+#: backends/platform/wince/CEActionsPocket.cpp:55
+#: backends/platform/wince/CEActionsSmartphone.cpp:49
+msgid "Bind Keys"
+msgstr "Bangding Jianwei"
+
+#: backends/platform/wince/CEActionsPocket.cpp:56
+msgid "Cursor Up"
+msgstr "Zhizhen Shang"
+
+#: backends/platform/wince/CEActionsPocket.cpp:57
+msgid "Cursor Down"
+msgstr "Zhizhen Xia"
+
+#: backends/platform/wince/CEActionsPocket.cpp:58
+msgid "Cursor Left"
+msgstr "Zhizhen Zuo"
+
+#: backends/platform/wince/CEActionsPocket.cpp:59
+msgid "Cursor Right"
+msgstr "Zhizhen You"
+
+#: backends/platform/wince/CEActionsPocket.cpp:267
+#: backends/platform/wince/CEActionsSmartphone.cpp:231
+msgid "Do you want to load or save the game?"
+msgstr "Nin Xinagyao Zairu Huo Baocun Youxi Ma?"
+
+#: backends/platform/wince/CEActionsPocket.cpp:326
+#: backends/platform/wince/CEActionsSmartphone.cpp:287
+msgid " Are you sure you want to quit ? "
+msgstr "Nin Queding Tuichu ma ?"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:50
+msgid "Keyboard"
+msgstr "Jianpan"
+
+#: backends/platform/wince/CEActionsSmartphone.cpp:51
+msgid "Rotate"
+msgstr "Xuanzhuan"
+
+#: backends/platform/wince/CELauncherDialog.cpp:56
+msgid "Using SDL driver "
+msgstr "Shiyong SDL Qudong"
+
+#: backends/platform/wince/CELauncherDialog.cpp:60
+msgid "Display "
+msgstr "Xianshi"
+
+#: backends/platform/wince/CELauncherDialog.cpp:83
+msgid "Do you want to perform an automatic scan ?"
+msgstr "Nin Xiwang Zidong Saomiao ma?"
+
+#: backends/platform/wince/wince-sdl.cpp:516
+msgid "Map right click action"
+msgstr "Yingshe Youjian Dianji Xingwei"
+
+#: backends/platform/wince/wince-sdl.cpp:520
+msgid "You must map a key to the 'Right Click' action to play this game"
+msgstr "Nin Bixu Yingshe Yige Jian Dao 'Youjian Danji' Lai kaishi Youxi"
+
+#: backends/platform/wince/wince-sdl.cpp:529
+msgid "Map hide toolbar action"
+msgstr "yingshe YIncang Gongjulan Xingwei"
+
+#: backends/platform/wince/wince-sdl.cpp:533
+msgid "You must map a key to the 'Hide toolbar' action to play this game"
+msgstr "Nin Bixu Yingshe Yigejian Dao 'Yincang Gongjulan' Lai Kaishi Youxi"
+
+#: backends/platform/wince/wince-sdl.cpp:542
+msgid "Map Zoom Up action (optional)"
+msgstr "Yingshe Fnagda Xingwei (Kexuan)"
+
+#: backends/platform/wince/wince-sdl.cpp:545
+msgid "Map Zoom Down action (optional)"
+msgstr "Yingshe Suoxiao Xingwei (Kexuan)"
+
+#: backends/platform/wince/wince-sdl.cpp:553
+msgid ""
+"Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"
+msgstr ""
+"Buyao Wnagji Yingshe YIge Jian Dao 'YIncang Gongjulan' Lai Chakan Suoyou "
+"xiang"
+
+#: backends/updates/macosx/macosx-updates.mm:67
+msgid "Check for Updates..."
+msgstr "Jiancha Gengxin..."
+
+#: engines/agi/detection.cpp:147 engines/cine/detection.cpp:70
+#: engines/drascula/detection.cpp:302 engines/dreamweb/detection.cpp:47
+#: engines/neverhood/detection.cpp:160 engines/sci/detection.cpp:404
+#: engines/toltecs/detection.cpp:200 engines/zvision/detection_tables.h:51
+msgid "Use original save/load screens"
+msgstr "Shiyong Yuanshi Baocun/Zairu Pingmu"
+
+#: engines/agi/detection.cpp:148 engines/cine/detection.cpp:71
+#: engines/drascula/detection.cpp:303 engines/dreamweb/detection.cpp:48
+#: engines/neverhood/detection.cpp:161 engines/sci/detection.cpp:405
+#: engines/toltecs/detection.cpp:201
+msgid "Use the original save/load screens, instead of the ScummVM ones"
+msgstr "Shiyong Yuanshi Baocun/Zairu Pingmu, Bu Shiyong ScummVM de"
+
+#: engines/agi/detection.cpp:157
+msgid "Use an alternative palette"
+msgstr "Shiyong Qita Mianban"
+
+#: engines/agi/detection.cpp:158
+msgid ""
+"Use an alternative palette, common for all Amiga games. This was the old "
+"behavior"
+msgstr "Shiyong QIta Mianban, Yiban Yonghu suoyou de Amiga Youxi. "
+
+#: engines/agi/detection.cpp:167
+msgid "Mouse support"
+msgstr "Shubiao Zhichi"
+
+#: engines/agi/detection.cpp:168
+msgid ""
+"Enables mouse support. Allows to use mouse for movement and in game menus."
+msgstr ""
+"Qiyong shubiao zhichi. Yunxu Shiyong Shubiao jinxing Yidong He Youxi Nei "
+"Caidan"
+
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
+msgid "Restore game:"
+msgstr "Huifu Youxi:"
+
+#: engines/agi/saveload.cpp:777 engines/avalanche/parser.cpp:1887
+#: engines/cge/events.cpp:85 engines/cge2/events.cpp:78
+#: engines/drascula/saveload.cpp:349 engines/dreamweb/saveload.cpp:169
+#: engines/hugo/file.cpp:400 engines/neverhood/menumodule.cpp:890
+#: engines/sci/engine/kfile.cpp:867 engines/sherlock/scalpel/scalpel.cpp:1262
+#: engines/sherlock/tattoo/widget_files.cpp:94 engines/toltecs/menu.cpp:256
+#: engines/toon/toon.cpp:3430
+msgid "Restore"
+msgstr "Huifu"
+
+#: engines/agos/saveload.cpp:160 engines/scumm/scumm.cpp:2377
+#, c-format
+msgid ""
+"Failed to load game state from file:\n"
+"\n"
+"%s"
+msgstr ""
+"Jiazai Youxi Cundang Shibai:\n"
+"\n"
+"%s"
+
+#: engines/agos/saveload.cpp:195 engines/scumm/scumm.cpp:2370
+#, c-format
+msgid ""
+"Failed to save game state to file:\n"
+"\n"
+"%s"
+msgstr ""
+"Baocun Youxi Cundang Shibai:\n"
+"\n"
+"%s"
+
+#: engines/agos/saveload.cpp:203 engines/scumm/scumm.cpp:2388
+#, c-format
+msgid ""
+"Successfully saved game state in file:\n"
+"\n"
+"%s"
+msgstr ""
+"Chenggong Baocun Youxi Cundang:\n"
+"\n"
+"%s"
+
+#: engines/agos/animation.cpp:557
+#, c-format
+msgid "Cutscene file '%s' not found!"
+msgstr "Changjing Qiehuan Wenjian '%s' Wei Zhaodao!"
+
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+msgid "Color Blind Mode"
+msgstr "Semang Moshi"
+
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+msgid "Enable Color Blind Mode by default"
+msgstr "Moren Qiyong Semang Moshi"
+
+#: engines/drascula/saveload.cpp:47
+msgid ""
+"ScummVM found that you have old savefiles for Drascula that should be "
+"converted.\n"
+"The old save game format is no longer supported, so you will not be able to "
+"load your games if you don't convert them.\n"
+"\n"
+"Press OK to convert them now, otherwise you will be asked again the next "
+"time you start the game.\n"
+msgstr ""
+"ScummVM Faxian Nin You Jiu de Drascula de Cundang Wenjian Xuyao Bei "
+"Zhuanhuan.\n"
+"Jiude cundang Wenjian Buzai Zhichi, Suoyi Nin Buneng Guo zai Zhuanhuan "
+"Zhiqian Duqu.\n"
+"Dianji Shi Lai Xianzai Zhuanhuan, Fouze Xiaci Qidong Youxi Shi Nin Huibei "
+"Zaici Xunwen\n"
+" \n"
+
+#: engines/dreamweb/detection.cpp:57
+msgid "Use bright palette mode"
+msgstr "Shiyong Liang Tiaoseban Moshi"
+
+#: engines/dreamweb/detection.cpp:58
+msgid "Display graphics using the game's bright palette"
+msgstr "Shiyong youxi de Liang Tiaoseban Lai Xianshi Tuxiang"
+
+#: engines/gob/inter_playtoons.cpp:256 engines/gob/inter_v2.cpp:1470
+#: engines/gob/inter_geisha.cpp:232 engines/tinsel/saveload.cpp:532
+msgid "Failed to load game state from file."
+msgstr "Wufa Cong Cundang Wenjian Zhong Duqu"
+
+#: engines/gob/inter_v2.cpp:1540 engines/gob/inter_geisha.cpp:263
+#: engines/tinsel/saveload.cpp:545
+msgid "Failed to save game state to file."
+msgstr "Wufa Baocun Cundang "
+
+#: engines/gob/inter_v5.cpp:107
+msgid "Failed to delete file."
+msgstr "Wufa Shanchu Wenjian"
+
+#: engines/groovie/detection.cpp:312
+msgid "Fast movie speed"
+msgstr "Kuaisu Yingpian"
+
+#: engines/groovie/detection.cpp:313
+msgid "Play movies at an increased speed"
+msgstr "Yong Gengkuai de Sudu Bofang Yingpian"
+
+#: engines/groovie/script.cpp:408
+msgid "Failed to save game"
+msgstr "Wufa baocun Youxi"
+
+#: engines/hopkins/detection.cpp:76 engines/hopkins/detection.cpp:86
+msgid "Gore Mode"
+msgstr "Gore Moshi"
+
+#: engines/hopkins/detection.cpp:77 engines/hopkins/detection.cpp:87
+msgid "Enable Gore Mode when available"
+msgstr "Dang Kexing Shi Qiyong Gore Moshi"
+
+#. I18N: Studio audience adds an applause and cheering sounds whenever
+#. Malcolm makes a joke.
+#: engines/kyra/detection.cpp:62
+msgid "Studio audience"
+msgstr "Luyinpeng Guanzhong"
+
+#: engines/kyra/detection.cpp:63
+msgid "Enable studio audience"
+msgstr "Qiyong Luyinpeng Guanzhong"
+
+#. I18N: This option allows the user to skip text and cutscenes.
+#: engines/kyra/detection.cpp:73
+msgid "Skip support"
+msgstr "Zhichi Tiaoguo"
+
+#: engines/kyra/detection.cpp:74
+msgid "Allow text and cutscenes to be skipped"
+msgstr "Zhichi Wenzi he Changjing Bei Tiaoguo"
+
+#. I18N: Helium mode makes people sound like they've inhaled Helium.
+#: engines/kyra/detection.cpp:84
+msgid "Helium mode"
+msgstr "Haiqi Moshi"
+
+#: engines/kyra/detection.cpp:85
+msgid "Enable helium mode"
+msgstr "Shiyong Haiqi Moshi"
+
+#. I18N: When enabled, this option makes scrolling smoother when
+#. changing from one screen to another.
+#: engines/kyra/detection.cpp:99
+msgid "Smooth scrolling"
+msgstr "Pinghua Gundong"
+
+#: engines/kyra/detection.cpp:100
+msgid "Enable smooth scrolling when walking"
+msgstr "Qiyong Zoulu Shi de pinghua Gundong"
+
+#. I18N: When enabled, this option changes the cursor when it floats to the
+#. edge of the screen to a directional arrow. The player can then click to
+#. walk towards that direction.
+#: engines/kyra/detection.cpp:112
+msgid "Floating cursors"
+msgstr "Xuanfu Guangbiao"
+
+#: engines/kyra/detection.cpp:113
+msgid "Enable floating cursors"
+msgstr "Qiyong Xuanfu Guangbiao"
+
+#. I18N: HP stands for Hit Points
+#: engines/kyra/detection.cpp:127
+msgid "HP bar graphs"
+msgstr "HP Tiao Tu"
+
+#: engines/kyra/detection.cpp:128
+msgid "Enable hit point bar graphs"
+msgstr "Qiyong Jida Dian Tiao Tu"
+
+#: engines/kyra/lol.cpp:478
+msgid "Attack 1"
+msgstr "Gongji 1"
+
+#: engines/kyra/lol.cpp:479
+msgid "Attack 2"
+msgstr "Gongji 2"
+
+#: engines/kyra/lol.cpp:480
+msgid "Attack 3"
+msgstr "Gongji 3"
+
+#: engines/kyra/lol.cpp:481
+msgid "Move Forward"
+msgstr "Xiangqian Yidong"
+
+#: engines/kyra/lol.cpp:482
+msgid "Move Back"
+msgstr "Xinaghou Yidong"
+
+#: engines/kyra/lol.cpp:483
+msgid "Slide Left"
+msgstr "Xiangzuo Huadong"
+
+#: engines/kyra/lol.cpp:484
+msgid "Slide Right"
+msgstr "Xiangyou Huadong"
+
+#: engines/kyra/lol.cpp:485 engines/pegasus/pegasus.cpp:2509
+msgid "Turn Left"
+msgstr "Zuozhuan"
+
+#: engines/kyra/lol.cpp:486 engines/pegasus/pegasus.cpp:2510
+msgid "Turn Right"
+msgstr "Youzhuan"
+
+#: engines/kyra/lol.cpp:487
+msgid "Rest"
+msgstr "Xiuxi"
+
+#: engines/kyra/lol.cpp:488
+msgid "Options"
+msgstr "Xuanxiang"
+
+#: engines/kyra/lol.cpp:489
+msgid "Choose Spell"
+msgstr "Xuanze Pinxie"
+
+#: engines/kyra/sound_midi.cpp:477
+msgid ""
+"You appear to be using a General MIDI device,\n"
+"but your game only supports Roland MT32 MIDI.\n"
+"We try to map the Roland MT32 instruments to\n"
+"General MIDI ones. It is still possible that\n"
+"some tracks sound incorrect."
+msgstr ""
+"Nin Sihu zhengzai shiyong yige Tongyong MIDI Shebei\n"
+"Danshi Nin de Youxi jinzhichi Roland MT32 MIDI.\n"
+"Women zhengzai changshi JIang Roland MT32 Yingshe\n"
+"wei Tongyong MIDI. Youxie YIngui Rengran Youkeneng\n"
+"Bu zheng que."
+
+#: engines/kyra/saveload_eob.cpp:557
+#, c-format
+msgid ""
+"The following original save game file has been found in your game path:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Do you wish to use this save game file with ScummVM?\n"
+"\n"
+msgstr ""
+"Xialie Yuanshi Cundang Wenjian Zai Nin de Youxi Lujing Zhong:\n"
+"\n"
+"%s %s\n"
+"\n"
+"Nin Xiwang Shiyong Zhege ScummVM Cundang Wenjian ma?\n"
+"\n"
+
+#: engines/kyra/saveload_eob.cpp:590
+#, c-format
+msgid ""
+"A save game file was found in the specified slot %d. Overwrite?\n"
+"\n"
+msgstr ""
+"Zai Cundang %d Zhong Yifaxian Baocun de Youxi WEnjian. Fugai Ma?\n"
+"\n"
+
+#: engines/kyra/saveload_eob.cpp:623
+#, c-format
+msgid ""
+"%d original save game files have been successfully imported into\n"
+"ScummVM. If you want to manually import original save game files later you "
+"will\n"
+"need to open the ScummVM debug console and use the command "
+"'import_savefile'.\n"
+"\n"
+msgstr ""
+"%d Ge yuanshi Cundang Youxi Wenjian Chenggong Daoru Daole\n"
+"ScummVM. Ruguo Nin Xinag Zhihou Rengong Daoru Cundang Wenjian, Nin Xuyao\n"
+"Dagai ScummVM Tiaoshi Kongzhitai, Bingqie shiyong mingling "
+"'import_savefile'.\n"
+"\n"
+
+#. I18N: Option for fast scene switching
+#: engines/mohawk/dialogs.cpp:92 engines/mohawk/dialogs.cpp:167
+msgid "~Z~ip Mode Activated"
+msgstr "~Z~Yasuo Moshi Qidong"
+
+#: engines/mohawk/dialogs.cpp:93
+msgid "~T~ransitions Enabled"
+msgstr "~T~Qiyong Zhuanyi"
+
+#. I18N: Drop book page
+#: engines/mohawk/dialogs.cpp:95
+msgid "~D~rop Page"
+msgstr "~D~shanchu Yemian"
+
+#: engines/mohawk/dialogs.cpp:99
+msgid "~S~how Map"
+msgstr "~S~Xianshi Ditu"
+
+#: engines/mohawk/dialogs.cpp:105
+msgid "~M~ain Menu"
+msgstr "~M~Zhucaidan"
+
+#: engines/mohawk/dialogs.cpp:168
+msgid "~W~ater Effect Enabled"
+msgstr "~W~Qiyong Shuimian Xiaoguo"
+
+#: engines/neverhood/detection.cpp:167
+msgid "Skip the Hall of Records storyboard scenes"
+msgstr "Tiaoguo Hall of Records Jishiban Changjing"
+
+#: engines/neverhood/detection.cpp:168
+msgid "Allows the player to skip past the Hall of Records storyboard scenes"
+msgstr "Yunxu Wanjia Tiaoguo Hall of Records Jishiban Changjing"
+
+#: engines/neverhood/detection.cpp:174
+msgid "Scale the making of videos to full screen"
+msgstr "Fangda Shipin Zhizuo Dao Quanping"
+
+#: engines/neverhood/detection.cpp:175
+msgid "Scale the making of videos, so that they use the whole screen"
+msgstr "Suofang Shipin Zhizuo, Quanping Ke Yong"
+
+#: engines/parallaction/saveload.cpp:133
+#, c-format
+msgid ""
+"Can't save game in slot %i\n"
+"\n"
+msgstr ""
+"Wufa Baocun Youxi Dao Kongwei %i\n"
+"\n"
+
+#: engines/parallaction/saveload.cpp:197
+msgid "Load file"
+msgstr "Zairu Wenjian"
+
+#: engines/parallaction/saveload.cpp:204
+msgid "Loading game..."
+msgstr "Zairu youxi..."
+
+#: engines/parallaction/saveload.cpp:212
+msgid "Save file"
+msgstr "Baocun Wenjian"
+
+#: engines/parallaction/saveload.cpp:219
+msgid "Saving game..."
+msgstr "Baocun Youxi..."
+
+#: engines/parallaction/saveload.cpp:272
+msgid ""
+"ScummVM found that you have old savefiles for Nippon Safes that should be "
+"renamed.\n"
+"The old names are no longer supported, so you will not be able to load your "
+"games if you don't convert them.\n"
+"\n"
+"Press OK to convert them now, otherwise you will be asked next time.\n"
+msgstr ""
+"ScummVM Faxian Youyixie Nippon Safes de Cundang Wenjian xuyao Gaiming.\n"
+"Yuanlai de wenjianming Buzai Bei Zhichi, Ruguo Bujing Zhuanhuan Ninjing "
+"Buneng Zairu Tamen.\n"
+"Dianji Queding Lai Xianzai Zhuanhuan, Fouze Nin Hui zai Xiaci Bei Xunwen\n"
+
+#: engines/parallaction/saveload.cpp:319
+msgid "ScummVM successfully converted all your savefiles."
+msgstr "ScummVM Chenggong Zhuanhuan le Nin de Suoyou Cundang Wenjian."
+
+#: engines/parallaction/saveload.cpp:321
+msgid ""
+"ScummVM printed some warnings in your console window and can't guarantee all "
+"your files have been converted.\n"
+"\n"
+"Please report to the team."
+msgstr ""
+"ScummVM zai Kongzhitai Zhong Youyixie Jinggai, Bingqie Women Buneng Baozheng "
+"Suoyou de wenjian doubei zhuanhuan\n"
+".\n"
+"\n"
+"QIng Jiang Qingkuang Baogao Gei Tuandui."
+
+#: engines/pegasus/pegasus.cpp:714
+msgid "Invalid save file name"
+msgstr "Wuxiao Baocun Wenjianming"
+
+#: engines/pegasus/pegasus.cpp:2507
+msgid "Up/Zoom In/Move Forward/Open Doors"
+msgstr "Xiangshang/fangda/Qianjin/Kaimen"
+
+#: engines/pegasus/pegasus.cpp:2508
+msgid "Down/Zoom Out"
+msgstr "Xiangxia/Suoxiao"
+
+#: engines/pegasus/pegasus.cpp:2511
+msgid "Display/Hide Inventory Tray"
+msgstr "Xianshi/Yincang Wupinlan"
+
+#: engines/pegasus/pegasus.cpp:2512
+msgid "Display/Hide Biochip Tray"
+msgstr "Xianshi/Yincang Biochip Lan"
+
+#: engines/pegasus/pegasus.cpp:2513
+msgid "Action/Select"
+msgstr "Dongzuo/Xuanze"
+
+#: engines/pegasus/pegasus.cpp:2514
+msgid "Toggle Center Data Display"
+msgstr "Qiehuan Shuju Zhongxin Xianshi"
+
+#: engines/pegasus/pegasus.cpp:2515
+msgid "Display/Hide Info Screen"
+msgstr "Xianshi/Yincang Xinxi Pingmu"
+
+#: engines/pegasus/pegasus.cpp:2516
+msgid "Display/Hide Pause Menu"
+msgstr "Xianshi/Yincang Zanting Caidan"
+
+#: engines/queen/detection.cpp:56
+msgid "Alternative intro"
+msgstr "QIta Jieshao"
+
+#: engines/queen/detection.cpp:57
+msgid "Use an alternative game intro (CD version only)"
+msgstr "Shiyong Qita Youxi Jieshao (Jin CD Ban)"
+
+#: engines/sci/detection.cpp:374
+msgid "Skip EGA dithering pass (full color backgrounds)"
+msgstr "Tiaoguo EGA Doudong (quancai Beijing)"
+
+#: engines/sci/detection.cpp:375
+msgid "Skip dithering pass in EGA games, graphics are shown with full colors"
+msgstr "tiaoguo EGA Youxi Zhong de Doudong, Tuxiang Yi Quancai Xianshi"
+
+#: engines/sci/detection.cpp:384
+msgid "Enable high resolution graphics"
+msgstr "QIyong Gaofenbianlv Tu"
+
+#: engines/sci/detection.cpp:385
+msgid "Enable high resolution graphics/content"
+msgstr "Qiyong Gaofenbianlv Tubian/Neirong"
+
+#: engines/sci/detection.cpp:394
+msgid "Prefer digital sound effects"
+msgstr "Youxianshiyong Shuzi Yinxiao"
+
+#: engines/sci/detection.cpp:395
+msgid "Prefer digital sound effects instead of synthesized ones"
+msgstr "Youxian SHiyong shuzi YInxiao, er fei Hecheng"
+
+#: engines/sci/detection.cpp:414
+msgid "Use IMF/Yamaha FB-01 for MIDI output"
+msgstr "Shiyong IMF/yamaha Fb-01 Huo MIDI shuchu"
+
+#: engines/sci/detection.cpp:415
+msgid ""
+"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
+"output"
+msgstr ""
+"Shiyong IBM Music Feature Ka Huozhe Yamaha FB-01 FM hecheng Mokuai zuowei "
+"MIDI shuchu"
+
+#: engines/sci/detection.cpp:425
+msgid "Use CD audio"
+msgstr "Shiyong CD YInpin"
+
+#: engines/sci/detection.cpp:426
+msgid "Use CD audio instead of in-game audio, if available"
+msgstr "Shiyong CD Yinpin erfei Youxinei Yinpin (ruguo keyong)"
+
+#: engines/sci/detection.cpp:436
+msgid "Use Windows cursors"
+msgstr "Shiyong WIndows Guangbiao"
+
+#: engines/sci/detection.cpp:437
+msgid ""
+"Use the Windows cursors (smaller and monochrome) instead of the DOS ones"
+msgstr "Shiyong Windows Guangbiao (gengxiao Danse) erfei DOS Guangbiao"
+
+#: engines/sci/detection.cpp:447
+msgid "Use silver cursors"
+msgstr "Shiyong Yinse Guangbiao"
+
+#: engines/sci/detection.cpp:448
+msgid ""
+"Use the alternate set of silver cursors, instead of the normal golden ones"
+msgstr "Shiyong Qita Yinse Guangbiao"
+
+#: engines/scumm/dialogs.cpp:176
+#, c-format
+msgid "Insert Disk %c and Press Button to Continue."
+msgstr "Charu Guangpan %c Bing An Anniu YI jixu"
+
+#: engines/scumm/dialogs.cpp:177
+#, c-format
+msgid "Unable to Find %s, (%c%d) Press Button."
+msgstr "Wufa zhaodao %s, (%c%d) Qing an anniu."
+
+#: engines/scumm/dialogs.cpp:178
+#, c-format
+msgid "Error reading disk %c, (%c%d) Press Button."
+msgstr "Duqu Guangpan %c Cuowu, (%c%d) Qing An Anniu."
+
+#: engines/scumm/dialogs.cpp:179
+msgid "Game Paused. Press SPACE to Continue."
+msgstr "Youxi Zanting. An Kongge Yi jixu."
+
+#. 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'
+#: engines/scumm/dialogs.cpp:183
+msgid "Are you sure you want to restart? (Y/N)Y"
+msgstr "NinQueding Yao Chongqi ma? (Y/N)Y"
+
+#. 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)Y"
+msgstr "NinQueding Yao Tuichu Ma? (Y/N)Y"
+
+#: engines/scumm/dialogs.cpp:190
+msgid "Play"
+msgstr "Kaishi"
+
+#: engines/scumm/dialogs.cpp:194
+msgid "Insert save/load game disk"
+msgstr "Charu Cundang/Duqu youxi Guangpan"
+
+#: engines/scumm/dialogs.cpp:195
+msgid "You must enter a name"
+msgstr "Nin bixu Shuru Yige Mingcheng"
+
+#: engines/scumm/dialogs.cpp:196
+msgid "The game was NOT saved (disk full?)"
+msgstr "Youxi Meiyou Baocun (Cipan Kongjian YIman?)"
+
+#: engines/scumm/dialogs.cpp:197
+msgid "The game was NOT loaded"
+msgstr "Youxi Meiyou Jiazai"
+
+#: engines/scumm/dialogs.cpp:198
+#, c-format
+msgid "Saving '%s'"
+msgstr "Baocun '%s'"
+
+#: engines/scumm/dialogs.cpp:199
+#, c-format
+msgid "Loading '%s'"
+msgstr "Zairu '%s'"
+
+#: engines/scumm/dialogs.cpp:200
+msgid "Name your SAVE game"
+msgstr "Wei baocun Youxi Qiming"
+
+#: engines/scumm/dialogs.cpp:201
+msgid "Select a game to LOAD"
+msgstr "Qing Xuanze Yige Youxi Jiazai"
+
+#: engines/scumm/dialogs.cpp:202
+msgid "Game title)"
+msgstr "Youxi Biaoti)"
+
+#. I18N: Previous page button
+#: engines/scumm/dialogs.cpp:288
+msgid "~P~revious"
+msgstr "~P~Shangyige"
+
+#. I18N: Next page button
+#: engines/scumm/dialogs.cpp:290
+msgid "~N~ext"
+msgstr "~N~Xiayige"
+
+#: engines/scumm/dialogs.cpp:602
+msgid "Speech Only"
+msgstr "Jin Yuyin"
+
+#: engines/scumm/dialogs.cpp:603
+msgid "Speech and Subtitles"
+msgstr "Yuyin he Zimu"
+
+#: engines/scumm/dialogs.cpp:604
+msgid "Subtitles Only"
+msgstr "Jin Zimu"
+
+#: engines/scumm/dialogs.cpp:612
+msgctxt "lowres"
+msgid "Speech & Subs"
+msgstr "Yuyin He Zimu"
+
+#: engines/scumm/dialogs.cpp:658
+msgid "Select a Proficiency Level."
+msgstr "Qing Xuanze Shulian Dengji"
+
+#: engines/scumm/dialogs.cpp:660
+msgid "Refer to your Loom(TM) manual for help."
+msgstr "Qingchayue Loom(TM) Shouce Huoqu Bangzhu."
+
+#: engines/scumm/dialogs.cpp:664
+msgid "Practice"
+msgstr "Lianxi"
+
+#: engines/scumm/dialogs.cpp:665
+msgid "Expert"
+msgstr "Zhuanjia"
+
+#: engines/scumm/help.cpp:74
+msgid "Common keyboard commands:"
+msgstr "Changyong Jianpan Mingling:"
+
+#: engines/scumm/help.cpp:75
+msgid "Save / Load dialog"
+msgstr "Baocun/Zairu Duihua"
+
+#: engines/scumm/help.cpp:77
+msgid "Skip line of text"
+msgstr "Tiaoguo cihang wenben"
+
+#: engines/scumm/help.cpp:78
+msgid "Esc"
+msgstr "Esc"
+
+#: engines/scumm/help.cpp:78
+msgid "Skip cutscene"
+msgstr "Tiaoguo Guochang"
+
+#: engines/scumm/help.cpp:79
+msgid "Space"
+msgstr "Kongge"
+
+#: engines/scumm/help.cpp:79
+msgid "Pause game"
+msgstr "Zanting Youxi"
+
+#: engines/scumm/help.cpp:80 engines/scumm/help.cpp:85
+#: engines/scumm/help.cpp:96 engines/scumm/help.cpp:97
+#: engines/scumm/help.cpp:98 engines/scumm/help.cpp:99
+#: engines/scumm/help.cpp:100 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+msgid "Ctrl"
+msgstr "Ctrl"
+
+#: engines/scumm/help.cpp:80
+msgid "Load game state 1-10"
+msgstr "Zairu Youxi Cundang 1-10"
+
+#: engines/scumm/help.cpp:81 engines/scumm/help.cpp:85
+#: engines/scumm/help.cpp:87 engines/scumm/help.cpp:101
+#: engines/scumm/help.cpp:102 engines/scumm/help.cpp:103
+msgid "Alt"
+msgstr "Alt"
+
+#: engines/scumm/help.cpp:81
+msgid "Save game state 1-10"
+msgstr "Baocun Youxi Cundang 1-10"
+
+#: engines/scumm/help.cpp:87 engines/scumm/help.cpp:90
+msgid "Enter"
+msgstr "Huiche"
+
+#: engines/scumm/help.cpp:88
+msgid "Music volume up / down"
+msgstr "Yinyue YInliang Gao/Di"
+
+#: engines/scumm/help.cpp:89
+msgid "Text speed slower / faster"
+msgstr "Wenben Sudu Man/Kuai"
+
+#: engines/scumm/help.cpp:90
+msgid "Simulate left mouse button"
+msgstr "Moni Shubiao Zuojian"
+
+#: engines/scumm/help.cpp:91
+msgid "Tab"
+msgstr "Tab"
+
+#: engines/scumm/help.cpp:91
+msgid "Simulate right mouse button"
+msgstr "Moni Shubiao Youjian"
+
+#: engines/scumm/help.cpp:94
+msgid "Special keyboard commands:"
+msgstr "Jianpan Teshu MIngling:"
+
+#: engines/scumm/help.cpp:95
+msgid "Show / Hide console"
+msgstr "Xianshi/YIncang Kongzhitai"
+
+#: engines/scumm/help.cpp:96
+msgid "Start the debugger"
+msgstr "Yunxing Tiaoshiqi"
+
+#: engines/scumm/help.cpp:97
+msgid "Show memory consumption"
+msgstr "Xianshi Neicun xioahao"
+
+#: engines/scumm/help.cpp:98
+msgid "Run in fast mode (*)"
+msgstr "zai Kuaisu Moshi Zhong YUnxing (*)"
+
+#: engines/scumm/help.cpp:99
+msgid "Run in really fast mode (*)"
+msgstr "Zai Chaokuai Moshi XIa yunxing(*)"
+
+#: engines/scumm/help.cpp:100
+msgid "Toggle mouse capture"
+msgstr "Qiehuan Shubiao buzhuo"
+
+#: engines/scumm/help.cpp:101
+msgid "Switch between graphics filters"
+msgstr "QIehuan Tuxiang Guolvqi"
+
+#: engines/scumm/help.cpp:102
+msgid "Increase / Decrease scale factor"
+msgstr "Zengjia / Jianshao suofang Yinzi"
+
+#: engines/scumm/help.cpp:103
+msgid "Toggle aspect-ratio correction"
+msgstr "Qiehuan bili Jiaozheng"
+
+#: engines/scumm/help.cpp:108
+msgid "* Note that using ctrl-f and"
+msgstr "* Zhuyi Ctrl-f He"
+
+#: engines/scumm/help.cpp:109
+msgid " ctrl-g are not recommended"
+msgstr " Ctrl-g BIngbu zhichi"
+
+#: engines/scumm/help.cpp:110
+msgid " since they may cause crashes"
+msgstr " Yinwei Keneng zaocheng cuowu"
+
+#: engines/scumm/help.cpp:111
+msgid " or incorrect game behavior."
+msgstr " Huo Buzhengque de Youxi xingwei"
+
+#: engines/scumm/help.cpp:115
+msgid "Spinning drafts on the keyboard:"
+msgstr "Jianpanshang xuanzhuan Zaogao:"
+
+#: engines/scumm/help.cpp:117
+msgid "Main game controls:"
+msgstr "Youxi zhuyao Kongzhi:"
+
+#: engines/scumm/help.cpp:122 engines/scumm/help.cpp:137
+#: engines/scumm/help.cpp:162
+msgid "Push"
+msgstr "Tui"
+
+#: engines/scumm/help.cpp:123 engines/scumm/help.cpp:138
+#: engines/scumm/help.cpp:163
+msgid "Pull"
+msgstr "La"
+
+#: engines/scumm/help.cpp:124 engines/scumm/help.cpp:139
+#: engines/scumm/help.cpp:164 engines/scumm/help.cpp:198
+#: engines/scumm/help.cpp:208
+msgid "Give"
+msgstr "gei"
+
+#: engines/scumm/help.cpp:125 engines/scumm/help.cpp:140
+#: engines/scumm/help.cpp:165 engines/scumm/help.cpp:191
+#: engines/scumm/help.cpp:209
+msgid "Open"
+msgstr "Dakai"
+
+#: engines/scumm/help.cpp:127
+msgid "Go to"
+msgstr "Qudao"
+
+#: engines/scumm/help.cpp:128
+msgid "Get"
+msgstr "Dedao"
+
+#: engines/scumm/help.cpp:129 engines/scumm/help.cpp:153
+#: engines/scumm/help.cpp:171 engines/scumm/help.cpp:199
+#: engines/scumm/help.cpp:214 engines/scumm/help.cpp:225
+#: engines/scumm/help.cpp:251
+msgid "Use"
+msgstr "Shiyong"
+
+#: engines/scumm/help.cpp:130 engines/scumm/help.cpp:142
+msgid "Read"
+msgstr "du"
+
+#: engines/scumm/help.cpp:131 engines/scumm/help.cpp:148
+msgid "New kid"
+msgstr "Xin kid"
+
+#: engines/scumm/help.cpp:132 engines/scumm/help.cpp:154
+#: engines/scumm/help.cpp:172
+msgid "Turn on"
+msgstr "DaKai"
+
+#: engines/scumm/help.cpp:133 engines/scumm/help.cpp:155
+#: engines/scumm/help.cpp:173
+msgid "Turn off"
+msgstr "Guanbi"
+
+#: engines/scumm/help.cpp:143 engines/scumm/help.cpp:168
+#: engines/scumm/help.cpp:195
+msgid "Walk to"
+msgstr "Zouxiang"
+
+#: engines/scumm/help.cpp:144 engines/scumm/help.cpp:169
+#: engines/scumm/help.cpp:196 engines/scumm/help.cpp:211
+#: engines/scumm/help.cpp:228
+msgid "Pick up"
+msgstr "Jianqi"
+
+#: engines/scumm/help.cpp:145 engines/scumm/help.cpp:170
+msgid "What is"
+msgstr "Shenme"
+
+#: engines/scumm/help.cpp:147
+msgid "Unlock"
+msgstr "Jiesuo"
+
+#: engines/scumm/help.cpp:150
+msgid "Put on"
+msgstr "Chuanshang"
+
+#: engines/scumm/help.cpp:151
+msgid "Take off"
+msgstr "Tuoxia"
+
+#: engines/scumm/help.cpp:157
+msgid "Fix"
+msgstr "Xiufu"
+
+#: engines/scumm/help.cpp:159
+msgid "Switch"
+msgstr "Qiehuan"
+
+#: engines/scumm/help.cpp:167 engines/scumm/help.cpp:229
+msgid "Look"
+msgstr "Kan"
+
+#: engines/scumm/help.cpp:174 engines/scumm/help.cpp:224
+msgid "Talk"
+msgstr "Shuohua"
+
+#: engines/scumm/help.cpp:175
+msgid "Travel"
+msgstr "LvXing"
+
+#: engines/scumm/help.cpp:176
+msgid "To Henry / To Indy"
+msgstr "Gei Henry/ Gei Indy"
+
+#. I18N: These are different musical notes
+#: engines/scumm/help.cpp:180
+msgid "play C minor on distaff"
+msgstr "Yanzou C Xiaodiao"
+
+#: engines/scumm/help.cpp:181
+msgid "play D on distaff"
+msgstr "Yanzou D"
+
+#: engines/scumm/help.cpp:182
+msgid "play E on distaff"
+msgstr "Yanzou E"
+
+#: engines/scumm/help.cpp:183
+msgid "play F on distaff"
+msgstr "Yanozu F"
+
+#: engines/scumm/help.cpp:184
+msgid "play G on distaff"
+msgstr "Yanzou G"
+
+#: engines/scumm/help.cpp:185
+msgid "play A on distaff"
+msgstr "Yanzou A"
+
+#: engines/scumm/help.cpp:186
+msgid "play B on distaff"
+msgstr "Yanzou B"
+
+#: engines/scumm/help.cpp:187
+msgid "play C major on distaff"
+msgstr "Yanzou C Dadiao"
+
+#: engines/scumm/help.cpp:193 engines/scumm/help.cpp:215
+msgid "puSh"
+msgstr "Tui"
+
+#: engines/scumm/help.cpp:194 engines/scumm/help.cpp:216
+msgid "pull (Yank)"
+msgstr "La"
+
+#: engines/scumm/help.cpp:197 engines/scumm/help.cpp:213
+#: engines/scumm/help.cpp:249
+msgid "Talk to"
+msgstr "Shuohua"
+
+#: engines/scumm/help.cpp:200 engines/scumm/help.cpp:212
+msgid "Look at"
+msgstr "Kanxiang"
+
+#: engines/scumm/help.cpp:201
+msgid "turn oN"
+msgstr "Dakai"
+
+#: engines/scumm/help.cpp:202
+msgid "turn oFf"
+msgstr "Guanbi"
+
+#: engines/scumm/help.cpp:218
+msgid "KeyUp"
+msgstr "TaiqiAnjian"
+
+#: engines/scumm/help.cpp:218
+msgid "Highlight prev dialogue"
+msgstr "Gaoliang Zhiqian Duihua"
+
+#: engines/scumm/help.cpp:219
+msgid "KeyDown"
+msgstr "AnxiaAnjian"
+
+#: engines/scumm/help.cpp:219
+msgid "Highlight next dialogue"
+msgstr "Gaoliang Zhihou Duihua"
+
+#: engines/scumm/help.cpp:223
+msgid "Walk"
+msgstr "Zou"
+
+#: engines/scumm/help.cpp:226 engines/scumm/help.cpp:235
+#: engines/scumm/help.cpp:242 engines/scumm/help.cpp:250
+msgid "Inventory"
+msgstr "Wupin"
+
+#: engines/scumm/help.cpp:227
+msgid "Object"
+msgstr "Dongxi"
+
+#: engines/scumm/help.cpp:230
+msgid "Black and White / Color"
+msgstr "Heibai / Caise"
+
+#: engines/scumm/help.cpp:233
+msgid "Eyes"
+msgstr "yanjing"
+
+#: engines/scumm/help.cpp:234
+msgid "Tongue"
+msgstr "Shetou"
+
+#: engines/scumm/help.cpp:236
+msgid "Punch"
+msgstr "Quantou"
+
+#: engines/scumm/help.cpp:237
+msgid "Kick"
+msgstr "Ti"
+
+#: engines/scumm/help.cpp:240 engines/scumm/help.cpp:248
+msgid "Examine"
+msgstr "Jiancha"
+
+#: engines/scumm/help.cpp:241
+msgid "Regular cursor"
+msgstr "Putong Guangbiao"
+
+#. I18N: Comm is a communication device
+#: engines/scumm/help.cpp:244
+msgid "Comm"
+msgstr "Tongxin"
+
+#: engines/scumm/help.cpp:247
+msgid "Save / Load / Options"
+msgstr "Baocun / Zairu / Xuanxiang"
+
+#: engines/scumm/help.cpp:256
+msgid "Other game controls:"
+msgstr "QIta youxi Kongzhi:"
+
+#: engines/scumm/help.cpp:258 engines/scumm/help.cpp:268
+msgid "Inventory:"
+msgstr "Wupin:"
+
+#: engines/scumm/help.cpp:259 engines/scumm/help.cpp:275
+msgid "Scroll list up"
+msgstr "LIebiao Shanghua"
+
+#: engines/scumm/help.cpp:260 engines/scumm/help.cpp:276
+msgid "Scroll list down"
+msgstr "LIebiao Xiahua"
+
+#: engines/scumm/help.cpp:261 engines/scumm/help.cpp:269
+msgid "Upper left item"
+msgstr "Zuoshang Wupin"
+
+#: engines/scumm/help.cpp:262 engines/scumm/help.cpp:271
+msgid "Lower left item"
+msgstr "Zuoxia Wupin"
+
+#: engines/scumm/help.cpp:263 engines/scumm/help.cpp:272
+msgid "Upper right item"
+msgstr "Youshang Wupin"
+
+#: engines/scumm/help.cpp:264 engines/scumm/help.cpp:274
+msgid "Lower right item"
+msgstr "Youxia Wupin"
+
+#: engines/scumm/help.cpp:270
+msgid "Middle left item"
+msgstr "Zhongzuo Wupin"
+
+#: engines/scumm/help.cpp:273
+msgid "Middle right item"
+msgstr "Zhongyou Wupin"
+
+#: engines/scumm/help.cpp:280 engines/scumm/help.cpp:285
+msgid "Switching characters:"
+msgstr "Qiehuan Juese"
+
+#: engines/scumm/help.cpp:282
+msgid "Second kid"
+msgstr "Dierge Kid"
+
+#: engines/scumm/help.cpp:283
+msgid "Third kid"
+msgstr "Disange Kid"
+
+#: engines/scumm/help.cpp:292
+msgid "Toggle Inventory/IQ Points display"
+msgstr "Qiehuan Wupin/IQ Dian Xianshi"
+
+#: engines/scumm/help.cpp:293
+msgid "Toggle Keyboard/Mouse Fighting (*)"
+msgstr "Qiehuan JInapan/Shubiao Zhandou (*)"
+
+#: engines/scumm/help.cpp:295
+msgid "* Keyboard Fighting is always on,"
+msgstr "* Jianpan Zhandou zongshi Kaiqi,"
+
+#: engines/scumm/help.cpp:296
+msgid " so despite the in-game message this"
+msgstr " Suoyi Hulue youxi nei xinxi"
+
+#: engines/scumm/help.cpp:297
+msgid " actually toggles Mouse Fighting Off/On"
+msgstr " Zhe shiji shang shi Zai qiehuan Shubiao Zhandou de Kaiguan"
+
+#: engines/scumm/help.cpp:304
+msgid "Fighting controls (numpad):"
+msgstr "Zhandou Kongzhi (zhuzijianpan):"
+
+#: engines/scumm/help.cpp:305 engines/scumm/help.cpp:306
+#: engines/scumm/help.cpp:307
+msgid "Step back"
+msgstr "Shangyibu"
+
+#: engines/scumm/help.cpp:308
+msgid "Block high"
+msgstr "Zudang Gaochu"
+
+#: engines/scumm/help.cpp:309
+msgid "Block middle"
+msgstr "Zudang Zhongjian"
+
+#: engines/scumm/help.cpp:310
+msgid "Block low"
+msgstr "Zudang Dichu"
+
+#: engines/scumm/help.cpp:311
+msgid "Punch high"
+msgstr "Quanda Gaochu"
+
+#: engines/scumm/help.cpp:312
+msgid "Punch middle"
+msgstr "Quanda Zhongjian"
+
+#: engines/scumm/help.cpp:313
+msgid "Punch low"
+msgstr "Quanda Dichu"
+
+#: engines/scumm/help.cpp:315
+msgid "Sucker punch"
+msgstr "Sucker Punch"
+
+#: engines/scumm/help.cpp:318
+msgid "These are for Indy on left."
+msgstr "Weile zai Zuobian de Indy"
+
+#: engines/scumm/help.cpp:319
+msgid "When Indy is on the right,"
+msgstr "Dnag Indy Zai Youbian Shi,"
+
+#: engines/scumm/help.cpp:320
+msgid "7, 4, and 1 are switched with"
+msgstr "7, 4 He 1 Fenbie keyi Yong"
+
+#: engines/scumm/help.cpp:321
+msgid "9, 6, and 3, respectively."
+msgstr "9, 6, 3 Laiqiehuan."
+
+#: engines/scumm/help.cpp:328
+msgid "Biplane controls (numpad):"
+msgstr "Shuangmian Kongzhi (shuzijianpan):"
+
+#: engines/scumm/help.cpp:329
+msgid "Fly to upper left"
+msgstr "Feiwang Zuoshang"
+
+#: engines/scumm/help.cpp:330
+msgid "Fly to left"
+msgstr "Feiwang Zuobian"
+
+#: engines/scumm/help.cpp:331
+msgid "Fly to lower left"
+msgstr "Feiwang Zuoxia"
+
+#: engines/scumm/help.cpp:332
+msgid "Fly upwards"
+msgstr "Xinagshang Fei"
+
+#: engines/scumm/help.cpp:333
+msgid "Fly straight"
+msgstr "Zhifei"
+
+#: engines/scumm/help.cpp:334
+msgid "Fly down"
+msgstr "Xiangxia Fei"
+
+#: engines/scumm/help.cpp:335
+msgid "Fly to upper right"
+msgstr "Feiwang YouShang"
+
+#: engines/scumm/help.cpp:336
+msgid "Fly to right"
+msgstr "Feiwang Youbian"
+
+#: engines/scumm/help.cpp:337
+msgid "Fly to lower right"
+msgstr "Feiwang Youxia"
+
+#: engines/scumm/input.cpp:580
+msgid "Snap scroll on"
+msgstr "Snap hundong kai"
+
+#: engines/scumm/input.cpp:582
+msgid "Snap scroll off"
+msgstr "Snap Gundong Guan"
+
+#: engines/scumm/input.cpp:595
+msgid "Music volume: "
+msgstr "Yinyue Yinliang:"
+
+#: engines/scumm/input.cpp:612
+msgid "Subtitle speed: "
+msgstr "Zimu Sudu:"
+
+#: engines/scumm/scumm.cpp:1832
+#, c-format
+msgid ""
+"Native MIDI support requires the Roland Upgrade from LucasArts,\n"
+"but %s is missing. Using AdLib instead."
+msgstr ""
+"Bendi MIDI Zhichi Xuyao Cong LucasArts Shengji Zhi Roland,\n"
+"Dnahsi %s meiyou zhaodao. Shiyong AdLib."
+
+#: engines/scumm/scumm.cpp:2644
+msgid ""
+"Usually, Maniac Mansion would start now. But for that to work, the game "
+"files for Maniac Mansion have to be in the 'Maniac' directory inside the "
+"Tentacle game directory, and the game has to be added to ScummVM."
+msgstr ""
+"Tongchang, Maniac mansion Huizai XIanzai kaishi. Raner, Manian mansion De "
+"youxi Wenjian Xuyao zai 'maniac'Mulu Nei , weiyu Tentacle Youxi Mulu, Ci "
+"Youxi Xuyao Bei tianjia dao ScummVM Zhong."
+
+#: engines/scumm/players/player_v3m.cpp:129
+msgid ""
+"Could not find the 'Loom' Macintosh executable to read the\n"
+"instruments from. Music will be disabled."
+msgstr ""
+"Wufa Zhaodao 'Loom' Macintosh Chengxu lai\n"
+" Duru Yinyue. Yinyue Huibei Jinyong."
+
+#: 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 ""
+"Wufa Zhaodao 'monkey Island' Macintosh Chengxu lai Duru YInyue. yinyue "
+"Huibei Jinyong."
+
+#: engines/sherlock/detection.cpp:71
+msgid "Use original savegame dialog"
+msgstr "Shiyong Yuanshi Youxi baocun Duihuakuang"
+
+#: engines/sherlock/detection.cpp:72
+msgid ""
+"Files button in-game shows original savegame dialog rather than the ScummVM "
+"menu"
+msgstr ""
+"YouxiNei wenjian Anniu shiyong Yuanshi Youxi Duihuakuang Erfei ScummVM Caidan"
+
+#: engines/sherlock/detection.cpp:81
+msgid "Pixellated scene transitions"
+msgstr "Xiangsuhua Changjing Qiehuan"
+
+#: engines/sherlock/detection.cpp:82
+msgid "When changing scenes, a randomized pixel transition is done"
+msgstr "Dang Qiehuan Changjingshi, Shiyong Suiji Xiangsu zhuanhuan"
+
+#: engines/sherlock/detection.cpp:91
+msgid "Don't show hotspots when moving mouse"
+msgstr "Dnag Yidong shubiao Shi Buyao Xianshi Redian"
+
+#: engines/sherlock/detection.cpp:92
+msgid ""
+"Only show hotspot names after you actually click on a hotspot or action "
+"button"
+msgstr "JInzai Dianji Redian Huo Dongzuo Anjianhou Xianshi Redianming"
+
+#: engines/sherlock/detection.cpp:101
+msgid "Show character portraits"
+msgstr "Xianshi Juese Huaxiang"
+
+#: engines/sherlock/detection.cpp:102
+msgid "Show portraits for the characters when conversing"
+msgstr "Jiaotan Shi Xianshi Juese Huaxiang"
+
+#: engines/sherlock/detection.cpp:111
+msgid "Slide dialogs into view"
+msgstr "Huadon Duigua dao SHituzhong"
+
+#: engines/sherlock/detection.cpp:112
+msgid "Slide UI dialogs into view, rather than simply showing them immediately"
+msgstr "Jiang UI Duihuakuang Huaru Shitu, Erfei Turan Chuxian"
+
+#: engines/sherlock/detection.cpp:121
+msgid "Transparent windows"
+msgstr "Touming Chuangkou"
+
+#: engines/sherlock/detection.cpp:122
+msgid "Show windows with a partially transparent background"
+msgstr "Xianshi Diayou Bantouming Beijing de Chuangkou"
+
+#: engines/sky/compact.cpp:130
+msgid ""
+"Unable to find \"sky.cpt\" file!\n"
+"Please download it from www.scummvm.org"
+msgstr ""
+"Wufa Zhaodao \"sky.cpt\" Wenjian\n"
+"Qing Cong www.cummvm.org Xiazai"
+
+#: engines/sky/compact.cpp:141
+msgid ""
+"The \"sky.cpt\" file has an incorrect size.\n"
+"Please (re)download it from www.scummvm.org"
+msgstr ""
+"Wenjian \"sky.cpt\" Chicun Cuowu.\n"
+"Qing Cong www.scummvm.org Chongxin Xiazai"
+
+#: engines/sky/detection.cpp:44
+msgid "Floppy intro"
+msgstr "Ruanpan Jieshao"
+
+#: engines/sky/detection.cpp:45
+msgid "Use the floppy version's intro (CD version only)"
+msgstr "Shiyong Ruanpan Banben JIeshao (jin CD banben)"
+
+#: engines/sword1/animation.cpp:524
+#, c-format
+msgid "PSX stream cutscene '%s' cannot be played in paletted mode"
+msgstr "PSX liu Changjing '%s' Wufa zai Tiaosiban Moshi xia Bofang"
+
+#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
+msgid "DXA cutscenes found but ScummVM has been built without zlib"
+msgstr "Zhaodao DXA Guochang Danshi ScummVM Meiyou yu Zlib bianyi"
+
+#: engines/sword1/animation.cpp:561 engines/sword2/animation.cpp:461
+msgid ""
+"MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"
+msgstr "MPEG-2 Guocheng Zhaodao Dnashi ScummVM Meiyou He MPEG-2 Zhichi Bianyi"
+
+#: engines/sword1/animation.cpp:568 engines/sword2/animation.cpp:470
+#, c-format
+msgid "Cutscene '%s' not found"
+msgstr "Guochang '%s' Weizhaodao"
+
+#: engines/sword1/control.cpp:863
+msgid ""
+"ScummVM found that you have old savefiles for Broken Sword 1 that should be "
+"converted.\n"
+"The old save game format is no longer supported, so you will not be able to "
+"load your games if you don't convert them.\n"
+"\n"
+"Press OK to convert them now, otherwise you will be asked again the next "
+"time you start the game.\n"
+msgstr ""
+"ScummVM Zhaodaole Zhiqian De Broken Sword 1 Cundang, qie YInggai Bei "
+"zhuanhuan.\n"
+"Zhiqian de cundang Geshi BUzai Zhichi, Nin Bixu Xianzhuanhuan Caineng Duqu "
+"Cundang\n"
+"Dianji Queding Lia zhuanhuancundang, Fouze NIn Huizai Xiaci Kaishi Youxi Shi "
+"bei Zaici Tishi\n"
+
+#: engines/sword1/control.cpp:1232
+#, c-format
+msgid ""
+"Target new save game already exists!\n"
+"Would you like to keep the old save game (%s) or the new one (%s)?\n"
+msgstr ""
+"Mubiao Xin Cundang Yijing Cunzai!\n"
+"Niyao Baocun jiude Cundang (%s) Haishi Xinde(%s)?\n"
+
+#: engines/sword1/control.cpp:1235
+msgid "Keep the old one"
+msgstr "Baoliu Jiude"
+
+#: engines/sword1/control.cpp:1235
+msgid "Keep the new one"
+msgstr "Baoliu Xinde"
+
+#: engines/sword1/logic.cpp:1633
+msgid "This is the end of the Broken Sword 1 Demo"
+msgstr "Zheshi Broken Sword 1 Demo de Jiewei"
+
+#: engines/sword2/animation.cpp:425
+msgid ""
+"PSX cutscenes found but ScummVM has been built without RGB color support"
+msgstr "PSX Guochang zhaodao Danshi ScmummVM Meiyou Zhichi RGB Secai Bianyi"
+
+#: engines/sword2/sword2.cpp:79
+msgid "Show object labels"
+msgstr "Xianshi Wuti Biaoqian"
+
+#: engines/sword2/sword2.cpp:80
+msgid "Show labels for objects on mouse hover"
+msgstr "Dang Shubiao Yishang Shi Xianshi Wuti Biaoqian"
+
+#: engines/teenagent/resources.cpp:95
+msgid ""
+"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
+msgstr ""
+"Zhaobudao 'teenagent.dat' Wenjian. Cong ScummVM wangzhan Shangmian Dedao"
+
+#: engines/teenagent/resources.cpp:116
+msgid ""
+"The teenagent.dat file is compressed and zlib hasn't been included in this "
+"executable. Please decompress it"
+msgstr ""
+"teenagent.dat Wenjian Yibeiyasuo Bingqie zlib Bingmeiyou Zai chengxu Zhong. "
+"Qing jieya."
+
+#: engines/wintermute/detection.cpp:58
+msgid "Show FPS-counter"
+msgstr "Xianshi FPS Jishuqi"
+
+#: engines/wintermute/detection.cpp:59
+msgid "Show the current number of frames per second in the upper left corner"
+msgstr "Zai Zuoshangjiao Xianshi Xianzai Meimiaozhong Zhenshu"
+
+#: engines/zvision/detection_tables.h:52
+msgid "Use the original save/load screens instead of the ScummVM interface"
+msgstr "Shiyong Yuanshi baocun/zairu Pingmu Erfei ScummVM jiemian"
+
+#: engines/zvision/detection_tables.h:61
+msgid "Double FPS"
+msgstr "Shuangbei FPS"
+
+#: engines/zvision/detection_tables.h:62
+msgid "Increase framerate from 30 to 60 FPS"
+msgstr "Zengjia zhenlv cong 30 dao 60 FPS"
+
+#: engines/zvision/detection_tables.h:71
+msgid "Enable Venus"
+msgstr "Qiyong Venus"
+
+#: engines/zvision/detection_tables.h:72
+msgid "Enable the Venus help system"
+msgstr "Qiyong Venus Bangzhu Xitong"
+
+#: engines/zvision/detection_tables.h:81
+msgid "Disable animation while turning"
+msgstr "zhuanxinag shi Jinyong Donghua"
+
+#: engines/zvision/detection_tables.h:82
+msgid "Disable animation while turning in panorama mode"
+msgstr "Quanjing Moshi xia Zhuanxiang shi Jinyong Donghua"
+
+#: engines/zvision/detection_tables.h:91
+msgid "Use high resolution MPEG video"
+msgstr "Shiyong Gaofenbianlv MPEG shipin"
+
+#: engines/zvision/detection_tables.h:92
+msgid "Use MPEG video from the DVD version, instead of lower resolution AVI"
+msgstr "Cong DVD Banben Zhong shiyong MPEG shipin, erfei Difenbianlv AVI"
diff --git a/ports.mk b/ports.mk
index fa380846e1..0eb94264de 100644
--- a/ports.mk
+++ b/ports.mk
@@ -223,6 +223,8 @@ ifneq ($(BACKEND), iphone)
ifneq ($(BACKEND), ios7)
# Static libaries, used for the scummvm-static and iphone targets
OSX_STATIC_LIBS := `$(SDLCONFIG) --static-libs`
+# With sdl2-config we don't always get the OpenGL framework
+OSX_STATIC_LIBS += -framework OpenGL
endif
endif
@@ -341,7 +343,7 @@ osxsnap: bundle
mkdir ScummVM-snapshot/doc/se
cp $(srcdir)/doc/se/LasMig ./ScummVM-snapshot/doc/se/LasMig
cp $(srcdir)/doc/se/Snabbstart ./ScummVM-snapshot/doc/se/Snabbstart
- /Developer/Tools/SetFile -t ttro -c ttxt ./ScummVM-snapshot/*
+ $(XCODETOOLSPATH)/SetFile -t ttro -c ttxt ./ScummVM-snapshot/*
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/cz/*
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/da/*
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/de/*
@@ -350,11 +352,11 @@ osxsnap: bundle
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/it/*
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/no-nb/*
xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/se/*
- /Developer/Tools/CpMac -r $(bundle_name) ./ScummVM-snapshot/
+ $(XCODETOOLSPATH)/CpMac -r $(bundle_name) ./ScummVM-snapshot/
cp $(srcdir)/dists/macosx/DS_Store ./ScummVM-snapshot/.DS_Store
cp $(srcdir)/dists/macosx/background.jpg ./ScummVM-snapshot/background.jpg
- /Developer/Tools/SetFile -a V ./ScummVM-snapshot/.DS_Store
- /Developer/Tools/SetFile -a V ./ScummVM-snapshot/background.jpg
+ $(XCODETOOLSPATH)/SetFile -a V ./ScummVM-snapshot/.DS_Store
+ $(XCODETOOLSPATH)/SetFile -a V ./ScummVM-snapshot/background.jpg
hdiutil create -ov -format UDZO -imagekey zlib-level=9 -fs HFS+ \
-srcfolder ScummVM-snapshot \
-volname "ScummVM" \
diff --git a/test/common/array.h b/test/common/array.h
index f0027ec201..64354abc00 100644
--- a/test/common/array.h
+++ b/test/common/array.h
@@ -44,6 +44,48 @@ class ArrayTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(iter, array.end());
}
+ void test_erase_iterator() {
+ Common::Array<int> array;
+ Common::Array<int>::iterator iter;
+
+ // Fill the array with some random data
+ array.push_back(17);
+ array.push_back(33);
+ array.push_back(-11);
+
+ iter = array.begin();
+ ++iter;
+
+ iter = array.erase(iter);
+ TS_ASSERT_DIFFERS(iter, array.end());
+ TS_ASSERT_EQUALS(*iter, -11);
+ TS_ASSERT_EQUALS(array.size(), (unsigned int)2);
+ TS_ASSERT_EQUALS(array[0], 17);
+ TS_ASSERT_EQUALS(array[1], -11);
+ }
+
+ void test_insert_iterator() {
+ Common::Array<int> array;
+ Common::Array<int>::iterator iter;
+
+ // Fill the array with some random data
+ array.push_back(17);
+ array.push_back(33);
+ array.push_back(-11);
+
+ iter = array.begin();
+ ++iter;
+
+ array.insert(iter, 99);
+
+ TS_ASSERT_EQUALS(*iter, 99);
+ TS_ASSERT_EQUALS(array.size(), (unsigned int)4);
+ TS_ASSERT_EQUALS(array[0], 17);
+ TS_ASSERT_EQUALS(array[1], 99);
+ TS_ASSERT_EQUALS(array[2], 33);
+ TS_ASSERT_EQUALS(array[3], -11);
+ }
+
void test_direct_access() {
Common::Array<int> array;
diff --git a/test/common/rational.h b/test/common/rational.h
index 46dfc278c7..23d0c10acd 100644
--- a/test/common/rational.h
+++ b/test/common/rational.h
@@ -130,4 +130,15 @@ public:
TS_ASSERT_EQUALS(r1 / 2, Common::Rational(1, 4));
TS_ASSERT_EQUALS(2 / r1, Common::Rational(4, 1));
}
+
+ void test_isOne() {
+ Common::Rational r0(5, 5);
+ Common::Rational r1(1, 2);
+ Common::Rational r2(2, 1);
+ Common::Rational r3(1, 1);
+ TS_ASSERT(r0.isOne());
+ TS_ASSERT(!r1.isOne());
+ TS_ASSERT(!r2.isOne());
+ TS_ASSERT(r3.isOne());
+ }
};
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 324bf65294..49034aad17 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -447,7 +447,9 @@ const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::decodeNextFrame()
}
// Update the edit list, if applicable
- if (endOfCurEdit()) {
+ // FIXME: Add support for playing backwards videos with more than one edit
+ // For now, stay on the first edit for reversed playback
+ if (endOfCurEdit() && !_reversed) {
_curEdit++;
if (atLastEdit())